root/drivers/media/usb/dvb-usb/dtv5100.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dtv5100_i2c_msg
  2. dtv5100_i2c_xfer
  3. dtv5100_i2c_func
  4. dtv5100_frontend_attach
  5. dtv5100_tuner_attach
  6. dtv5100_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
   4  *
   5  * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
   6  * http://royale.zerezo.com/dtv5100/
   7  *
   8  * Inspired by gl861.c and au6610.c drivers
   9  */
  10 
  11 #include "dtv5100.h"
  12 #include "zl10353.h"
  13 #include "qt1010.h"
  14 
  15 /* debug */
  16 static int dvb_usb_dtv5100_debug;
  17 module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
  18 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
  19 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  20 
  21 struct dtv5100_state {
  22         unsigned char data[80];
  23 };
  24 
  25 static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
  26                            u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
  27 {
  28         struct dtv5100_state *st = d->priv;
  29         u8 request;
  30         u8 type;
  31         u16 value;
  32         u16 index;
  33 
  34         switch (wlen) {
  35         case 1:
  36                 /* write { reg }, read { value } */
  37                 request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
  38                                                         DTV5100_TUNER_READ);
  39                 type = USB_TYPE_VENDOR | USB_DIR_IN;
  40                 value = 0;
  41                 break;
  42         case 2:
  43                 /* write { reg, value } */
  44                 request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
  45                                                         DTV5100_TUNER_WRITE);
  46                 type = USB_TYPE_VENDOR | USB_DIR_OUT;
  47                 value = wbuf[1];
  48                 break;
  49         default:
  50                 warn("wlen = %x, aborting.", wlen);
  51                 return -EINVAL;
  52         }
  53         index = (addr << 8) + wbuf[0];
  54 
  55         memcpy(st->data, rbuf, rlen);
  56         msleep(1); /* avoid I2C errors */
  57         return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
  58                                type, value, index, st->data, rlen,
  59                                DTV5100_USB_TIMEOUT);
  60 }
  61 
  62 /* I2C */
  63 static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
  64                             int num)
  65 {
  66         struct dvb_usb_device *d = i2c_get_adapdata(adap);
  67         int i;
  68 
  69         if (num > 2)
  70                 return -EINVAL;
  71 
  72         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
  73                 return -EAGAIN;
  74 
  75         for (i = 0; i < num; i++) {
  76                 /* write/read request */
  77                 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
  78                         if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
  79                                             msg[i].len, msg[i+1].buf,
  80                                             msg[i+1].len) < 0)
  81                                 break;
  82                         i++;
  83                 } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
  84                                            msg[i].len, NULL, 0) < 0)
  85                                 break;
  86         }
  87 
  88         mutex_unlock(&d->i2c_mutex);
  89         return i;
  90 }
  91 
  92 static u32 dtv5100_i2c_func(struct i2c_adapter *adapter)
  93 {
  94         return I2C_FUNC_I2C;
  95 }
  96 
  97 static struct i2c_algorithm dtv5100_i2c_algo = {
  98         .master_xfer   = dtv5100_i2c_xfer,
  99         .functionality = dtv5100_i2c_func,
 100 };
 101 
 102 /* Callbacks for DVB USB */
 103 static struct zl10353_config dtv5100_zl10353_config = {
 104         .demod_address = DTV5100_DEMOD_ADDR,
 105         .no_tuner = 1,
 106         .parallel_ts = 1,
 107 };
 108 
 109 static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
 110 {
 111         adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
 112                               &adap->dev->i2c_adap);
 113         if (adap->fe_adap[0].fe == NULL)
 114                 return -EIO;
 115 
 116         /* disable i2c gate, or it won't work... is this safe? */
 117         adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
 118 
 119         return 0;
 120 }
 121 
 122 static struct qt1010_config dtv5100_qt1010_config = {
 123         .i2c_address = DTV5100_TUNER_ADDR
 124 };
 125 
 126 static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
 127 {
 128         return dvb_attach(qt1010_attach,
 129                           adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 130                           &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
 131 }
 132 
 133 /* DVB USB Driver stuff */
 134 static struct dvb_usb_device_properties dtv5100_properties;
 135 
 136 static int dtv5100_probe(struct usb_interface *intf,
 137                          const struct usb_device_id *id)
 138 {
 139         int i, ret;
 140         struct usb_device *udev = interface_to_usbdev(intf);
 141 
 142         /* initialize non qt1010/zl10353 part? */
 143         for (i = 0; dtv5100_init[i].request; i++) {
 144                 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 145                                       dtv5100_init[i].request,
 146                                       USB_TYPE_VENDOR | USB_DIR_OUT,
 147                                       dtv5100_init[i].value,
 148                                       dtv5100_init[i].index, NULL, 0,
 149                                       DTV5100_USB_TIMEOUT);
 150                 if (ret)
 151                         return ret;
 152         }
 153 
 154         ret = dvb_usb_device_init(intf, &dtv5100_properties,
 155                                   THIS_MODULE, NULL, adapter_nr);
 156         if (ret)
 157                 return ret;
 158 
 159         return 0;
 160 }
 161 
 162 static struct usb_device_id dtv5100_table[] = {
 163         { USB_DEVICE(0x06be, 0xa232) },
 164         { }             /* Terminating entry */
 165 };
 166 MODULE_DEVICE_TABLE(usb, dtv5100_table);
 167 
 168 static struct dvb_usb_device_properties dtv5100_properties = {
 169         .caps = DVB_USB_IS_AN_I2C_ADAPTER,
 170         .usb_ctrl = DEVICE_SPECIFIC,
 171 
 172         .size_of_priv = sizeof(struct dtv5100_state),
 173 
 174         .num_adapters = 1,
 175         .adapter = {{
 176                 .num_frontends = 1,
 177                 .fe = {{
 178                 .frontend_attach = dtv5100_frontend_attach,
 179                 .tuner_attach    = dtv5100_tuner_attach,
 180 
 181                 .stream = {
 182                         .type = USB_BULK,
 183                         .count = 8,
 184                         .endpoint = 0x82,
 185                         .u = {
 186                                 .bulk = {
 187                                         .buffersize = 4096,
 188                                 }
 189                         }
 190                 },
 191                 }},
 192         } },
 193 
 194         .i2c_algo = &dtv5100_i2c_algo,
 195 
 196         .num_device_descs = 1,
 197         .devices = {
 198                 {
 199                         .name = "AME DTV-5100 USB2.0 DVB-T",
 200                         .cold_ids = { NULL },
 201                         .warm_ids = { &dtv5100_table[0], NULL },
 202                 },
 203         }
 204 };
 205 
 206 static struct usb_driver dtv5100_driver = {
 207         .name           = "dvb_usb_dtv5100",
 208         .probe          = dtv5100_probe,
 209         .disconnect     = dvb_usb_device_exit,
 210         .id_table       = dtv5100_table,
 211 };
 212 
 213 module_usb_driver(dtv5100_driver);
 214 
 215 MODULE_AUTHOR(DRIVER_AUTHOR);
 216 MODULE_DESCRIPTION(DRIVER_DESC);
 217 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */