1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Intel CE6230 DVB USB driver 4 * 5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 6 */ 7 8 #include "ce6230.h" 9 10 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 11 12 static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) 13 { 14 int ret; 15 unsigned int pipe; 16 u8 request; 17 u8 requesttype; 18 u16 value; 19 u16 index; 20 u8 *buf; 21 22 request = req->cmd; 23 value = req->value; 24 index = req->index; 25 26 switch (req->cmd) { 27 case I2C_READ: 28 case DEMOD_READ: 29 case REG_READ: 30 requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); 31 break; 32 case I2C_WRITE: 33 case DEMOD_WRITE: 34 case REG_WRITE: 35 requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); 36 break; 37 default: 38 dev_err(&d->udev->dev, "%s: unknown command=%02x\n", 39 KBUILD_MODNAME, req->cmd); 40 ret = -EINVAL; 41 goto error; 42 } 43 44 buf = kmalloc(req->data_len, GFP_KERNEL); 45 if (!buf) { 46 ret = -ENOMEM; 47 goto error; 48 } 49 50 if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { 51 /* write */ 52 memcpy(buf, req->data, req->data_len); 53 pipe = usb_sndctrlpipe(d->udev, 0); 54 } else { 55 /* read */ 56 pipe = usb_rcvctrlpipe(d->udev, 0); 57 } 58 59 msleep(1); /* avoid I2C errors */ 60 61 ret = usb_control_msg(d->udev, pipe, request, requesttype, value, index, 62 buf, req->data_len, CE6230_USB_TIMEOUT); 63 64 dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, value, index, 65 buf, req->data_len); 66 67 if (ret < 0) 68 dev_err(&d->udev->dev, "%s: usb_control_msg() failed=%d\n", 69 KBUILD_MODNAME, ret); 70 else 71 ret = 0; 72 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); 76 77 kfree(buf); 78 error: 79 return ret; 80 } 81 82 /* I2C */ 83 static struct zl10353_config ce6230_zl10353_config; 84 85 static int ce6230_i2c_master_xfer(struct i2c_adapter *adap, 86 struct i2c_msg msg[], int num) 87 { 88 struct dvb_usb_device *d = i2c_get_adapdata(adap); 89 int ret = 0, i = 0; 90 struct usb_req req; 91 92 if (num > 2) 93 return -EOPNOTSUPP; 94 95 memset(&req, 0, sizeof(req)); 96 97 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 98 return -EAGAIN; 99 100 while (i < num) { 101 if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { 102 if (msg[i].addr == 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); 110 } else { 111 dev_err(&d->udev->dev, "%s: I2C read not " \ 112 "implemented\n", 113 KBUILD_MODNAME); 114 ret = -EOPNOTSUPP; 115 } 116 i += 2; 117 } else { 118 if (msg[i].addr == 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); 126 } else { 127 req.cmd = I2C_WRITE; 128 req.value = 0x2000 + (msg[i].addr >> 1); 129 req.index = 0x0000; 130 req.data_len = msg[i].len; 131 req.data = &msg[i].buf[0]; 132 ret = ce6230_ctrl_msg(d, &req); 133 } 134 i += 1; 135 } 136 if (ret) 137 break; 138 } 139 140 mutex_unlock(&d->i2c_mutex); 141 return ret ? ret : i; 142 } 143 144 static u32 ce6230_i2c_functionality(struct i2c_adapter *adapter) 145 { 146 return I2C_FUNC_I2C; 147 } 148 149 static struct i2c_algorithm ce6230_i2c_algorithm = { 150 .master_xfer = ce6230_i2c_master_xfer, 151 .functionality = ce6230_i2c_functionality, 152 }; 153 154 /* Callbacks for DVB USB */ 155 static struct zl10353_config ce6230_zl10353_config = { 156 .demod_address = 0x1e, 157 .adc_clock = 450000, 158 .if2 = 45700, 159 .no_tuner = 1, 160 .parallel_ts = 1, 161 .clock_ctl_1 = 0x34, 162 .pll_0 = 0x0e, 163 }; 164 165 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap) 166 { 167 struct dvb_usb_device *d = adap_to_d(adap); 168 169 dev_dbg(&d->udev->dev, "%s:\n", __func__); 170 171 adap->fe[0] = dvb_attach(zl10353_attach, &ce6230_zl10353_config, 172 &d->i2c_adap); 173 if (adap->fe[0] == NULL) 174 return -ENODEV; 175 176 return 0; 177 } 178 179 static struct mxl5005s_config ce6230_mxl5003s_config = { 180 .i2c_address = 0xc6, 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, 194 }; 195 196 static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) 197 { 198 struct dvb_usb_device *d = adap_to_d(adap); 199 int ret; 200 201 dev_dbg(&d->udev->dev, "%s:\n", __func__); 202 203 ret = dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap, 204 &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0; 205 return ret; 206 } 207 208 static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff) 209 { 210 int ret; 211 212 dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); 213 214 /* InterfaceNumber 1 / AlternateSetting 0 idle 215 InterfaceNumber 1 / AlternateSetting 1 streaming */ 216 ret = usb_set_interface(d->udev, 1, onoff); 217 if (ret) 218 dev_err(&d->udev->dev, "%s: usb_set_interface() failed=%d\n", 219 KBUILD_MODNAME, ret); 220 221 return ret; 222 } 223 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, 230 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, 235 236 .num_adapters = 1, 237 .adapter = { 238 { 239 .stream = { 240 .type = USB_BULK, 241 .count = 6, 242 .endpoint = 0x82, 243 .u = { 244 .bulk = { 245 .buffersize = (16 * 512), 246 } 247 } 248 }, 249 } 250 }, 251 }; 252 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) }, 258 { } 259 }; 260 MODULE_DEVICE_TABLE(usb, ce6230_id_table); 261 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, 270 .no_dynamic_id = 1, 271 .soft_unbind = 1, 272 }; 273 274 module_usb_driver(ce6230_usb_driver); 275 276 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 277 MODULE_DESCRIPTION("Intel CE6230 driver"); 278 MODULE_LICENSE("GPL"); 279