1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Intel CE6230 DVB USB driver
5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
10 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
);
12 static int ce6230_ctrl_msg(struct dvb_usb_device
*d
, struct usb_req
*req
)
30 requesttype
= (USB_TYPE_VENDOR
| USB_DIR_IN
);
35 requesttype
= (USB_TYPE_VENDOR
| USB_DIR_OUT
);
38 dev_err(&d
->udev
->dev
, "%s: unknown command=%02x\n",
39 KBUILD_MODNAME
, req
->cmd
);
44 buf
= kmalloc(req
->data_len
, GFP_KERNEL
);
50 if (requesttype
== (USB_TYPE_VENDOR
| USB_DIR_OUT
)) {
52 memcpy(buf
, req
->data
, req
->data_len
);
53 pipe
= usb_sndctrlpipe(d
->udev
, 0);
56 pipe
= usb_rcvctrlpipe(d
->udev
, 0);
59 msleep(1); /* avoid I2C errors */
61 ret
= usb_control_msg(d
->udev
, pipe
, request
, requesttype
, value
, index
,
62 buf
, req
->data_len
, CE6230_USB_TIMEOUT
);
64 dvb_usb_dbg_usb_control_msg(d
->udev
, request
, requesttype
, value
, index
,
68 dev_err(&d
->udev
->dev
, "%s: usb_control_msg() failed=%d\n",
73 /* read request, copy returned data to return buf */
74 if (!ret
&& requesttype
== (USB_TYPE_VENDOR
| USB_DIR_IN
))
75 memcpy(req
->data
, buf
, req
->data_len
);
83 static struct zl10353_config ce6230_zl10353_config
;
85 static int ce6230_i2c_master_xfer(struct i2c_adapter
*adap
,
86 struct i2c_msg msg
[], int num
)
88 struct dvb_usb_device
*d
= i2c_get_adapdata(adap
);
95 memset(&req
, 0, sizeof(req
));
97 if (mutex_lock_interruptible(&d
->i2c_mutex
) < 0)
101 if (num
> i
+ 1 && (msg
[i
+1].flags
& I2C_M_RD
)) {
103 ce6230_zl10353_config
.demod_address
) {
104 req
.cmd
= DEMOD_READ
;
105 req
.value
= msg
[i
].addr
>> 1;
106 req
.index
= msg
[i
].buf
[0];
107 req
.data_len
= msg
[i
+1].len
;
108 req
.data
= &msg
[i
+1].buf
[0];
109 ret
= ce6230_ctrl_msg(d
, &req
);
111 dev_err(&d
->udev
->dev
, "%s: I2C read not " \
119 ce6230_zl10353_config
.demod_address
) {
120 req
.cmd
= DEMOD_WRITE
;
121 req
.value
= msg
[i
].addr
>> 1;
122 req
.index
= msg
[i
].buf
[0];
123 req
.data_len
= msg
[i
].len
-1;
124 req
.data
= &msg
[i
].buf
[1];
125 ret
= ce6230_ctrl_msg(d
, &req
);
128 req
.value
= 0x2000 + (msg
[i
].addr
>> 1);
130 req
.data_len
= msg
[i
].len
;
131 req
.data
= &msg
[i
].buf
[0];
132 ret
= ce6230_ctrl_msg(d
, &req
);
140 mutex_unlock(&d
->i2c_mutex
);
141 return ret
? ret
: i
;
144 static u32
ce6230_i2c_functionality(struct i2c_adapter
*adapter
)
149 static struct i2c_algorithm ce6230_i2c_algorithm
= {
150 .master_xfer
= ce6230_i2c_master_xfer
,
151 .functionality
= ce6230_i2c_functionality
,
154 /* Callbacks for DVB USB */
155 static struct zl10353_config ce6230_zl10353_config
= {
156 .demod_address
= 0x1e,
165 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter
*adap
)
167 struct dvb_usb_device
*d
= adap_to_d(adap
);
169 dev_dbg(&d
->udev
->dev
, "%s:\n", __func__
);
171 adap
->fe
[0] = dvb_attach(zl10353_attach
, &ce6230_zl10353_config
,
173 if (adap
->fe
[0] == NULL
)
179 static struct mxl5005s_config ce6230_mxl5003s_config
= {
181 .if_freq
= IF_FREQ_4570000HZ
,
182 .xtal_freq
= CRYSTAL_FREQ_16000000HZ
,
183 .agc_mode
= MXL_SINGLE_AGC
,
184 .tracking_filter
= MXL_TF_DEFAULT
,
185 .rssi_enable
= MXL_RSSI_ENABLE
,
186 .cap_select
= MXL_CAP_SEL_ENABLE
,
187 .div_out
= MXL_DIV_OUT_4
,
188 .clock_out
= MXL_CLOCK_OUT_DISABLE
,
189 .output_load
= MXL5005S_IF_OUTPUT_LOAD_200_OHM
,
190 .top
= MXL5005S_TOP_25P2
,
191 .mod_mode
= MXL_DIGITAL_MODE
,
192 .if_mode
= MXL_ZERO_IF
,
193 .AgcMasterByte
= 0x00,
196 static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter
*adap
)
198 struct dvb_usb_device
*d
= adap_to_d(adap
);
201 dev_dbg(&d
->udev
->dev
, "%s:\n", __func__
);
203 ret
= dvb_attach(mxl5005s_attach
, adap
->fe
[0], &d
->i2c_adap
,
204 &ce6230_mxl5003s_config
) == NULL
? -ENODEV
: 0;
208 static int ce6230_power_ctrl(struct dvb_usb_device
*d
, int onoff
)
212 dev_dbg(&d
->udev
->dev
, "%s: onoff=%d\n", __func__
, onoff
);
214 /* InterfaceNumber 1 / AlternateSetting 0 idle
215 InterfaceNumber 1 / AlternateSetting 1 streaming */
216 ret
= usb_set_interface(d
->udev
, 1, onoff
);
218 dev_err(&d
->udev
->dev
, "%s: usb_set_interface() failed=%d\n",
219 KBUILD_MODNAME
, ret
);
224 /* DVB USB Driver stuff */
225 static struct dvb_usb_device_properties ce6230_props
= {
226 .driver_name
= KBUILD_MODNAME
,
227 .owner
= THIS_MODULE
,
228 .adapter_nr
= adapter_nr
,
229 .bInterfaceNumber
= 1,
231 .i2c_algo
= &ce6230_i2c_algorithm
,
232 .power_ctrl
= ce6230_power_ctrl
,
233 .frontend_attach
= ce6230_zl10353_frontend_attach
,
234 .tuner_attach
= ce6230_mxl5003s_tuner_attach
,
245 .buffersize
= (16 * 512),
253 static const struct usb_device_id ce6230_id_table
[] = {
254 { DVB_USB_DEVICE(USB_VID_INTEL
, USB_PID_INTEL_CE9500
,
255 &ce6230_props
, "Intel CE9500 reference design", NULL
) },
256 { DVB_USB_DEVICE(USB_VID_AVERMEDIA
, USB_PID_AVERMEDIA_A310
,
257 &ce6230_props
, "AVerMedia A310 USB 2.0 DVB-T tuner", NULL
) },
260 MODULE_DEVICE_TABLE(usb
, ce6230_id_table
);
262 static struct usb_driver ce6230_usb_driver
= {
263 .name
= KBUILD_MODNAME
,
264 .id_table
= ce6230_id_table
,
265 .probe
= dvb_usbv2_probe
,
266 .disconnect
= dvb_usbv2_disconnect
,
267 .suspend
= dvb_usbv2_suspend
,
268 .resume
= dvb_usbv2_resume
,
269 .reset_resume
= dvb_usbv2_reset_resume
,
274 module_usb_driver(ce6230_usb_driver
);
276 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
277 MODULE_DESCRIPTION("Intel CE6230 driver");
278 MODULE_LICENSE("GPL");