media: tm6000: add error handling for dvb_register_adapter
[linux-2.6-microblaze.git] / drivers / media / usb / 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
16 #include <linux/kernel.h>
17 #include <linux/slab.h>
18 #include <linux/usb.h>
19
20 #include "tm6000.h"
21 #include "tm6000-regs.h"
22
23 #include "zl10353.h"
24
25 #include <media/tuner.h>
26
27 #include "tuner-xc2028.h"
28 #include "xc5000.h"
29
30 MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
31 MODULE_AUTHOR("Mauro Carvalho Chehab");
32 MODULE_LICENSE("GPL");
33
34 MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},{{Trident, tm6000},{{Trident, tm6010}");
35
36 static int debug;
37
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "enable debug message");
40
41 static inline void print_err_status(struct tm6000_core *dev,
42                                     int packet, int status)
43 {
44         char *errmsg = "Unknown";
45
46         switch (status) {
47         case -ENOENT:
48                 errmsg = "unlinked synchronously";
49                 break;
50         case -ECONNRESET:
51                 errmsg = "unlinked asynchronously";
52                 break;
53         case -ENOSR:
54                 errmsg = "Buffer error (overrun)";
55                 break;
56         case -EPIPE:
57                 errmsg = "Stalled (device not responding)";
58                 break;
59         case -EOVERFLOW:
60                 errmsg = "Babble (bad cable?)";
61                 break;
62         case -EPROTO:
63                 errmsg = "Bit-stuff error (bad cable?)";
64                 break;
65         case -EILSEQ:
66                 errmsg = "CRC/Timeout (could be anything)";
67                 break;
68         case -ETIME:
69                 errmsg = "Device does not respond";
70                 break;
71         }
72         if (packet < 0) {
73                 dprintk(dev, 1, "URB status %d [%s].\n",
74                         status, errmsg);
75         } else {
76                 dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
77                         packet, status, errmsg);
78         }
79 }
80
81 static void tm6000_urb_received(struct urb *urb)
82 {
83         int ret;
84         struct tm6000_core *dev = urb->context;
85
86         switch (urb->status) {
87         case 0:
88         case -ETIMEDOUT:
89                 break;
90         case -ENOENT:
91         case -ECONNRESET:
92         case -ESHUTDOWN:
93                 return;
94         default:
95                 print_err_status(dev, 0, urb->status);
96         }
97
98         if (urb->actual_length > 0)
99                 dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
100                                                    urb->actual_length);
101
102         if (dev->dvb->streams > 0) {
103                 ret = usb_submit_urb(urb, GFP_ATOMIC);
104                 if (ret < 0) {
105                         printk(KERN_ERR "tm6000:  error %s\n", __func__);
106                         kfree(urb->transfer_buffer);
107                         usb_free_urb(urb);
108                 }
109         }
110 }
111
112 static int tm6000_start_stream(struct tm6000_core *dev)
113 {
114         int ret;
115         unsigned int pipe, size;
116         struct tm6000_dvb *dvb = dev->dvb;
117
118         printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
119
120         if (dev->mode != TM6000_MODE_DIGITAL) {
121                 tm6000_init_digital_mode(dev);
122                 dev->mode = TM6000_MODE_DIGITAL;
123         }
124
125         dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
126         if (!dvb->bulk_urb)
127                 return -ENOMEM;
128
129         pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
130                                                           & USB_ENDPOINT_NUMBER_MASK);
131
132         size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
133         size = size * 15; /* 512 x 8 or 12 or 15 */
134
135         dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
136         if (!dvb->bulk_urb->transfer_buffer) {
137                 usb_free_urb(dvb->bulk_urb);
138                 return -ENOMEM;
139         }
140
141         usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
142                                                  dvb->bulk_urb->transfer_buffer,
143                                                  size,
144                                                  tm6000_urb_received, dev);
145
146         ret = usb_clear_halt(dev->udev, pipe);
147         if (ret < 0) {
148                 printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
149                                                         ret, __func__);
150                 return ret;
151         } else
152                 printk(KERN_ERR "tm6000: pipe resetted\n");
153
154 /*      mutex_lock(&tm6000_driver.open_close_mutex); */
155         ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
156
157 /*      mutex_unlock(&tm6000_driver.open_close_mutex); */
158         if (ret) {
159                 printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
160                                                                         ret);
161
162                 kfree(dvb->bulk_urb->transfer_buffer);
163                 usb_free_urb(dvb->bulk_urb);
164                 return ret;
165         }
166
167         return 0;
168 }
169
170 static void tm6000_stop_stream(struct tm6000_core *dev)
171 {
172         struct tm6000_dvb *dvb = dev->dvb;
173
174         if (dvb->bulk_urb) {
175                 printk(KERN_INFO "urb killing\n");
176                 usb_kill_urb(dvb->bulk_urb);
177                 printk(KERN_INFO "urb buffer free\n");
178                 kfree(dvb->bulk_urb->transfer_buffer);
179                 usb_free_urb(dvb->bulk_urb);
180                 dvb->bulk_urb = NULL;
181         }
182 }
183
184 static int tm6000_start_feed(struct dvb_demux_feed *feed)
185 {
186         struct dvb_demux *demux = feed->demux;
187         struct tm6000_core *dev = demux->priv;
188         struct tm6000_dvb *dvb = dev->dvb;
189         printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
190
191         mutex_lock(&dvb->mutex);
192         if (dvb->streams == 0) {
193                 dvb->streams = 1;
194 /*              mutex_init(&tm6000_dev->streming_mutex); */
195                 tm6000_start_stream(dev);
196         } else
197                 ++(dvb->streams);
198         mutex_unlock(&dvb->mutex);
199
200         return 0;
201 }
202
203 static int tm6000_stop_feed(struct dvb_demux_feed *feed)
204 {
205         struct dvb_demux *demux = feed->demux;
206         struct tm6000_core *dev = demux->priv;
207         struct tm6000_dvb *dvb = dev->dvb;
208
209         printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
210
211         mutex_lock(&dvb->mutex);
212
213         printk(KERN_INFO "stream %#x\n", dvb->streams);
214         --(dvb->streams);
215         if (dvb->streams == 0) {
216                 printk(KERN_INFO "stop stream\n");
217                 tm6000_stop_stream(dev);
218 /*              mutex_destroy(&tm6000_dev->streaming_mutex); */
219         }
220         mutex_unlock(&dvb->mutex);
221 /*      mutex_destroy(&tm6000_dev->streaming_mutex); */
222
223         return 0;
224 }
225
226 static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
227 {
228         struct tm6000_dvb *dvb = dev->dvb;
229
230         if (dev->caps.has_zl10353) {
231                 struct zl10353_config config = {
232                                      .demod_address = dev->demod_addr,
233                                      .no_tuner = 1,
234                                      .parallel_ts = 1,
235                                      .if2 = 45700,
236                                      .disable_i2c_gate_ctrl = 1,
237                                     };
238
239                 dvb->frontend = dvb_attach(zl10353_attach, &config,
240                                                            &dev->i2c_adap);
241         } else {
242                 printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
243                 return -1;
244         }
245
246         return (!dvb->frontend) ? -1 : 0;
247 }
248
249 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
250
251 static int register_dvb(struct tm6000_core *dev)
252 {
253         int ret = -1;
254         struct tm6000_dvb *dvb = dev->dvb;
255
256         mutex_init(&dvb->mutex);
257
258         dvb->streams = 0;
259
260         /* attach the frontend */
261         ret = tm6000_dvb_attach_frontend(dev);
262         if (ret < 0) {
263                 printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
264                 goto err;
265         }
266
267         ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
268                                         THIS_MODULE, &dev->udev->dev, adapter_nr);
269         if (ret < 0) {
270                 pr_err("tm6000: couldn't register the adapter!\n");
271                 goto err;
272         }
273
274         dvb->adapter.priv = dev;
275
276         if (dvb->frontend) {
277                 switch (dev->tuner_type) {
278                 case TUNER_XC2028: {
279                         struct xc2028_config cfg = {
280                                 .i2c_adap = &dev->i2c_adap,
281                                 .i2c_addr = dev->tuner_addr,
282                         };
283
284                         dvb->frontend->callback = tm6000_tuner_callback;
285                         ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
286                         if (ret < 0) {
287                                 printk(KERN_ERR
288                                         "tm6000: couldn't register frontend\n");
289                                 goto adapter_err;
290                         }
291
292                         if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
293                                 printk(KERN_ERR "tm6000: couldn't register frontend (xc3028)\n");
294                                 ret = -EINVAL;
295                                 goto frontend_err;
296                         }
297                         printk(KERN_INFO "tm6000: XC2028/3028 asked to be attached to frontend!\n");
298                         break;
299                         }
300                 case TUNER_XC5000: {
301                         struct xc5000_config cfg = {
302                                 .i2c_address = dev->tuner_addr,
303                         };
304
305                         dvb->frontend->callback = tm6000_xc5000_callback;
306                         ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
307                         if (ret < 0) {
308                                 printk(KERN_ERR
309                                         "tm6000: couldn't register frontend\n");
310                                 goto adapter_err;
311                         }
312
313                         if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
314                                 printk(KERN_ERR "tm6000: couldn't register frontend (xc5000)\n");
315                                 ret = -EINVAL;
316                                 goto frontend_err;
317                         }
318                         printk(KERN_INFO "tm6000: XC5000 asked to be attached to frontend!\n");
319                         break;
320                         }
321                 }
322         } else
323                 printk(KERN_ERR "tm6000: no frontend found\n");
324
325         dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
326                                                             | DMX_MEMORY_BASED_FILTERING;
327         dvb->demux.priv = dev;
328         dvb->demux.filternum = 8;
329         dvb->demux.feednum = 8;
330         dvb->demux.start_feed = tm6000_start_feed;
331         dvb->demux.stop_feed = tm6000_stop_feed;
332         dvb->demux.write_to_decoder = NULL;
333         ret = dvb_dmx_init(&dvb->demux);
334         if (ret < 0) {
335                 printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
336                 goto frontend_err;
337         }
338
339         dvb->dmxdev.filternum = dev->dvb->demux.filternum;
340         dvb->dmxdev.demux = &dev->dvb->demux.dmx;
341         dvb->dmxdev.capabilities = 0;
342
343         ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
344         if (ret < 0) {
345                 printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
346                 goto dvb_dmx_err;
347         }
348
349         return 0;
350
351 dvb_dmx_err:
352         dvb_dmx_release(&dvb->demux);
353 frontend_err:
354         if (dvb->frontend) {
355                 dvb_unregister_frontend(dvb->frontend);
356                 dvb_frontend_detach(dvb->frontend);
357         }
358 adapter_err:
359         dvb_unregister_adapter(&dvb->adapter);
360 err:
361         return ret;
362 }
363
364 static void unregister_dvb(struct tm6000_core *dev)
365 {
366         struct tm6000_dvb *dvb = dev->dvb;
367
368         if (dvb->bulk_urb) {
369                 struct urb *bulk_urb = dvb->bulk_urb;
370
371                 kfree(bulk_urb->transfer_buffer);
372                 bulk_urb->transfer_buffer = NULL;
373                 usb_unlink_urb(bulk_urb);
374                 usb_free_urb(bulk_urb);
375         }
376
377 /*      mutex_lock(&tm6000_driver.open_close_mutex); */
378         if (dvb->frontend) {
379                 dvb_unregister_frontend(dvb->frontend);
380                 dvb_frontend_detach(dvb->frontend);
381         }
382
383         dvb_dmxdev_release(&dvb->dmxdev);
384         dvb_dmx_release(&dvb->demux);
385         dvb_unregister_adapter(&dvb->adapter);
386         mutex_destroy(&dvb->mutex);
387 /*      mutex_unlock(&tm6000_driver.open_close_mutex); */
388 }
389
390 static int dvb_init(struct tm6000_core *dev)
391 {
392         struct tm6000_dvb *dvb;
393         int rc;
394
395         if (!dev)
396                 return 0;
397
398         if (!dev->caps.has_dvb)
399                 return 0;
400
401         if (dev->udev->speed == USB_SPEED_FULL) {
402                 printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
403                 return 0;
404         }
405
406         dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
407         if (!dvb)
408                 return -ENOMEM;
409
410         dev->dvb = dvb;
411
412         rc = register_dvb(dev);
413         if (rc < 0) {
414                 kfree(dvb);
415                 dev->dvb = NULL;
416                 return 0;
417         }
418
419         return 0;
420 }
421
422 static int dvb_fini(struct tm6000_core *dev)
423 {
424         if (!dev)
425                 return 0;
426
427         if (!dev->caps.has_dvb)
428                 return 0;
429
430         if (dev->dvb) {
431                 unregister_dvb(dev);
432                 kfree(dev->dvb);
433                 dev->dvb = NULL;
434         }
435
436         return 0;
437 }
438
439 static struct tm6000_ops dvb_ops = {
440         .type   = TM6000_DVB,
441         .name   = "TM6000 dvb Extension",
442         .init   = dvb_init,
443         .fini   = dvb_fini,
444 };
445
446 static int __init tm6000_dvb_register(void)
447 {
448         return tm6000_register_extension(&dvb_ops);
449 }
450
451 static void __exit tm6000_dvb_unregister(void)
452 {
453         tm6000_unregister_extension(&dvb_ops);
454 }
455
456 module_init(tm6000_dvb_register);
457 module_exit(tm6000_dvb_unregister);