]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/tm6000/tm6000-dvb.c
V4L/DVB: tm6000: set variable dev_mode in function tm6000_start_stream
[karo-tx-linux.git] / drivers / staging / tm6000 / tm6000-dvb.c
1 /*
2    tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 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/kernel.h>
21 #include <linux/usb.h>
22
23 #include "tm6000.h"
24 #include "tm6000-regs.h"
25
26 #include "zl10353.h"
27
28 #include <media/tuner.h>
29
30 #include "tuner-xc2028.h"
31
32 static void inline print_err_status (struct tm6000_core *dev,
33                                      int packet, int status)
34 {
35         char *errmsg = "Unknown";
36
37         switch(status) {
38         case -ENOENT:
39                 errmsg = "unlinked synchronuously";
40                 break;
41         case -ECONNRESET:
42                 errmsg = "unlinked asynchronuously";
43                 break;
44         case -ENOSR:
45                 errmsg = "Buffer error (overrun)";
46                 break;
47         case -EPIPE:
48                 errmsg = "Stalled (device not responding)";
49                 break;
50         case -EOVERFLOW:
51                 errmsg = "Babble (bad cable?)";
52                 break;
53         case -EPROTO:
54                 errmsg = "Bit-stuff error (bad cable?)";
55                 break;
56         case -EILSEQ:
57                 errmsg = "CRC/Timeout (could be anything)";
58                 break;
59         case -ETIME:
60                 errmsg = "Device does not respond";
61                 break;
62         }
63         if (packet<0) {
64                 dprintk(dev, 1, "URB status %d [%s].\n",
65                         status, errmsg);
66         } else {
67                 dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
68                         packet, status, errmsg);
69         }
70 }
71
72 static void tm6000_urb_received(struct urb *urb)
73 {
74         int ret;
75         struct tm6000_core* dev = urb->context;
76
77         if(urb->status != 0) {
78                 print_err_status (dev,0,urb->status);
79         }
80         else if(urb->actual_length>0){
81                 dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
82                                                    urb->actual_length);
83         }
84
85         if(dev->dvb->streams > 0) {
86                 ret = usb_submit_urb(urb, GFP_ATOMIC);
87                 if(ret < 0) {
88                         printk(KERN_ERR "tm6000:  error %s\n", __FUNCTION__);
89                         kfree(urb->transfer_buffer);
90                         usb_free_urb(urb);
91                 }
92         }
93 }
94
95 int tm6000_start_stream(struct tm6000_core *dev)
96 {
97         int ret;
98         unsigned int pipe, size;
99         struct tm6000_dvb *dvb = dev->dvb;
100
101         printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__);
102
103         if (dev->mode != TM6000_MODE_DIGITAL) {
104                 tm6000_init_digital_mode(dev);
105                 dev->mode = TM6000_MODE_DIGITAL;
106         }
107
108         dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
109         if(dvb->bulk_urb == NULL) {
110                 printk(KERN_ERR "tm6000: couldn't allocate urb\n");
111                 return -ENOMEM;
112         }
113
114         pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
115                                                           & USB_ENDPOINT_NUMBER_MASK);
116
117         size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
118         size = size * 15; /* 512 x 8 or 12 or 15 */
119
120         dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
121         if(dvb->bulk_urb->transfer_buffer == NULL) {
122                 usb_free_urb(dvb->bulk_urb);
123                 printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
124                 return -ENOMEM;
125         }
126
127         usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
128                                                  dvb->bulk_urb->transfer_buffer,
129                                                  size,
130                                                  tm6000_urb_received, dev);
131
132         ret = usb_clear_halt(dev->udev, pipe);
133         if(ret < 0) {
134                 printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",ret,__FUNCTION__);
135                 return ret;
136         }
137         else {
138                 printk(KERN_ERR "tm6000: pipe resetted\n");
139         }
140
141 /*      mutex_lock(&tm6000_driver.open_close_mutex); */
142         ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
143
144 /*      mutex_unlock(&tm6000_driver.open_close_mutex); */
145         if (ret) {
146                 printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",ret);
147
148                 kfree(dvb->bulk_urb->transfer_buffer);
149                 usb_free_urb(dvb->bulk_urb);
150                 return ret;
151         }
152
153         return 0;
154 }
155
156 void tm6000_stop_stream(struct tm6000_core *dev)
157 {
158         struct tm6000_dvb *dvb = dev->dvb;
159
160         if(dvb->bulk_urb) {
161                 printk (KERN_INFO "urb killing\n");
162                 usb_kill_urb(dvb->bulk_urb);
163                 printk (KERN_INFO "urb buffer free\n");
164                 kfree(dvb->bulk_urb->transfer_buffer);
165                 usb_free_urb(dvb->bulk_urb);
166                 dvb->bulk_urb = NULL;
167         }
168 }
169
170 int tm6000_start_feed(struct dvb_demux_feed *feed)
171 {
172         struct dvb_demux *demux = feed->demux;
173         struct tm6000_core *dev = demux->priv;
174         struct tm6000_dvb *dvb = dev->dvb;
175         printk(KERN_INFO "tm6000: got start feed request %s\n",__FUNCTION__);
176
177         mutex_lock(&dvb->mutex);
178         if(dvb->streams == 0) {
179                 dvb->streams = 1;
180 /*              mutex_init(&tm6000_dev->streming_mutex); */
181                 tm6000_start_stream(dev);
182         }
183         else {
184                 ++(dvb->streams);
185         }
186         mutex_unlock(&dvb->mutex);
187
188         return 0;
189 }
190
191 int tm6000_stop_feed(struct dvb_demux_feed *feed) {
192         struct dvb_demux *demux = feed->demux;
193         struct tm6000_core *dev = demux->priv;
194         struct tm6000_dvb *dvb = dev->dvb;
195
196         printk(KERN_INFO "tm6000: got stop feed request %s\n",__FUNCTION__);
197
198         mutex_lock(&dvb->mutex);
199
200         printk (KERN_INFO "stream %#x\n", dvb->streams);
201         --(dvb->streams);
202         if(dvb->streams == 0) {
203                 printk (KERN_INFO "stop stream\n");
204                 tm6000_stop_stream(dev);
205 /*              mutex_destroy(&tm6000_dev->streaming_mutex); */
206         }
207         mutex_unlock(&dvb->mutex);
208 /*      mutex_destroy(&tm6000_dev->streaming_mutex); */
209
210         return 0;
211 }
212
213 int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
214 {
215         struct tm6000_dvb *dvb = dev->dvb;
216
217         if(dev->caps.has_zl10353) {
218                 struct zl10353_config config =
219                                     {.demod_address = dev->demod_addr,
220                                      .no_tuner = 1,
221                                      .parallel_ts = 1,
222                                      .if2 = 45700,
223                                      .disable_i2c_gate_ctrl = 1,
224                                     };
225
226                 dvb->frontend = dvb_attach(zl10353_attach, &config,
227                                                            &dev->i2c_adap);
228         }
229         else {
230                 printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
231                 return -1;
232         }
233
234         return (!dvb->frontend) ? -1 : 0;
235 }
236
237 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
238
239 int tm6000_dvb_register(struct tm6000_core *dev)
240 {
241         int ret = -1;
242         struct tm6000_dvb *dvb = dev->dvb;
243
244         mutex_init(&dvb->mutex);
245
246         dvb->streams = 0;
247
248         /* attach the frontend */
249         ret = tm6000_dvb_attach_frontend(dev);
250         if(ret < 0) {
251                 printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
252                 goto err;
253         }
254
255         ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
256                                                           THIS_MODULE, &dev->udev->dev, adapter_nr);
257         dvb->adapter.priv = dev;
258
259         if (dvb->frontend) {
260                 struct xc2028_config cfg = {
261                         .i2c_adap = &dev->i2c_adap,
262                         .i2c_addr = dev->tuner_addr,
263                 };
264
265                 dvb->frontend->callback = tm6000_tuner_callback;
266                 ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
267                 if (ret < 0) {
268                         printk(KERN_ERR
269                                 "tm6000: couldn't register frontend\n");
270                         goto adapter_err;
271                 }
272
273                 if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
274                         printk(KERN_ERR "tm6000: couldn't register "
275                                         "frontend (xc3028)\n");
276                         ret = -EINVAL;
277                         goto frontend_err;
278                 }
279                 printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
280                                  "attached to frontend!\n");
281         } else {
282                 printk(KERN_ERR "tm6000: no frontend found\n");
283         }
284
285         dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
286                                                             | DMX_MEMORY_BASED_FILTERING;
287         dvb->demux.priv = dev;
288         dvb->demux.filternum = 8;
289         dvb->demux.feednum = 8;
290         dvb->demux.start_feed = tm6000_start_feed;
291         dvb->demux.stop_feed = tm6000_stop_feed;
292         dvb->demux.write_to_decoder = NULL;
293         ret = dvb_dmx_init(&dvb->demux);
294         if(ret < 0) {
295                 printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
296                 goto frontend_err;
297         }
298
299         dvb->dmxdev.filternum = dev->dvb->demux.filternum;
300         dvb->dmxdev.demux = &dev->dvb->demux.dmx;
301         dvb->dmxdev.capabilities = 0;
302
303         ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
304         if(ret < 0) {
305                 printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
306                 goto dvb_dmx_err;
307         }
308
309         return 0;
310
311 dvb_dmx_err:
312         dvb_dmx_release(&dvb->demux);
313 frontend_err:
314         if(dvb->frontend) {
315                 dvb_frontend_detach(dvb->frontend);
316                 dvb_unregister_frontend(dvb->frontend);
317         }
318 adapter_err:
319         dvb_unregister_adapter(&dvb->adapter);
320 err:
321         return ret;
322 }
323
324 void tm6000_dvb_unregister(struct tm6000_core *dev)
325 {
326         struct tm6000_dvb *dvb = dev->dvb;
327
328         if(dvb->bulk_urb != NULL) {
329                 struct urb *bulk_urb = dvb->bulk_urb;
330
331                 kfree(bulk_urb->transfer_buffer);
332                 bulk_urb->transfer_buffer = NULL;
333                 usb_unlink_urb(bulk_urb);
334                 usb_free_urb(bulk_urb);
335         }
336
337 /*      mutex_lock(&tm6000_driver.open_close_mutex); */
338         if(dvb->frontend) {
339                 dvb_frontend_detach(dvb->frontend);
340                 dvb_unregister_frontend(dvb->frontend);
341         }
342
343         dvb_dmxdev_release(&dvb->dmxdev);
344         dvb_dmx_release(&dvb->demux);
345         dvb_unregister_adapter(&dvb->adapter);
346         mutex_destroy(&dvb->mutex);
347 /*      mutex_unlock(&tm6000_driver.open_close_mutex); */
348
349 }