Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
0004  *
0005  * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
0006  * http://royale.zerezo.com/dtv5100/
0007  *
0008  * Inspired by gl861.c and au6610.c drivers
0009  */
0010 
0011 #include "dtv5100.h"
0012 #include "zl10353.h"
0013 #include "qt1010.h"
0014 
0015 /* debug */
0016 static int dvb_usb_dtv5100_debug;
0017 module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
0018 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
0019 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0020 
0021 struct dtv5100_state {
0022     unsigned char data[80];
0023 };
0024 
0025 static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
0026                u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
0027 {
0028     struct dtv5100_state *st = d->priv;
0029     unsigned int pipe;
0030     u8 request;
0031     u8 type;
0032     u16 value;
0033     u16 index;
0034 
0035     switch (wlen) {
0036     case 1:
0037         /* write { reg }, read { value } */
0038         pipe = usb_rcvctrlpipe(d->udev, 0);
0039         request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
0040                             DTV5100_TUNER_READ);
0041         type = USB_TYPE_VENDOR | USB_DIR_IN;
0042         value = 0;
0043         break;
0044     case 2:
0045         /* write { reg, value } */
0046         pipe = usb_sndctrlpipe(d->udev, 0);
0047         request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
0048                             DTV5100_TUNER_WRITE);
0049         type = USB_TYPE_VENDOR | USB_DIR_OUT;
0050         value = wbuf[1];
0051         break;
0052     default:
0053         warn("wlen = %x, aborting.", wlen);
0054         return -EINVAL;
0055     }
0056     index = (addr << 8) + wbuf[0];
0057 
0058     memcpy(st->data, rbuf, rlen);
0059     msleep(1); /* avoid I2C errors */
0060     return usb_control_msg(d->udev, pipe, request,
0061                    type, value, index, st->data, rlen,
0062                    DTV5100_USB_TIMEOUT);
0063 }
0064 
0065 /* I2C */
0066 static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
0067                 int num)
0068 {
0069     struct dvb_usb_device *d = i2c_get_adapdata(adap);
0070     int i;
0071 
0072     if (num > 2)
0073         return -EINVAL;
0074 
0075     if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
0076         return -EAGAIN;
0077 
0078     for (i = 0; i < num; i++) {
0079         /* write/read request */
0080         if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
0081             if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
0082                         msg[i].len, msg[i+1].buf,
0083                         msg[i+1].len) < 0)
0084                 break;
0085             i++;
0086         } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
0087                        msg[i].len, NULL, 0) < 0)
0088                 break;
0089     }
0090 
0091     mutex_unlock(&d->i2c_mutex);
0092     return i;
0093 }
0094 
0095 static u32 dtv5100_i2c_func(struct i2c_adapter *adapter)
0096 {
0097     return I2C_FUNC_I2C;
0098 }
0099 
0100 static struct i2c_algorithm dtv5100_i2c_algo = {
0101     .master_xfer   = dtv5100_i2c_xfer,
0102     .functionality = dtv5100_i2c_func,
0103 };
0104 
0105 /* Callbacks for DVB USB */
0106 static struct zl10353_config dtv5100_zl10353_config = {
0107     .demod_address = DTV5100_DEMOD_ADDR,
0108     .no_tuner = 1,
0109     .parallel_ts = 1,
0110 };
0111 
0112 static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
0113 {
0114     adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
0115                   &adap->dev->i2c_adap);
0116     if (adap->fe_adap[0].fe == NULL)
0117         return -EIO;
0118 
0119     /* disable i2c gate, or it won't work... is this safe? */
0120     adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
0121 
0122     return 0;
0123 }
0124 
0125 static struct qt1010_config dtv5100_qt1010_config = {
0126     .i2c_address = DTV5100_TUNER_ADDR
0127 };
0128 
0129 static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
0130 {
0131     return dvb_attach(qt1010_attach,
0132               adap->fe_adap[0].fe, &adap->dev->i2c_adap,
0133               &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
0134 }
0135 
0136 /* DVB USB Driver stuff */
0137 static struct dvb_usb_device_properties dtv5100_properties;
0138 
0139 static int dtv5100_probe(struct usb_interface *intf,
0140              const struct usb_device_id *id)
0141 {
0142     int i, ret;
0143     struct usb_device *udev = interface_to_usbdev(intf);
0144 
0145     /* initialize non qt1010/zl10353 part? */
0146     for (i = 0; dtv5100_init[i].request; i++) {
0147         ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0148                       dtv5100_init[i].request,
0149                       USB_TYPE_VENDOR | USB_DIR_OUT,
0150                       dtv5100_init[i].value,
0151                       dtv5100_init[i].index, NULL, 0,
0152                       DTV5100_USB_TIMEOUT);
0153         if (ret)
0154             return ret;
0155     }
0156 
0157     ret = dvb_usb_device_init(intf, &dtv5100_properties,
0158                   THIS_MODULE, NULL, adapter_nr);
0159     if (ret)
0160         return ret;
0161 
0162     return 0;
0163 }
0164 
0165 enum {
0166     AME_DTV5100,
0167 };
0168 
0169 static struct usb_device_id dtv5100_table[] = {
0170     DVB_USB_DEV(AME, AME_DTV5100),
0171     { }
0172 };
0173 
0174 MODULE_DEVICE_TABLE(usb, dtv5100_table);
0175 
0176 static struct dvb_usb_device_properties dtv5100_properties = {
0177     .caps = DVB_USB_IS_AN_I2C_ADAPTER,
0178     .usb_ctrl = DEVICE_SPECIFIC,
0179 
0180     .size_of_priv = sizeof(struct dtv5100_state),
0181 
0182     .num_adapters = 1,
0183     .adapter = {{
0184         .num_frontends = 1,
0185         .fe = {{
0186         .frontend_attach = dtv5100_frontend_attach,
0187         .tuner_attach    = dtv5100_tuner_attach,
0188 
0189         .stream = {
0190             .type = USB_BULK,
0191             .count = 8,
0192             .endpoint = 0x82,
0193             .u = {
0194                 .bulk = {
0195                     .buffersize = 4096,
0196                 }
0197             }
0198         },
0199         }},
0200     } },
0201 
0202     .i2c_algo = &dtv5100_i2c_algo,
0203 
0204     .num_device_descs = 1,
0205     .devices = {
0206         {
0207             .name = "AME DTV-5100 USB2.0 DVB-T",
0208             .cold_ids = { NULL },
0209             .warm_ids = { &dtv5100_table[AME_DTV5100], NULL },
0210         },
0211     }
0212 };
0213 
0214 static struct usb_driver dtv5100_driver = {
0215     .name       = "dvb_usb_dtv5100",
0216     .probe      = dtv5100_probe,
0217     .disconnect = dvb_usb_device_exit,
0218     .id_table   = dtv5100_table,
0219 };
0220 
0221 module_usb_driver(dtv5100_driver);
0222 
0223 MODULE_AUTHOR(DRIVER_AUTHOR);
0224 MODULE_DESCRIPTION(DRIVER_DESC);
0225 MODULE_LICENSE("GPL");