• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/dvb/dvb-usb/
1/*
2 * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
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; either version 2 of the License, or
9 *    (at your option) any later version.
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
22#include "ce6230.h"
23#include "zl10353.h"
24#include "mxl5005s.h"
25
26/* debug */
27static int dvb_usb_ce6230_debug;
28module_param_named(debug, dvb_usb_ce6230_debug, int, 0644);
29MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
30DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
31
32static struct zl10353_config ce6230_zl10353_config;
33
34static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
35{
36	int ret;
37	unsigned int pipe;
38	u8 request;
39	u8 requesttype;
40	u16 value;
41	u16 index;
42	u8 buf[req->data_len];
43
44	request = req->cmd;
45	value = req->value;
46	index = req->index;
47
48	switch (req->cmd) {
49	case I2C_READ:
50	case DEMOD_READ:
51	case REG_READ:
52		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
53		break;
54	case I2C_WRITE:
55	case DEMOD_WRITE:
56	case REG_WRITE:
57		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
58		break;
59	default:
60		err("unknown command:%02x", req->cmd);
61		ret = -EPERM;
62		goto error;
63	}
64
65	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
66		/* write */
67		memcpy(buf, req->data, req->data_len);
68		pipe = usb_sndctrlpipe(udev, 0);
69	} else {
70		/* read */
71		pipe = usb_rcvctrlpipe(udev, 0);
72	}
73
74	msleep(1); /* avoid I2C errors */
75
76	ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
77				buf, sizeof(buf), CE6230_USB_TIMEOUT);
78
79	ce6230_debug_dump(request, requesttype, value, index, buf,
80		req->data_len, deb_xfer);
81
82	if (ret < 0)
83		deb_info("%s: usb_control_msg failed:%d\n", __func__, ret);
84	else
85		ret = 0;
86
87	/* read request, copy returned data to return buf */
88	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
89		memcpy(req->data, buf, req->data_len);
90
91error:
92	return ret;
93}
94
95static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
96{
97	return ce6230_rw_udev(d->udev, req);
98}
99
100/* I2C */
101static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
102			   int num)
103{
104	struct dvb_usb_device *d = i2c_get_adapdata(adap);
105	int i = 0;
106	struct req_t req;
107	int ret = 0;
108	memset(&req, 0, sizeof(req));
109
110	if (num > 2)
111		return -EINVAL;
112
113	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
114		return -EAGAIN;
115
116	while (i < num) {
117		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
118			if (msg[i].addr ==
119				ce6230_zl10353_config.demod_address) {
120				req.cmd = DEMOD_READ;
121				req.value = msg[i].addr >> 1;
122				req.index = msg[i].buf[0];
123				req.data_len = msg[i+1].len;
124				req.data = &msg[i+1].buf[0];
125				ret = ce6230_ctrl_msg(d, &req);
126			} else {
127				err("i2c read not implemented");
128				ret = -EPERM;
129			}
130			i += 2;
131		} else {
132			if (msg[i].addr ==
133				ce6230_zl10353_config.demod_address) {
134				req.cmd = DEMOD_WRITE;
135				req.value = msg[i].addr >> 1;
136				req.index = msg[i].buf[0];
137				req.data_len = msg[i].len-1;
138				req.data = &msg[i].buf[1];
139				ret = ce6230_ctrl_msg(d, &req);
140			} else {
141				req.cmd = I2C_WRITE;
142				req.value = 0x2000 + (msg[i].addr >> 1);
143				req.index = 0x0000;
144				req.data_len = msg[i].len;
145				req.data = &msg[i].buf[0];
146				ret = ce6230_ctrl_msg(d, &req);
147			}
148			i += 1;
149		}
150		if (ret)
151			break;
152	}
153
154	mutex_unlock(&d->i2c_mutex);
155	return ret ? ret : i;
156}
157
158static u32 ce6230_i2c_func(struct i2c_adapter *adapter)
159{
160	return I2C_FUNC_I2C;
161}
162
163static struct i2c_algorithm ce6230_i2c_algo = {
164	.master_xfer   = ce6230_i2c_xfer,
165	.functionality = ce6230_i2c_func,
166};
167
168/* Callbacks for DVB USB */
169static struct zl10353_config ce6230_zl10353_config = {
170	.demod_address = 0x1e,
171	.adc_clock = 450000,
172	.if2 = 45700,
173	.no_tuner = 1,
174	.parallel_ts = 1,
175	.clock_ctl_1 = 0x34,
176	.pll_0 = 0x0e,
177};
178
179static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
180{
181	deb_info("%s:\n", __func__);
182	adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
183		&adap->dev->i2c_adap);
184	if (adap->fe == NULL)
185		return -ENODEV;
186	return 0;
187}
188
189static struct mxl5005s_config ce6230_mxl5003s_config = {
190	.i2c_address     = 0xc6,
191	.if_freq         = IF_FREQ_4570000HZ,
192	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
193	.agc_mode        = MXL_SINGLE_AGC,
194	.tracking_filter = MXL_TF_DEFAULT,
195	.rssi_enable     = MXL_RSSI_ENABLE,
196	.cap_select      = MXL_CAP_SEL_ENABLE,
197	.div_out         = MXL_DIV_OUT_4,
198	.clock_out       = MXL_CLOCK_OUT_DISABLE,
199	.output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
200	.top		 = MXL5005S_TOP_25P2,
201	.mod_mode        = MXL_DIGITAL_MODE,
202	.if_mode         = MXL_ZERO_IF,
203	.AgcMasterByte   = 0x00,
204};
205
206static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
207{
208	int ret;
209	deb_info("%s:\n", __func__);
210	ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
211			&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
212	return ret;
213}
214
215static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff)
216{
217	int ret;
218	deb_info("%s: onoff:%d\n", __func__, onoff);
219
220	/* InterfaceNumber 1 / AlternateSetting 0     idle
221	   InterfaceNumber 1 / AlternateSetting 1     streaming */
222	ret = usb_set_interface(d->udev, 1, onoff);
223	if (ret)
224		err("usb_set_interface failed with error:%d", ret);
225
226	return ret;
227}
228
229/* DVB USB Driver stuff */
230static struct dvb_usb_device_properties ce6230_properties;
231
232static int ce6230_probe(struct usb_interface *intf,
233			const struct usb_device_id *id)
234{
235	int ret = 0;
236	struct dvb_usb_device *d = NULL;
237
238	deb_info("%s: interface:%d\n", __func__,
239		intf->cur_altsetting->desc.bInterfaceNumber);
240
241	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
242		ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE,
243			&d, adapter_nr);
244		if (ret)
245			err("init failed with error:%d\n", ret);
246	}
247
248	return ret;
249}
250
251static struct usb_device_id ce6230_table[] = {
252	{ USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) },
253	{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) },
254	{ } /* Terminating entry */
255};
256MODULE_DEVICE_TABLE(usb, ce6230_table);
257
258static struct dvb_usb_device_properties ce6230_properties = {
259	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
260
261	.usb_ctrl = DEVICE_SPECIFIC,
262	.no_reconnect = 1,
263
264	.size_of_priv = 0,
265
266	.num_adapters = 1,
267	.adapter = {
268		{
269			.frontend_attach  = ce6230_zl10353_frontend_attach,
270			.tuner_attach     = ce6230_mxl5003s_tuner_attach,
271			.stream = {
272				.type = USB_BULK,
273				.count = 6,
274				.endpoint = 0x82,
275				.u = {
276					.bulk = {
277						.buffersize = (16*512),
278					}
279				}
280			},
281		}
282	},
283
284	.power_ctrl = ce6230_power_ctrl,
285
286	.i2c_algo = &ce6230_i2c_algo,
287
288	.num_device_descs = 2,
289	.devices = {
290		{
291			.name = "Intel CE9500 reference design",
292			.cold_ids = {NULL},
293			.warm_ids = {&ce6230_table[0], NULL},
294		},
295		{
296			.name = "AVerMedia A310 USB 2.0 DVB-T tuner",
297			.cold_ids = {NULL},
298			.warm_ids = {&ce6230_table[1], NULL},
299		},
300	}
301};
302
303static struct usb_driver ce6230_driver = {
304	.name       = "dvb_usb_ce6230",
305	.probe      = ce6230_probe,
306	.disconnect = dvb_usb_device_exit,
307	.id_table   = ce6230_table,
308};
309
310/* module stuff */
311static int __init ce6230_module_init(void)
312{
313	int ret;
314	deb_info("%s:\n", __func__);
315	ret = usb_register(&ce6230_driver);
316	if (ret)
317		err("usb_register failed with error:%d", ret);
318
319	return ret;
320}
321
322static void __exit ce6230_module_exit(void)
323{
324	deb_info("%s:\n", __func__);
325	/* deregister this driver from the USB subsystem */
326	usb_deregister(&ce6230_driver);
327}
328
329module_init(ce6230_module_init);
330module_exit(ce6230_module_exit);
331
332MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
333MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0");
334MODULE_LICENSE("GPL");
335