aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Ludwig <michel.ludwig@gmail.com>2007-08-21 16:37:22 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-17 23:39:37 -0400
commit3169c9b26fffa180bc3bc81dc247df2f4824ee7d (patch)
treec9792c64ae210fa879a42517431761b301599238
parenta4cf976c77ce0865ceaa0f08cc1667538894936c (diff)
V4L/DVB (12788): tm6000: Add initial DVB-T support
Signed-off-by: Michel Ludwig <michel.ludwig@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/tm6000/Makefile5
-rw-r--r--drivers/staging/tm6000/hack.c251
-rw-r--r--drivers/staging/tm6000/hack.h45
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c19
-rw-r--r--drivers/staging/tm6000/tm6000-core.c29
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c303
-rw-r--r--drivers/staging/tm6000/tm6000.h28
7 files changed, 677 insertions, 3 deletions
diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile
index 1efc583c10a4..1fefe057d4e8 100644
--- a/drivers/staging/tm6000/Makefile
+++ b/drivers/staging/tm6000/Makefile
@@ -1,7 +1,10 @@
1tm6000-objs := tm6000-cards.o \ 1tm6000-objs := tm6000-cards.o \
2 tm6000-core.o \ 2 tm6000-core.o \
3 tm6000-i2c.o \ 3 tm6000-i2c.o \
4 tm6000-video.o 4 tm6000-video.o \
5 tm6000-dvb.o \
6 hack.o \
7
5 8
6obj-$(CONFIG_VIDEO_TM6000) += tm6000.o 9obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
7 10
diff --git a/drivers/staging/tm6000/hack.c b/drivers/staging/tm6000/hack.c
new file mode 100644
index 000000000000..87f3f498e8eb
--- /dev/null
+++ b/drivers/staging/tm6000/hack.c
@@ -0,0 +1,251 @@
1
2
3
4
5
6
7/*
8 hack.h - hackish code that needs to be improved (or removed) at a
9 later point
10
11 Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation version 2
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include "hack.h"
28
29#include "tm6000.h"
30
31#include <linux/usb.h>
32
33static inline int tm6000_snd_control_msg(struct tm6000_core *dev, __u8 request, __u16 value, __u16 index, void *data, __u16 size)
34{
35 return tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, request, value, index, data, size);
36}
37
38static int pseudo_zl10353_pll(struct tm6000_core *tm6000_dev, struct dvb_frontend_parameters *p)
39{
40 int ret;
41 u8 *data = kzalloc(50*sizeof(u8), GFP_KERNEL);
42
43printk(KERN_ALERT "should set frequency %u\n", p->frequency);
44printk(KERN_ALERT "and bandwith %u\n", p->u.ofdm.bandwidth);
45
46 if(tm6000_dev->dvb->frontend->ops.tuner_ops.set_params) {
47 tm6000_dev->dvb->frontend->ops.tuner_ops.set_params(tm6000_dev->dvb->frontend, p);
48 }
49 else {
50 printk(KERN_ALERT "pseudo zl10353: couldn't set tuner parameters\n");
51 }
52
53 // init ZL10353
54 data[0] = 0x0b;
55 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x501e, 0x00, data, 0x1);
56 msleep(15);
57 data[0] = 0x80;
58 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x551e, 0x00, data, 0x1);
59 msleep(100);
60 data[0] = 0x01;
61 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0xea1e, 0x00, data, 0x1);
62 msleep(100);
63 data[0] = 0x00;
64 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0xea1e, 0x00, data, 0x1);
65 msleep(15);
66 data[0] = 0x1c;
67 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x561e, 0x00, data, 0x1);
68 msleep(15);
69 data[0] = 0x40;
70 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x5e1e, 0x00, data, 0x1);
71 msleep(15);
72 data[0] = 0x36;
73 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x641e, 0x00, data, 0x1);
74 msleep(15);
75 data[0] = 0x67;
76 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x651e, 0x00, data, 0x1);
77 msleep(15);
78 data[0] = 0xe5;
79 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x661e, 0x00, data, 0x1);
80 msleep(15);
81 data[0] = 0x19;
82 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6c1e, 0x00, data, 0x1);
83 msleep(15);
84 data[0] = 0xe9;
85 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6d1e, 0x00, data, 0x1);
86 msleep(15);
87 data[0] = 0x44;
88 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x511e, 0x00, data, 0x1);
89 msleep(15);
90 data[0] = 0x46;
91 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x521e, 0x00, data, 0x1);
92 msleep(15);
93 data[0] = 0x15;
94 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x531e, 0x00, data, 0x1);
95 msleep(15);
96 data[0] = 0x0f;
97 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x541e, 0x00, data, 0x1);
98 msleep(15);
99 data[0] = 0x75;
100 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x5c1e, 0x00, data, 0x1);
101 msleep(15);
102 data[0] = 0x01;
103 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
104 msleep(15);
105 data[0] = 0x00;
106 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
107 msleep(15);
108
109 msleep(50);
110
111 switch(p->u.ofdm.bandwidth) {
112 case BANDWIDTH_8_MHZ:
113 data[0] = 0x00;
114 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
115 msleep(15);
116 data[0] = 0x36;
117 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x641e, 0x00, data, 0x1);
118 msleep(15);
119 data[0] = 0x67;
120 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x651e, 0x00, data, 0x1);
121 msleep(15);
122 data[0] = 0xe5;
123 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x661e, 0x00, data, 0x1);
124 msleep(15);
125 data[0] = 0x19;
126 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6c1e, 0x00, data, 0x1);
127 msleep(15);
128 data[0] = 0xe9;
129 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6d1e, 0x00, data, 0x1);
130 msleep(15);
131 data[0] = 0x44;
132 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x511e, 0x00, data, 0x1);
133 msleep(15);
134 data[0] = 0x46;
135 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x521e, 0x00, data, 0x1);
136 msleep(15);
137 data[0] = 0x15;
138 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x531e, 0x00, data, 0x1);
139 msleep(15);
140 data[0] = 0x0f;
141 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x541e, 0x00, data, 0x1);
142 msleep(15);
143 data[0] = 0x75;
144 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x5c1e, 0x00, data, 0x1);
145 msleep(15);
146 data[0] = 0x01;
147 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
148 msleep(15);
149 break;
150
151 default:
152 printk(KERN_ALERT "tm6000: bandwidth not supported\n");
153 case BANDWIDTH_7_MHZ:
154 data[0] = 0x00;
155 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
156 msleep(15);
157 data[0] = 0x35;
158 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x641e, 0x00, data, 0x1);
159 msleep(15);
160 data[0] = 0x5a;
161 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x651e, 0x00, data, 0x1);
162 msleep(15);
163 data[0] = 0xe9;
164 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x661e, 0x00, data, 0x1);
165 msleep(15);
166 data[0] = 0x19;
167 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6c1e, 0x00, data, 0x1);
168 msleep(15);
169 data[0] = 0xe9;
170 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x6d1e, 0x00, data, 0x1);
171 msleep(15);
172 data[0] = 0x44;
173 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x511e, 0x00, data, 0x1);
174 msleep(15);
175 data[0] = 0x46;
176 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x521e, 0x00, data, 0x1);
177 msleep(15);
178 data[0] = 0x15;
179 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x531e, 0x00, data, 0x1);
180 msleep(15);
181 data[0] = 0x0f;
182 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x541e, 0x00, data, 0x1);
183 msleep(15);
184 data[0] = 0x86;
185 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x5c1e, 0x00, data, 0x1);
186 msleep(15);
187 data[0] = 0x01;
188 ret = tm6000_snd_control_msg(tm6000_dev, 0x10, 0x701e, 0x00, data, 0x1);
189 msleep(15);
190 break;
191 }
192
193 kfree(data);
194
195 return 0;
196};
197
198
199
200int pseudo_zl10353_set_frontend(struct dvb_frontend *fe,
201 struct dvb_frontend_parameters *p)
202{
203 struct tm6000_core *tm6000_dev = fe->dvb->priv;
204 u32 status;
205
206 if(p != NULL) {
207// mutex_lock(&tm6000_dev->mutex);
208 pseudo_zl10353_pll(tm6000_dev, p);
209// mutex_unlock(&tm6000_dev->mutex);
210 }
211
212 if(tm6000_dev->dvb->frontend->ops.read_status) {
213 tm6000_dev->dvb->frontend->ops.read_status(tm6000_dev->dvb->frontend, &status);
214 printk(KERN_ALERT "demodulator status: FE_HAS_CARRIER %i \n", (status & FE_HAS_CARRIER));
215 printk(KERN_ALERT "demodulator status: FE_HAS_VITERBI %i \n", (status & FE_HAS_VITERBI));
216 printk(KERN_ALERT "demodulator status: FE_HAS_LOCK %i \n", (status & FE_HAS_LOCK));
217 printk(KERN_ALERT "demodulator status: FE_HAS_SYNC %i \n", (status & FE_HAS_SYNC));
218 printk(KERN_ALERT "demodulator status: FE_HAS_SIGNAL %i \n", (status & FE_HAS_SIGNAL));
219 }
220 else {
221 printk(KERN_ALERT "pseudo zl10353: couldn't read demodulator status\n");
222 }
223 return 0;
224}
225
226int pseudo_zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
227{
228
229 *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK | FE_HAS_SIGNAL;
230
231 return 0;
232}
233
234struct dvb_frontend* pseudo_zl10353_attach(struct tm6000_core *dev,
235 const struct zl10353_config *config,
236 struct i2c_adapter *i2c)
237{
238 struct tm6000_dvb *dvb = dev->dvb;
239
240 dvb->frontend = zl10353_attach(config, i2c);
241 if(!dvb->frontend) {
242 return NULL;
243 }
244
245 /* override some functions with our implementations */
246 dvb->frontend->ops.set_frontend = pseudo_zl10353_set_frontend;
247 dvb->frontend->ops.read_status = pseudo_zl10353_read_status;
248 dvb->frontend->frontend_priv = dev;
249
250 return dvb->frontend;
251}
diff --git a/drivers/staging/tm6000/hack.h b/drivers/staging/tm6000/hack.h
new file mode 100644
index 000000000000..96f1b61df682
--- /dev/null
+++ b/drivers/staging/tm6000/hack.h
@@ -0,0 +1,45 @@
1/*
2 hack.h - hackish code that needs to be improved (or removed) at a
3 later point
4
5 Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 2
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifndef HACK_H
22#define HACK_H
23
24#include <linux/i2c.h>
25
26#include "zl10353.h"
27#include "dvb_frontend.h"
28
29struct tm6000_core;
30
31int pseudo_zl103530_init(struct dvb_frontend *fe);
32
33int pseudo_zl10353_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
34
35int pseudo_zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status);
36
37int pseudo_zl10353_read_signal_strength(struct dvb_frontend* fe, u16* strength);
38
39int pseudo_zl10353_read_snr(struct dvb_frontend *fe, u16 *snr);
40
41struct dvb_frontend* pseudo_zl10353_attach(struct tm6000_core *dev,
42 const struct zl10353_config *config,
43 struct i2c_adapter *i2c);
44
45#endif
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index e8f88ea5ded9..b41b3a46779f 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -185,7 +185,19 @@ static int tm6000_init_dev(struct tm6000_core *dev)
185 dev->freq = f.frequency; 185 dev->freq = f.frequency;
186 186
187 tm6000_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); 187 tm6000_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
188 188 if(dev->caps.has_dvb) {
189 dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
190 if(!dev->dvb) {
191 rc = -ENOMEM;
192 goto err;
193 }
194 rc = tm6000_dvb_register(dev);
195 if(rc < 0) {
196 kfree(dev->dvb);
197 dev->dvb = NULL;
198 goto err;
199 }
200 }
189err: 201err:
190 mutex_unlock(&dev->lock); 202 mutex_unlock(&dev->lock);
191 return rc; 203 return rc;
@@ -389,6 +401,11 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
389 401
390 mutex_lock(&dev->lock); 402 mutex_lock(&dev->lock);
391 403
404 if(dev->dvb) {
405 tm6000_dvb_unregister(dev);
406 kfree(dev->dvb);
407 }
408
392 tm6000_v4l2_unregister(dev); 409 tm6000_v4l2_unregister(dev);
393 410
394 tm6000_i2c_unregister(dev); 411 tm6000_i2c_unregister(dev);
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index 6becde2eace6..5e9325582bde 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -3,6 +3,9 @@
3 3
4 Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> 4 Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
5 5
6 Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
7 - DVB-T support
8
6 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2 11 the Free Software Foundation version 2
@@ -207,6 +210,32 @@ int tm6000_init_analog_mode (struct tm6000_core *dev)
207 return 0; 210 return 0;
208} 211}
209 212
213int tm6000_init_digital_mode (struct tm6000_core *dev)
214{
215 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00ff, 0x08);
216 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00ff, 0x00);
217 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x003f, 0x01);
218 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00df, 0x08);
219 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e2, 0x0c);
220 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00e8, 0xff);
221 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0xd8);
222 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c0, 0x40);
223 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c1, 0xd0);
224 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00c3, 0x09);
225 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00da, 0x37);
226 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d1, 0xd8);
227 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d2, 0xc0);
228 tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00d6, 0x60);
229 msleep(50);
230
231 tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
232 tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
233 tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
234
235 msleep(100);
236
237 return 0;
238}
210 239
211/* The meaning of those initializations are unknown */ 240/* The meaning of those initializations are unknown */
212u8 init_tab[][2] = { 241u8 init_tab[][2] = {
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
new file mode 100644
index 000000000000..d2ec6ca766cb
--- /dev/null
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -0,0 +1,303 @@
1/*
2 tm6000-dvb.c - dvb-t support for TM5600/TM6000 USB video capture devices
3
4 Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/usb.h>
21
22#include "tm6000.h"
23#include "tm6000-regs.h"
24
25#include "hack.h"
26
27#include "zl10353.h"
28
29#include <media/tuner.h>
30
31static void tm6000_urb_received(struct urb *urb)
32{
33 int ret;
34 struct tm6000_core* dev = urb->context;
35
36 if(urb->status != 0){
37 printk(KERN_ERR "tm6000: status != 0\n");
38 }
39 else if(urb->actual_length>0){
40 dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
41 urb->actual_length);
42 }
43
44 if(dev->dvb->streams > 0) {
45 ret = usb_submit_urb(urb, GFP_ATOMIC);
46 if(ret < 0) {
47 printk(KERN_ERR "tm6000: error %s\n", __FUNCTION__);
48 kfree(urb->transfer_buffer);
49 usb_free_urb(urb);
50 }
51 }
52}
53
54int tm6000_start_stream(struct tm6000_core *dev)
55{
56 int ret;
57 unsigned int pipe, maxPaketSize;
58 struct tm6000_dvb *dvb = dev->dvb;
59
60 printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__);
61
62 tm6000_init_digital_mode(dev);
63
64// ret = usb_set_interface(dev->udev, 0, 1);
65// if (ret<0)
66// return ret;
67
68/*
69 ret = tm6000_set_led_status(tm6000_dev, 0x1);
70 if(ret < 0) {
71 return -1;
72 }
73*/
74
75 dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
76 if(dvb->bulk_urb == NULL) {
77 printk(KERN_ERR "tm6000: couldn't allocate urb\n");
78 return -ENOMEM;
79 }
80
81 maxPaketSize = dev->bulk_in->desc.wMaxPacketSize;
82
83 dvb->bulk_urb->transfer_buffer = kzalloc(maxPaketSize, GFP_KERNEL);
84 if(dvb->bulk_urb->transfer_buffer == NULL) {
85 usb_free_urb(dvb->bulk_urb);
86 printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
87 return -ENOMEM;
88 }
89
90 pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in->desc.bEndpointAddress
91 & USB_ENDPOINT_NUMBER_MASK);
92
93 usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
94 dvb->bulk_urb->transfer_buffer,
95 maxPaketSize,
96 tm6000_urb_received, dev);
97 ret = usb_clear_halt(dev->udev, pipe);
98 if(ret < 0) {
99 printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",ret,__FUNCTION__);
100// return ret;
101 }
102 else {
103 printk(KERN_ERR "tm6000: pipe resetted\n");
104 }
105
106// mutex_lock(&tm6000_driver.open_close_mutex);
107 ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
108
109
110// mutex_unlock(&tm6000_driver.open_close_mutex);
111 if (ret) {
112 printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",ret);
113
114 kfree(dvb->bulk_urb->transfer_buffer);
115 usb_free_urb(dvb->bulk_urb);
116 return ret;
117 }
118
119 return 0;
120}
121
122void tm6000_stop_stream(struct tm6000_core *dev)
123{
124 struct tm6000_dvb *dvb = dev->dvb;
125
126// tm6000_set_led_status(tm6000_dev, 0x0);
127
128 if(dvb->bulk_urb) {
129 usb_kill_urb(dvb->bulk_urb);
130 kfree(dvb->bulk_urb->transfer_buffer);
131 usb_free_urb(dvb->bulk_urb);
132 dvb->bulk_urb = NULL;
133 }
134}
135
136int tm6000_start_feed(struct dvb_demux_feed *feed)
137{
138 struct dvb_demux *demux = feed->demux;
139 struct tm6000_core *dev = demux->priv;
140 struct tm6000_dvb *dvb = dev->dvb;
141 printk(KERN_INFO "tm6000: got start feed request %s\n",__FUNCTION__);
142
143 mutex_lock(&dvb->mutex);
144 if(dvb->streams == 0) {
145 dvb->streams = 1;
146// mutex_init(&tm6000_dev->streaming_mutex);
147 tm6000_start_stream(dev);
148 }
149 else {
150 ++(dvb->streams);
151 }
152 mutex_unlock(&dvb->mutex);
153
154 return 0;
155}
156
157int tm6000_stop_feed(struct dvb_demux_feed *feed) {
158 struct dvb_demux *demux = feed->demux;
159 struct tm6000_core *dev = demux->priv;
160 struct tm6000_dvb *dvb = dev->dvb;
161
162 printk(KERN_INFO "tm6000: got stop feed request %s\n",__FUNCTION__);
163
164 mutex_lock(&dvb->mutex);
165 --dvb->streams;
166
167 if(0 == dvb->streams) {
168 tm6000_stop_stream(dev);
169// mutex_destroy(&tm6000_dev->streaming_mutex);
170 }
171 mutex_unlock(&dvb->mutex);
172// mutex_destroy(&tm6000_dev->streaming_mutex);
173
174 return 0;
175}
176
177int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
178{
179 struct tm6000_dvb *dvb = dev->dvb;
180
181 if(dev->caps.has_zl10353) {
182 struct zl10353_config config =
183 {.demod_address = dev->demod_addr >> 1,
184 .no_tuner = 1,
185// .input_frequency = 0x19e9,
186// .r56_agc_targets = 0x1c,
187 };
188
189 dvb->frontend = pseudo_zl10353_attach(dev, &config,
190 &dev->i2c_adap);
191 }
192 else {
193 printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
194 return -1;
195 }
196
197 if(dvb->frontend) {
198 return 0;
199 }
200 else {
201 return -1;
202 }
203}
204
205int tm6000_dvb_register(struct tm6000_core *dev)
206{
207 int ret = -1;
208 struct tm6000_dvb *dvb = dev->dvb;
209
210 mutex_init(&dvb->mutex);
211
212 dvb->streams = 0;
213
214 /* attach the frontend */
215 ret = tm6000_dvb_attach_frontend(dev);
216 if(ret < 0) {
217 printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
218// goto err;
219 }
220
221 ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
222 THIS_MODULE, &dev->udev->dev);
223 dvb->adapter.priv = dev;
224
225 if(dvb->frontend) {
226 ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
227 if(ret < 0) {
228 printk("tm6000: couldn't register frontend\n");
229 goto adapter_err;
230 }
231
232 // attach the tuner like this for now
233 tm6000_i2c_call_clients(dev, VIDIOC_INT_DVB_TUNER_ATTACH, dvb->frontend);
234
235 printk("tm6000: XC2028/3028 asked to be attached to frontend!\n");
236 }
237 else {
238 printk("tm6000: no frontend found\n");
239 }
240
241 dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
242 | DMX_MEMORY_BASED_FILTERING;
243 dvb->demux.priv = dev;
244 dvb->demux.filternum = 256;
245 dvb->demux.feednum = 256;
246 dvb->demux.start_feed = tm6000_start_feed;
247 dvb->demux.stop_feed = tm6000_stop_feed;
248 dvb->demux.write_to_decoder = NULL;
249 ret = dvb_dmx_init(&dvb->demux);
250 if(ret < 0) {
251 printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
252 goto frontend_err;
253 }
254
255 dvb->dmxdev.filternum = dev->dvb->demux.filternum;
256 dvb->dmxdev.demux = &dev->dvb->demux.dmx;
257 dvb->dmxdev.capabilities = 0;
258
259 ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
260 if(ret < 0) {
261 printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
262 goto dvb_dmx_err;
263 }
264
265 return 0;
266
267dvb_dmx_err:
268 dvb_dmx_release(&dvb->demux);
269frontend_err:
270 if(dvb->frontend) {
271 dvb_unregister_frontend(dvb->frontend);
272 }
273adapter_err:
274 dvb_unregister_adapter(&dvb->adapter);
275err:
276 return ret;
277}
278
279void tm6000_dvb_unregister(struct tm6000_core *dev)
280{
281 struct tm6000_dvb *dvb = dev->dvb;
282
283 if(dvb->bulk_urb != NULL) {
284 struct urb *bulk_urb = dvb->bulk_urb;
285
286 kfree(bulk_urb->transfer_buffer);
287 bulk_urb->transfer_buffer = NULL;
288 usb_unlink_urb(bulk_urb);
289 usb_free_urb(bulk_urb);
290 }
291
292// mutex_lock(&tm6000_driver.open_close_mutex);
293 if(dvb->frontend) {
294 dvb_unregister_frontend(dvb->frontend);
295 }
296
297 dvb_dmxdev_release(&dvb->dmxdev);
298 dvb_dmx_release(&dvb->demux);
299 dvb_unregister_adapter(&dvb->adapter);
300 mutex_destroy(&dvb->mutex);
301// mutex_unlock(&tm6000_driver.open_close_mutex);
302
303}
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 27bee627d3b7..3556fa4c403d 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -3,6 +3,9 @@
3 3
4 Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> 4 Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
5 5
6 Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
7 - DVB-T support
8
6 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2 11 the Free Software Foundation version 2
@@ -27,6 +30,11 @@
27#include <linux/i2c.h> 30#include <linux/i2c.h>
28#include <linux/mutex.h> 31#include <linux/mutex.h>
29 32
33#include <linux/dvb/frontend.h>
34#include "dvb_demux.h"
35#include "dvb_frontend.h"
36#include "dmxdev.h"
37
30#define TM6000_VERSION KERNEL_VERSION(0, 0, 1) 38#define TM6000_VERSION KERNEL_VERSION(0, 0, 1)
31 39
32/* Inputs */ 40/* Inputs */
@@ -97,12 +105,23 @@ struct tm6000_capabilities {
97 unsigned int has_eeprom:1; 105 unsigned int has_eeprom:1;
98}; 106};
99 107
108struct tm6000_dvb {
109 struct dvb_adapter adapter;
110 struct dvb_demux demux;
111 struct dvb_frontend *frontend;
112 struct dmxdev dmxdev;
113 unsigned int streams;
114 struct urb *bulk_urb;
115 struct mutex mutex;
116};
117
100struct tm6000_core { 118struct tm6000_core {
101 /* generic device properties */ 119 /* generic device properties */
102 char name[30]; /* name (including minor) of the device */ 120 char name[30]; /* name (including minor) of the device */
103 int model; /* index in the device_data struct */ 121 int model; /* index in the device_data struct */
104 int devno; /* marks the number of this device */ 122 int devno; /* marks the number of this device */
105 v4l2_std_id norm; /* Current norm */ 123
124 v4l2_std_id norm; /* Current norm */
106 125
107 enum tm6000_core_state state; 126 enum tm6000_core_state state;
108 127
@@ -136,6 +155,9 @@ struct tm6000_core {
136 155
137 enum tm6000_mode mode; 156 enum tm6000_mode mode;
138 157
158 /* DVB-T support */
159 struct tm6000_dvb *dvb;
160
139 /* locks */ 161 /* locks */
140 struct mutex lock; 162 struct mutex lock;
141 163
@@ -181,9 +203,13 @@ int tm6000_init (struct tm6000_core *dev);
181int tm6000_init_after_firmware (struct tm6000_core *dev); 203int tm6000_init_after_firmware (struct tm6000_core *dev);
182 204
183int tm6000_init_analog_mode (struct tm6000_core *dev); 205int tm6000_init_analog_mode (struct tm6000_core *dev);
206int tm6000_init_digital_mode (struct tm6000_core *dev);
184int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm); 207int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm);
185int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate); 208int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate);
186 209
210int tm6000_dvb_register(struct tm6000_core *dev);
211void tm6000_dvb_unregister(struct tm6000_core *dev);
212
187int tm6000_v4l2_register(struct tm6000_core *dev); 213int tm6000_v4l2_register(struct tm6000_core *dev);
188int tm6000_v4l2_unregister(struct tm6000_core *dev); 214int tm6000_v4l2_unregister(struct tm6000_core *dev);
189int tm6000_v4l2_exit(void); 215int tm6000_v4l2_exit(void);