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