Path: blob/master/drivers/media/dvb/dvb-usb/ec168.c
15111 views
/*1* E3C EC168 DVB USB driver2*3* Copyright (C) 2009 Antti Palosaari <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.18*19*/2021#include "ec168.h"22#include "ec100.h"23#include "mxl5005s.h"2425/* debug */26static int dvb_usb_ec168_debug;27module_param_named(debug, dvb_usb_ec168_debug, int, 0644);28MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);29DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);3031static struct ec100_config ec168_ec100_config;3233static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)34{35int ret;36unsigned int pipe;37u8 request, requesttype;38u8 *buf;39404142switch (req->cmd) {43case DOWNLOAD_FIRMWARE:44case GPIO:45case WRITE_I2C:46case STREAMING_CTRL:47requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);48request = req->cmd;49break;50case READ_I2C:51requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);52request = req->cmd;53break;54case GET_CONFIG:55requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);56request = CONFIG;57break;58case SET_CONFIG:59requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);60request = CONFIG;61break;62case WRITE_DEMOD:63requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);64request = DEMOD_RW;65break;66case READ_DEMOD:67requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);68request = DEMOD_RW;69break;70default:71err("unknown command:%02x", req->cmd);72ret = -EPERM;73goto error;74}7576buf = kmalloc(req->size, GFP_KERNEL);77if (!buf) {78ret = -ENOMEM;79goto error;80}8182if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {83/* write */84memcpy(buf, req->data, req->size);85pipe = usb_sndctrlpipe(udev, 0);86} else {87/* read */88pipe = usb_rcvctrlpipe(udev, 0);89}9091msleep(1); /* avoid I2C errors */9293ret = usb_control_msg(udev, pipe, request, requesttype, req->value,94req->index, buf, req->size, EC168_USB_TIMEOUT);9596ec168_debug_dump(request, requesttype, req->value, req->index, buf,97req->size, deb_xfer);9899if (ret < 0)100goto err_dealloc;101else102ret = 0;103104/* read request, copy returned data to return buf */105if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))106memcpy(req->data, buf, req->size);107108kfree(buf);109return ret;110111err_dealloc:112kfree(buf);113error:114deb_info("%s: failed:%d\n", __func__, ret);115return ret;116}117118static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)119{120return ec168_rw_udev(d->udev, req);121}122123/* I2C */124static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],125int num)126{127struct dvb_usb_device *d = i2c_get_adapdata(adap);128struct ec168_req req;129int i = 0;130int ret;131132if (num > 2)133return -EINVAL;134135if (mutex_lock_interruptible(&d->i2c_mutex) < 0)136return -EAGAIN;137138while (i < num) {139if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {140if (msg[i].addr == ec168_ec100_config.demod_address) {141req.cmd = READ_DEMOD;142req.value = 0;143req.index = 0xff00 + msg[i].buf[0]; /* reg */144req.size = msg[i+1].len; /* bytes to read */145req.data = &msg[i+1].buf[0];146ret = ec168_ctrl_msg(d, &req);147i += 2;148} else {149err("I2C read not implemented");150ret = -ENOSYS;151i += 2;152}153} else {154if (msg[i].addr == ec168_ec100_config.demod_address) {155req.cmd = WRITE_DEMOD;156req.value = msg[i].buf[1]; /* val */157req.index = 0xff00 + msg[i].buf[0]; /* reg */158req.size = 0;159req.data = NULL;160ret = ec168_ctrl_msg(d, &req);161i += 1;162} else {163req.cmd = WRITE_I2C;164req.value = msg[i].buf[0]; /* val */165req.index = 0x0100 + msg[i].addr; /* I2C addr */166req.size = msg[i].len-1;167req.data = &msg[i].buf[1];168ret = ec168_ctrl_msg(d, &req);169i += 1;170}171}172if (ret)173goto error;174175}176ret = i;177178error:179mutex_unlock(&d->i2c_mutex);180return i;181}182183184static u32 ec168_i2c_func(struct i2c_adapter *adapter)185{186return I2C_FUNC_I2C;187}188189static struct i2c_algorithm ec168_i2c_algo = {190.master_xfer = ec168_i2c_xfer,191.functionality = ec168_i2c_func,192};193194/* Callbacks for DVB USB */195static struct ec100_config ec168_ec100_config = {196.demod_address = 0xff, /* not real address, demod is integrated */197};198199static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)200{201deb_info("%s:\n", __func__);202adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,203&adap->dev->i2c_adap);204if (adap->fe == NULL)205return -ENODEV;206207return 0;208}209210static struct mxl5005s_config ec168_mxl5003s_config = {211.i2c_address = 0xc6,212.if_freq = IF_FREQ_4570000HZ,213.xtal_freq = CRYSTAL_FREQ_16000000HZ,214.agc_mode = MXL_SINGLE_AGC,215.tracking_filter = MXL_TF_OFF,216.rssi_enable = MXL_RSSI_ENABLE,217.cap_select = MXL_CAP_SEL_ENABLE,218.div_out = MXL_DIV_OUT_4,219.clock_out = MXL_CLOCK_OUT_DISABLE,220.output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,221.top = MXL5005S_TOP_25P2,222.mod_mode = MXL_DIGITAL_MODE,223.if_mode = MXL_ZERO_IF,224.AgcMasterByte = 0x00,225};226227static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)228{229deb_info("%s:\n", __func__);230return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,231&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;232}233234static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)235{236struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};237deb_info("%s: onoff:%d\n", __func__, onoff);238if (onoff)239req.index = 0x0102;240return ec168_ctrl_msg(adap->dev, &req);241}242243static int ec168_download_firmware(struct usb_device *udev,244const struct firmware *fw)245{246int i, len, packets, remainder, ret;247u16 addr = 0x0000; /* firmware start address */248struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};249deb_info("%s:\n", __func__);250251#define FW_PACKET_MAX_DATA 2048252packets = fw->size / FW_PACKET_MAX_DATA;253remainder = fw->size % FW_PACKET_MAX_DATA;254len = FW_PACKET_MAX_DATA;255for (i = 0; i <= packets; i++) {256if (i == packets) /* set size of the last packet */257len = remainder;258259req.size = len;260req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);261req.index = addr;262addr += FW_PACKET_MAX_DATA;263264ret = ec168_rw_udev(udev, &req);265if (ret) {266err("firmware download failed:%d packet:%d", ret, i);267goto error;268}269}270req.size = 0;271272/* set "warm"? */273req.cmd = SET_CONFIG;274req.value = 0;275req.index = 0x0001;276ret = ec168_rw_udev(udev, &req);277if (ret)278goto error;279280/* really needed - no idea what does */281req.cmd = GPIO;282req.value = 0;283req.index = 0x0206;284ret = ec168_rw_udev(udev, &req);285if (ret)286goto error;287288/* activate tuner I2C? */289req.cmd = WRITE_I2C;290req.value = 0;291req.index = 0x00c6;292ret = ec168_rw_udev(udev, &req);293if (ret)294goto error;295296return ret;297error:298deb_info("%s: failed:%d\n", __func__, ret);299return ret;300}301302static int ec168_identify_state(struct usb_device *udev,303struct dvb_usb_device_properties *props,304struct dvb_usb_device_description **desc, int *cold)305{306int ret;307u8 reply;308struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};309deb_info("%s:\n", __func__);310311ret = ec168_rw_udev(udev, &req);312if (ret)313goto error;314315deb_info("%s: reply:%02x\n", __func__, reply);316317if (reply == 0x01)318*cold = 0;319else320*cold = 1;321322return ret;323error:324deb_info("%s: failed:%d\n", __func__, ret);325return ret;326}327328/* DVB USB Driver stuff */329static struct dvb_usb_device_properties ec168_properties;330331static int ec168_probe(struct usb_interface *intf,332const struct usb_device_id *id)333{334int ret;335deb_info("%s: interface:%d\n", __func__,336intf->cur_altsetting->desc.bInterfaceNumber);337338ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL,339adapter_nr);340if (ret)341goto error;342343return ret;344error:345deb_info("%s: failed:%d\n", __func__, ret);346return ret;347}348349#define E3C_EC168_1689 0350#define E3C_EC168_FFFA 1351#define E3C_EC168_FFFB 2352#define E3C_EC168_1001 3353#define E3C_EC168_1002 4354355static struct usb_device_id ec168_id[] = {356[E3C_EC168_1689] =357{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)},358[E3C_EC168_FFFA] =359{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)},360[E3C_EC168_FFFB] =361{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)},362[E3C_EC168_1001] =363{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)},364[E3C_EC168_1002] =365{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)},366{} /* terminating entry */367};368369MODULE_DEVICE_TABLE(usb, ec168_id);370371static struct dvb_usb_device_properties ec168_properties = {372.caps = DVB_USB_IS_AN_I2C_ADAPTER,373374.usb_ctrl = DEVICE_SPECIFIC,375.download_firmware = ec168_download_firmware,376.firmware = "dvb-usb-ec168.fw",377.no_reconnect = 1,378379.size_of_priv = 0,380381.num_adapters = 1,382.adapter = {383{384.streaming_ctrl = ec168_streaming_ctrl,385.frontend_attach = ec168_ec100_frontend_attach,386.tuner_attach = ec168_mxl5003s_tuner_attach,387.stream = {388.type = USB_BULK,389.count = 6,390.endpoint = 0x82,391.u = {392.bulk = {393.buffersize = (32*512),394}395}396},397}398},399400.identify_state = ec168_identify_state,401402.i2c_algo = &ec168_i2c_algo,403404.num_device_descs = 1,405.devices = {406{407.name = "E3C EC168 DVB-T USB2.0 reference design",408.cold_ids = {409&ec168_id[E3C_EC168_1689],410&ec168_id[E3C_EC168_FFFA],411&ec168_id[E3C_EC168_FFFB],412&ec168_id[E3C_EC168_1001],413&ec168_id[E3C_EC168_1002],414NULL},415.warm_ids = {NULL},416},417}418};419420static struct usb_driver ec168_driver = {421.name = "dvb_usb_ec168",422.probe = ec168_probe,423.disconnect = dvb_usb_device_exit,424.id_table = ec168_id,425};426427/* module stuff */428static int __init ec168_module_init(void)429{430int ret;431deb_info("%s:\n", __func__);432ret = usb_register(&ec168_driver);433if (ret)434err("module init failed:%d", ret);435436return ret;437}438439static void __exit ec168_module_exit(void)440{441deb_info("%s:\n", __func__);442/* deregister this driver from the USB subsystem */443usb_deregister(&ec168_driver);444}445446module_init(ec168_module_init);447module_exit(ec168_module_exit);448449MODULE_AUTHOR("Antti Palosaari <[email protected]>");450MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver");451MODULE_LICENSE("GPL");452453454