xref: /OK3568_Linux_fs/kernel/drivers/media/usb/dvb-usb/a800.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
3*4882a593Smuzhiyun  * USB2.0 (A800) DVB-T receiver.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de)
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Thanks to
8*4882a593Smuzhiyun  *   - AVerMedia who kindly provided information and
9*4882a593Smuzhiyun  *   - Glen Harris who suffered from my mistakes during development.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun #include "dibusb.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun static int debug;
16*4882a593Smuzhiyun module_param(debug, int, 0644);
17*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define deb_rc(args...)   dprintk(debug,0x01,args)
22*4882a593Smuzhiyun 
a800_power_ctrl(struct dvb_usb_device * d,int onoff)23*4882a593Smuzhiyun static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	/* do nothing for the AVerMedia */
26*4882a593Smuzhiyun 	return 0;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* assure to put cold to 0 for iManufacturer == 1 */
a800_identify_state(struct usb_device * udev,const struct dvb_usb_device_properties * props,const struct dvb_usb_device_description ** desc,int * cold)30*4882a593Smuzhiyun static int a800_identify_state(struct usb_device *udev,
31*4882a593Smuzhiyun 			       const struct dvb_usb_device_properties *props,
32*4882a593Smuzhiyun 			       const struct dvb_usb_device_description **desc,
33*4882a593Smuzhiyun 			       int *cold)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	*cold = udev->descriptor.iManufacturer != 1;
36*4882a593Smuzhiyun 	return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
a800_rc_query(struct dvb_usb_device * d)39*4882a593Smuzhiyun static int a800_rc_query(struct dvb_usb_device *d)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	int ret = 0;
42*4882a593Smuzhiyun 	u8 *key = kmalloc(5, GFP_KERNEL);
43*4882a593Smuzhiyun 	if (!key)
44*4882a593Smuzhiyun 		return -ENOMEM;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
47*4882a593Smuzhiyun 				0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
48*4882a593Smuzhiyun 				2000) != 5) {
49*4882a593Smuzhiyun 		ret = -ENODEV;
50*4882a593Smuzhiyun 		goto out;
51*4882a593Smuzhiyun 	}
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* Note that extended nec and nec32 are dropped */
54*4882a593Smuzhiyun 	if (key[0] == 1)
55*4882a593Smuzhiyun 		rc_keydown(d->rc_dev, RC_PROTO_NEC,
56*4882a593Smuzhiyun 			   RC_SCANCODE_NEC(key[1], key[3]), 0);
57*4882a593Smuzhiyun 	else if (key[0] == 2)
58*4882a593Smuzhiyun 		rc_repeat(d->rc_dev);
59*4882a593Smuzhiyun out:
60*4882a593Smuzhiyun 	kfree(key);
61*4882a593Smuzhiyun 	return ret;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* USB Driver stuff */
65*4882a593Smuzhiyun static struct dvb_usb_device_properties a800_properties;
66*4882a593Smuzhiyun 
a800_probe(struct usb_interface * intf,const struct usb_device_id * id)67*4882a593Smuzhiyun static int a800_probe(struct usb_interface *intf,
68*4882a593Smuzhiyun 		const struct usb_device_id *id)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	return dvb_usb_device_init(intf, &a800_properties,
71*4882a593Smuzhiyun 				   THIS_MODULE, NULL, adapter_nr);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* do not change the order of the ID table */
75*4882a593Smuzhiyun static struct usb_device_id a800_table [] = {
76*4882a593Smuzhiyun /* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
77*4882a593Smuzhiyun /* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
78*4882a593Smuzhiyun 			{ }		/* Terminating entry */
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun MODULE_DEVICE_TABLE (usb, a800_table);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun static struct dvb_usb_device_properties a800_properties = {
83*4882a593Smuzhiyun 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	.usb_ctrl = CYPRESS_FX2,
86*4882a593Smuzhiyun 	.firmware = "dvb-usb-avertv-a800-02.fw",
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	.num_adapters = 1,
89*4882a593Smuzhiyun 	.adapter = {
90*4882a593Smuzhiyun 		{
91*4882a593Smuzhiyun 		.num_frontends = 1,
92*4882a593Smuzhiyun 		.fe = {{
93*4882a593Smuzhiyun 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
94*4882a593Smuzhiyun 			.pid_filter_count = 32,
95*4882a593Smuzhiyun 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
96*4882a593Smuzhiyun 			.pid_filter       = dibusb_pid_filter,
97*4882a593Smuzhiyun 			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 			.frontend_attach  = dibusb_dib3000mc_frontend_attach,
100*4882a593Smuzhiyun 			.tuner_attach     = dibusb_dib3000mc_tuner_attach,
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 			/* parameter for the MPEG2-data transfer */
103*4882a593Smuzhiyun 					.stream = {
104*4882a593Smuzhiyun 						.type = USB_BULK,
105*4882a593Smuzhiyun 				.count = 7,
106*4882a593Smuzhiyun 				.endpoint = 0x06,
107*4882a593Smuzhiyun 				.u = {
108*4882a593Smuzhiyun 					.bulk = {
109*4882a593Smuzhiyun 						.buffersize = 4096,
110*4882a593Smuzhiyun 					}
111*4882a593Smuzhiyun 				}
112*4882a593Smuzhiyun 			},
113*4882a593Smuzhiyun 		}},
114*4882a593Smuzhiyun 			.size_of_priv     = sizeof(struct dibusb_state),
115*4882a593Smuzhiyun 		},
116*4882a593Smuzhiyun 	},
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	.power_ctrl       = a800_power_ctrl,
119*4882a593Smuzhiyun 	.identify_state   = a800_identify_state,
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	.rc.core = {
122*4882a593Smuzhiyun 		.rc_interval	= DEFAULT_RC_INTERVAL,
123*4882a593Smuzhiyun 		.rc_codes	= RC_MAP_AVERMEDIA_M135A,
124*4882a593Smuzhiyun 		.module_name	= KBUILD_MODNAME,
125*4882a593Smuzhiyun 		.rc_query	= a800_rc_query,
126*4882a593Smuzhiyun 		.allowed_protos = RC_PROTO_BIT_NEC,
127*4882a593Smuzhiyun 	},
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	.i2c_algo         = &dibusb_i2c_algo,
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	.generic_bulk_ctrl_endpoint = 0x01,
132*4882a593Smuzhiyun 	.num_device_descs = 1,
133*4882a593Smuzhiyun 	.devices = {
134*4882a593Smuzhiyun 		{   "AVerMedia AverTV DVB-T USB 2.0 (A800)",
135*4882a593Smuzhiyun 			{ &a800_table[0], NULL },
136*4882a593Smuzhiyun 			{ &a800_table[1], NULL },
137*4882a593Smuzhiyun 		},
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static struct usb_driver a800_driver = {
142*4882a593Smuzhiyun 	.name		= "dvb_usb_a800",
143*4882a593Smuzhiyun 	.probe		= a800_probe,
144*4882a593Smuzhiyun 	.disconnect = dvb_usb_device_exit,
145*4882a593Smuzhiyun 	.id_table	= a800_table,
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun module_usb_driver(a800_driver);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
151*4882a593Smuzhiyun MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
152*4882a593Smuzhiyun MODULE_VERSION("1.0");
153*4882a593Smuzhiyun MODULE_LICENSE("GPL");
154