linux/drivers/media/usb/dvb-usb-v2/ec168.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * E3C EC168 DVB USB driver
   4 *
   5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
   6 */
   7
   8#include "ec168.h"
   9#include "ec100.h"
  10#include "mxl5005s.h"
  11
  12DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  13
  14static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)
  15{
  16        int ret;
  17        unsigned int pipe;
  18        u8 request, requesttype;
  19        u8 *buf;
  20
  21        switch (req->cmd) {
  22        case DOWNLOAD_FIRMWARE:
  23        case GPIO:
  24        case WRITE_I2C:
  25        case STREAMING_CTRL:
  26                requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
  27                request = req->cmd;
  28                break;
  29        case READ_I2C:
  30                requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
  31                request = req->cmd;
  32                break;
  33        case GET_CONFIG:
  34                requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
  35                request = CONFIG;
  36                break;
  37        case SET_CONFIG:
  38                requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
  39                request = CONFIG;
  40                break;
  41        case WRITE_DEMOD:
  42                requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
  43                request = DEMOD_RW;
  44                break;
  45        case READ_DEMOD:
  46                requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
  47                request = DEMOD_RW;
  48                break;
  49        default:
  50                dev_err(&d->udev->dev, "%s: unknown command=%02x\n",
  51                                KBUILD_MODNAME, req->cmd);
  52                ret = -EINVAL;
  53                goto error;
  54        }
  55
  56        buf = kmalloc(req->size, GFP_KERNEL);
  57        if (!buf) {
  58                ret = -ENOMEM;
  59                goto error;
  60        }
  61
  62        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
  63                /* write */
  64                memcpy(buf, req->data, req->size);
  65                pipe = usb_sndctrlpipe(d->udev, 0);
  66        } else {
  67                /* read */
  68                pipe = usb_rcvctrlpipe(d->udev, 0);
  69        }
  70
  71        msleep(1); /* avoid I2C errors */
  72
  73        ret = usb_control_msg(d->udev, pipe, request, requesttype, req->value,
  74                req->index, buf, req->size, EC168_USB_TIMEOUT);
  75
  76        dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, req->value,
  77                        req->index, buf, req->size);
  78
  79        if (ret < 0)
  80                goto err_dealloc;
  81        else
  82                ret = 0;
  83
  84        /* read request, copy returned data to return buf */
  85        if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
  86                memcpy(req->data, buf, req->size);
  87
  88        kfree(buf);
  89        return ret;
  90
  91err_dealloc:
  92        kfree(buf);
  93error:
  94        dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
  95        return ret;
  96}
  97
  98/* I2C */
  99static struct ec100_config ec168_ec100_config;
 100
 101static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 102        int num)
 103{
 104        struct dvb_usb_device *d = i2c_get_adapdata(adap);
 105        struct ec168_req req;
 106        int i = 0;
 107        int ret;
 108
 109        if (num > 2)
 110                return -EINVAL;
 111
 112        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 113                return -EAGAIN;
 114
 115        while (i < num) {
 116                if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
 117                        if (msg[i].addr == ec168_ec100_config.demod_address) {
 118                                req.cmd = READ_DEMOD;
 119                                req.value = 0;
 120                                req.index = 0xff00 + msg[i].buf[0]; /* reg */
 121                                req.size = msg[i+1].len; /* bytes to read */
 122                                req.data = &msg[i+1].buf[0];
 123                                ret = ec168_ctrl_msg(d, &req);
 124                                i += 2;
 125                        } else {
 126                                dev_err(&d->udev->dev, "%s: I2C read not " \
 127                                                "implemented\n",
 128                                                KBUILD_MODNAME);
 129                                ret = -EOPNOTSUPP;
 130                                i += 2;
 131                        }
 132                } else {
 133                        if (msg[i].addr == ec168_ec100_config.demod_address) {
 134                                req.cmd = WRITE_DEMOD;
 135                                req.value = msg[i].buf[1]; /* val */
 136                                req.index = 0xff00 + msg[i].buf[0]; /* reg */
 137                                req.size = 0;
 138                                req.data = NULL;
 139                                ret = ec168_ctrl_msg(d, &req);
 140                                i += 1;
 141                        } else {
 142                                req.cmd = WRITE_I2C;
 143                                req.value = msg[i].buf[0]; /* val */
 144                                req.index = 0x0100 + msg[i].addr; /* I2C addr */
 145                                req.size = msg[i].len-1;
 146                                req.data = &msg[i].buf[1];
 147                                ret = ec168_ctrl_msg(d, &req);
 148                                i += 1;
 149                        }
 150                }
 151                if (ret)
 152                        goto error;
 153
 154        }
 155        ret = i;
 156
 157error:
 158        mutex_unlock(&d->i2c_mutex);
 159        return ret;
 160}
 161
 162static u32 ec168_i2c_func(struct i2c_adapter *adapter)
 163{
 164        return I2C_FUNC_I2C;
 165}
 166
 167static struct i2c_algorithm ec168_i2c_algo = {
 168        .master_xfer   = ec168_i2c_xfer,
 169        .functionality = ec168_i2c_func,
 170};
 171
 172/* Callbacks for DVB USB */
 173static int ec168_identify_state(struct dvb_usb_device *d, const char **name)
 174{
 175        int ret;
 176        u8 reply;
 177        struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};
 178        dev_dbg(&d->udev->dev, "%s:\n", __func__);
 179
 180        ret = ec168_ctrl_msg(d, &req);
 181        if (ret)
 182                goto error;
 183
 184        dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply);
 185
 186        if (reply == 0x01)
 187                ret = WARM;
 188        else
 189                ret = COLD;
 190
 191        return ret;
 192error:
 193        dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 194        return ret;
 195}
 196
 197static int ec168_download_firmware(struct dvb_usb_device *d,
 198                const struct firmware *fw)
 199{
 200        int ret, len, remaining;
 201        struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};
 202        dev_dbg(&d->udev->dev, "%s:\n", __func__);
 203
 204        #define LEN_MAX 2048 /* max packet size */
 205        for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
 206                len = remaining;
 207                if (len > LEN_MAX)
 208                        len = LEN_MAX;
 209
 210                req.size = len;
 211                req.data = (u8 *) &fw->data[fw->size - remaining];
 212                req.index = fw->size - remaining;
 213
 214                ret = ec168_ctrl_msg(d, &req);
 215                if (ret) {
 216                        dev_err(&d->udev->dev,
 217                                        "%s: firmware download failed=%d\n",
 218                                        KBUILD_MODNAME, ret);
 219                        goto error;
 220                }
 221        }
 222
 223        req.size = 0;
 224
 225        /* set "warm"? */
 226        req.cmd = SET_CONFIG;
 227        req.value = 0;
 228        req.index = 0x0001;
 229        ret = ec168_ctrl_msg(d, &req);
 230        if (ret)
 231                goto error;
 232
 233        /* really needed - no idea what does */
 234        req.cmd = GPIO;
 235        req.value = 0;
 236        req.index = 0x0206;
 237        ret = ec168_ctrl_msg(d, &req);
 238        if (ret)
 239                goto error;
 240
 241        /* activate tuner I2C? */
 242        req.cmd = WRITE_I2C;
 243        req.value = 0;
 244        req.index = 0x00c6;
 245        ret = ec168_ctrl_msg(d, &req);
 246        if (ret)
 247                goto error;
 248
 249        return ret;
 250error:
 251        dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 252        return ret;
 253}
 254
 255static struct ec100_config ec168_ec100_config = {
 256        .demod_address = 0xff, /* not real address, demod is integrated */
 257};
 258
 259static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
 260{
 261        struct dvb_usb_device *d = adap_to_d(adap);
 262        dev_dbg(&d->udev->dev, "%s:\n", __func__);
 263
 264        adap->fe[0] = dvb_attach(ec100_attach, &ec168_ec100_config,
 265                        &d->i2c_adap);
 266        if (adap->fe[0] == NULL)
 267                return -ENODEV;
 268
 269        return 0;
 270}
 271
 272static struct mxl5005s_config ec168_mxl5003s_config = {
 273        .i2c_address     = 0xc6,
 274        .if_freq         = IF_FREQ_4570000HZ,
 275        .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
 276        .agc_mode        = MXL_SINGLE_AGC,
 277        .tracking_filter = MXL_TF_OFF,
 278        .rssi_enable     = MXL_RSSI_ENABLE,
 279        .cap_select      = MXL_CAP_SEL_ENABLE,
 280        .div_out         = MXL_DIV_OUT_4,
 281        .clock_out       = MXL_CLOCK_OUT_DISABLE,
 282        .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
 283        .top             = MXL5005S_TOP_25P2,
 284        .mod_mode        = MXL_DIGITAL_MODE,
 285        .if_mode         = MXL_ZERO_IF,
 286        .AgcMasterByte   = 0x00,
 287};
 288
 289static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 290{
 291        struct dvb_usb_device *d = adap_to_d(adap);
 292        dev_dbg(&d->udev->dev, "%s:\n", __func__);
 293
 294        return dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap,
 295                        &ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
 296}
 297
 298static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff)
 299{
 300        struct dvb_usb_device *d = fe_to_d(fe);
 301        struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};
 302        dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
 303
 304        if (onoff)
 305                req.index = 0x0102;
 306        return ec168_ctrl_msg(d, &req);
 307}
 308
 309/* DVB USB Driver stuff */
 310/* bInterfaceNumber 0 is HID
 311 * bInterfaceNumber 1 is DVB-T */
 312static struct dvb_usb_device_properties ec168_props = {
 313        .driver_name = KBUILD_MODNAME,
 314        .owner = THIS_MODULE,
 315        .adapter_nr = adapter_nr,
 316        .bInterfaceNumber = 1,
 317
 318        .identify_state = ec168_identify_state,
 319        .firmware = EC168_FIRMWARE,
 320        .download_firmware = ec168_download_firmware,
 321
 322        .i2c_algo = &ec168_i2c_algo,
 323        .frontend_attach = ec168_ec100_frontend_attach,
 324        .tuner_attach = ec168_mxl5003s_tuner_attach,
 325        .streaming_ctrl = ec168_streaming_ctrl,
 326
 327        .num_adapters = 1,
 328        .adapter = {
 329                {
 330                        .stream = DVB_USB_STREAM_BULK(0x82, 6, 32 * 512),
 331                }
 332        },
 333};
 334
 335static const struct dvb_usb_driver_info ec168_driver_info = {
 336        .name = "E3C EC168 reference design",
 337        .props = &ec168_props,
 338};
 339
 340static const struct usb_device_id ec168_id[] = {
 341        { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168),
 342                .driver_info = (kernel_ulong_t) &ec168_driver_info },
 343        { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2),
 344                .driver_info = (kernel_ulong_t) &ec168_driver_info },
 345        { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3),
 346                .driver_info = (kernel_ulong_t) &ec168_driver_info },
 347        { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4),
 348                .driver_info = (kernel_ulong_t) &ec168_driver_info },
 349        { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5),
 350                .driver_info = (kernel_ulong_t) &ec168_driver_info },
 351        {}
 352};
 353MODULE_DEVICE_TABLE(usb, ec168_id);
 354
 355static struct usb_driver ec168_driver = {
 356        .name = KBUILD_MODNAME,
 357        .id_table = ec168_id,
 358        .probe = dvb_usbv2_probe,
 359        .disconnect = dvb_usbv2_disconnect,
 360        .suspend = dvb_usbv2_suspend,
 361        .resume = dvb_usbv2_resume,
 362        .no_dynamic_id = 1,
 363        .soft_unbind = 1,
 364};
 365
 366module_usb_driver(ec168_driver);
 367
 368MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 369MODULE_DESCRIPTION("E3C EC168 driver");
 370MODULE_LICENSE("GPL");
 371MODULE_FIRMWARE(EC168_FIRMWARE);
 372