2 * Intel CE6230 DVB USB driver
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
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.
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.
20 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
22 static int ce6230_ctrl_msg(struct dvb_usb_device
*d
, struct usb_req
*req
)
40 requesttype
= (USB_TYPE_VENDOR
| USB_DIR_IN
);
45 requesttype
= (USB_TYPE_VENDOR
| USB_DIR_OUT
);
48 dev_err(&d
->udev
->dev
, "%s: unknown command=%02x\n",
49 KBUILD_MODNAME
, req
->cmd
);
54 buf
= kmalloc(req
->data_len
, GFP_KERNEL
);
60 if (requesttype
== (USB_TYPE_VENDOR
| USB_DIR_OUT
)) {
62 memcpy(buf
, req
->data
, req
->data_len
);
63 pipe
= usb_sndctrlpipe(d
->udev
, 0);
66 pipe
= usb_rcvctrlpipe(d
->udev
, 0);
69 msleep(1); /* avoid I2C errors */
71 ret
= usb_control_msg(d
->udev
, pipe
, request
, requesttype
, value
, index
,
72 buf
, req
->data_len
, CE6230_USB_TIMEOUT
);
74 dvb_usb_dbg_usb_control_msg(d
->udev
, request
, requesttype
, value
, index
,
78 dev_err(&d
->udev
->dev
, "%s: usb_control_msg() failed=%d\n",
83 /* read request, copy returned data to return buf */
84 if (!ret
&& requesttype
== (USB_TYPE_VENDOR
| USB_DIR_IN
))
85 memcpy(req
->data
, buf
, req
->data_len
);
93 static struct zl10353_config ce6230_zl10353_config
;
95 static int ce6230_i2c_master_xfer(struct i2c_adapter
*adap
,
96 struct i2c_msg msg
[], int num
)
98 struct dvb_usb_device
*d
= i2c_get_adapdata(adap
);
105 memset(&req
, 0, sizeof(req
));
107 if (mutex_lock_interruptible(&d
->i2c_mutex
) < 0)
111 if (num
> i
+ 1 && (msg
[i
+1].flags
& I2C_M_RD
)) {
113 ce6230_zl10353_config
.demod_address
) {
114 req
.cmd
= DEMOD_READ
;
115 req
.value
= msg
[i
].addr
>> 1;
116 req
.index
= msg
[i
].buf
[0];
117 req
.data_len
= msg
[i
+1].len
;
118 req
.data
= &msg
[i
+1].buf
[0];
119 ret
= ce6230_ctrl_msg(d
, &req
);
121 dev_err(&d
->udev
->dev
, "%s: I2C read not " \
129 ce6230_zl10353_config
.demod_address
) {
130 req
.cmd
= DEMOD_WRITE
;
131 req
.value
= msg
[i
].addr
>> 1;
132 req
.index
= msg
[i
].buf
[0];
133 req
.data_len
= msg
[i
].len
-1;
134 req
.data
= &msg
[i
].buf
[1];
135 ret
= ce6230_ctrl_msg(d
, &req
);
138 req
.value
= 0x2000 + (msg
[i
].addr
>> 1);
140 req
.data_len
= msg
[i
].len
;
141 req
.data
= &msg
[i
].buf
[0];
142 ret
= ce6230_ctrl_msg(d
, &req
);
150 mutex_unlock(&d
->i2c_mutex
);
151 return ret
? ret
: i
;
154 static u32
ce6230_i2c_functionality(struct i2c_adapter
*adapter
)
159 static struct i2c_algorithm ce6230_i2c_algorithm
= {
160 .master_xfer
= ce6230_i2c_master_xfer
,
161 .functionality
= ce6230_i2c_functionality
,
164 /* Callbacks for DVB USB */
165 static struct zl10353_config ce6230_zl10353_config
= {
166 .demod_address
= 0x1e,
175 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter
*adap
)
177 struct dvb_usb_device
*d
= adap_to_d(adap
);
179 dev_dbg(&d
->udev
->dev
, "%s:\n", __func__
);
181 adap
->fe
[0] = dvb_attach(zl10353_attach
, &ce6230_zl10353_config
,
183 if (adap
->fe
[0] == NULL
)
189 static struct mxl5005s_config ce6230_mxl5003s_config
= {
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,
206 static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter
*adap
)
208 struct dvb_usb_device
*d
= adap_to_d(adap
);
211 dev_dbg(&d
->udev
->dev
, "%s:\n", __func__
);
213 ret
= dvb_attach(mxl5005s_attach
, adap
->fe
[0], &d
->i2c_adap
,
214 &ce6230_mxl5003s_config
) == NULL
? -ENODEV
: 0;
218 static int ce6230_power_ctrl(struct dvb_usb_device
*d
, int onoff
)
222 dev_dbg(&d
->udev
->dev
, "%s: onoff=%d\n", __func__
, onoff
);
224 /* InterfaceNumber 1 / AlternateSetting 0 idle
225 InterfaceNumber 1 / AlternateSetting 1 streaming */
226 ret
= usb_set_interface(d
->udev
, 1, onoff
);
228 dev_err(&d
->udev
->dev
, "%s: usb_set_interface() failed=%d\n",
229 KBUILD_MODNAME
, ret
);
234 /* DVB USB Driver stuff */
235 static struct dvb_usb_device_properties ce6230_props
= {
236 .driver_name
= KBUILD_MODNAME
,
237 .owner
= THIS_MODULE
,
238 .adapter_nr
= adapter_nr
,
239 .bInterfaceNumber
= 1,
241 .i2c_algo
= &ce6230_i2c_algorithm
,
242 .power_ctrl
= ce6230_power_ctrl
,
243 .frontend_attach
= ce6230_zl10353_frontend_attach
,
244 .tuner_attach
= ce6230_mxl5003s_tuner_attach
,
255 .buffersize
= (16 * 512),
263 static const struct usb_device_id ce6230_id_table
[] = {
264 { DVB_USB_DEVICE(USB_VID_INTEL
, USB_PID_INTEL_CE9500
,
265 &ce6230_props
, "Intel CE9500 reference design", NULL
) },
266 { DVB_USB_DEVICE(USB_VID_AVERMEDIA
, USB_PID_AVERMEDIA_A310
,
267 &ce6230_props
, "AVerMedia A310 USB 2.0 DVB-T tuner", NULL
) },
270 MODULE_DEVICE_TABLE(usb
, ce6230_id_table
);
272 static struct usb_driver ce6230_usb_driver
= {
273 .name
= KBUILD_MODNAME
,
274 .id_table
= ce6230_id_table
,
275 .probe
= dvb_usbv2_probe
,
276 .disconnect
= dvb_usbv2_disconnect
,
277 .suspend
= dvb_usbv2_suspend
,
278 .resume
= dvb_usbv2_resume
,
279 .reset_resume
= dvb_usbv2_reset_resume
,
284 module_usb_driver(ce6230_usb_driver
);
286 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
287 MODULE_DESCRIPTION("Intel CE6230 driver");
288 MODULE_LICENSE("GPL");