···322322 depends on DVB_USB323323 help324324 Say Y here to support the Japanese DTV receiver Friio.325325+326326+config DVB_USB_EC168327327+ tristate "E3C EC168 DVB-T USB2.0 support"328328+ depends on DVB_USB && EXPERIMENTAL329329+ select DVB_EC100330330+ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE331331+ help332332+ Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
+3
drivers/media/dvb/dvb-usb/Makefile
···8282dvb-usb-friio-objs = friio.o friio-fe.o8383obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o84848585+dvb-usb-ec168-objs = ec168.o8686+obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o8787+8588EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/8689# due to tuner-xc30288790EXTRA_CFLAGS += -Idrivers/media/common/tuners
···11+/*22+ * E3C EC168 DVB USB driver33+ *44+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ * You should have received a copy of the GNU General Public License1717+ * along with this program; if not, write to the Free Software1818+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.1919+ *2020+ */2121+2222+#include "ec168.h"2323+#include "ec100.h"2424+#include "mxl5005s.h"2525+2626+/* debug */2727+static int dvb_usb_ec168_debug;2828+module_param_named(debug, dvb_usb_ec168_debug, int, 0644);2929+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);3030+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);3131+3232+static struct ec100_config ec168_ec100_config;3333+3434+static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)3535+{3636+ int ret;3737+ unsigned int pipe;3838+ u8 request, requesttype;3939+ u8 buf[req->size];4040+4141+ switch (req->cmd) {4242+ case DOWNLOAD_FIRMWARE:4343+ case GPIO:4444+ case WRITE_I2C:4545+ case STREAMING_CTRL:4646+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);4747+ request = req->cmd;4848+ break;4949+ case READ_I2C:5050+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);5151+ request = req->cmd;5252+ break;5353+ case GET_CONFIG:5454+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);5555+ request = CONFIG;5656+ break;5757+ case SET_CONFIG:5858+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);5959+ request = CONFIG;6060+ break;6161+ case WRITE_DEMOD:6262+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);6363+ request = DEMOD_RW;6464+ break;6565+ case READ_DEMOD:6666+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);6767+ request = DEMOD_RW;6868+ break;6969+ default:7070+ err("unknown command:%02x", req->cmd);7171+ ret = -EPERM;7272+ goto error;7373+ }7474+7575+ if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {7676+ /* write */7777+ memcpy(buf, req->data, req->size);7878+ pipe = usb_sndctrlpipe(udev, 0);7979+ } else {8080+ /* read */8181+ pipe = usb_rcvctrlpipe(udev, 0);8282+ }8383+8484+ msleep(1); /* avoid I2C errors */8585+8686+ ret = usb_control_msg(udev, pipe, request, requesttype, req->value,8787+ req->index, buf, sizeof(buf), EC168_USB_TIMEOUT);8888+8989+ ec168_debug_dump(request, requesttype, req->value, req->index, buf,9090+ req->size, deb_xfer);9191+9292+ if (ret < 0)9393+ goto error;9494+ else9595+ ret = 0;9696+9797+ /* read request, copy returned data to return buf */9898+ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))9999+ memcpy(req->data, buf, req->size);100100+101101+ return ret;102102+error:103103+ deb_info("%s: failed:%d\n", __func__, ret);104104+ return ret;105105+}106106+107107+static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)108108+{109109+ return ec168_rw_udev(d->udev, req);110110+}111111+112112+/* I2C */113113+static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],114114+ int num)115115+{116116+ struct dvb_usb_device *d = i2c_get_adapdata(adap);117117+ struct ec168_req req;118118+ int i = 0;119119+ int ret;120120+121121+ if (num > 2)122122+ return -EINVAL;123123+124124+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)125125+ return -EAGAIN;126126+127127+ while (i < num) {128128+ if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {129129+ if (msg[i].addr == ec168_ec100_config.demod_address) {130130+ req.cmd = READ_DEMOD;131131+ req.value = 0;132132+ req.index = 0xff00 + msg[i].buf[0]; /* reg */133133+ req.size = msg[i+1].len; /* bytes to read */134134+ req.data = &msg[i+1].buf[0];135135+ ret = ec168_ctrl_msg(d, &req);136136+ i += 2;137137+ } else {138138+ err("I2C read not implemented");139139+ ret = -ENOSYS;140140+ i += 2;141141+ }142142+ } else {143143+ if (msg[i].addr == ec168_ec100_config.demod_address) {144144+ req.cmd = WRITE_DEMOD;145145+ req.value = msg[i].buf[1]; /* val */146146+ req.index = 0xff00 + msg[i].buf[0]; /* reg */147147+ req.size = 0;148148+ req.data = NULL;149149+ ret = ec168_ctrl_msg(d, &req);150150+ i += 1;151151+ } else {152152+ req.cmd = WRITE_I2C;153153+ req.value = msg[i].buf[0]; /* val */154154+ req.index = 0x0100 + msg[i].addr; /* I2C addr */155155+ req.size = msg[i].len-1;156156+ req.data = &msg[i].buf[1];157157+ ret = ec168_ctrl_msg(d, &req);158158+ i += 1;159159+ }160160+ }161161+ if (ret)162162+ goto error;163163+164164+ }165165+ ret = i;166166+167167+error:168168+ mutex_unlock(&d->i2c_mutex);169169+ return i;170170+}171171+172172+173173+static u32 ec168_i2c_func(struct i2c_adapter *adapter)174174+{175175+ return I2C_FUNC_I2C;176176+}177177+178178+static struct i2c_algorithm ec168_i2c_algo = {179179+ .master_xfer = ec168_i2c_xfer,180180+ .functionality = ec168_i2c_func,181181+};182182+183183+/* Callbacks for DVB USB */184184+static struct ec100_config ec168_ec100_config = {185185+ .demod_address = 0xff, /* not real address, demod is integrated */186186+};187187+188188+static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)189189+{190190+ deb_info("%s:\n", __func__);191191+ adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,192192+ &adap->dev->i2c_adap);193193+ if (adap->fe == NULL)194194+ return -ENODEV;195195+196196+ return 0;197197+}198198+199199+static struct mxl5005s_config ec168_mxl5003s_config = {200200+ .i2c_address = 0xc6,201201+ .if_freq = IF_FREQ_4570000HZ,202202+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,203203+ .agc_mode = MXL_SINGLE_AGC,204204+ .tracking_filter = MXL_TF_OFF,205205+ .rssi_enable = MXL_RSSI_ENABLE,206206+ .cap_select = MXL_CAP_SEL_ENABLE,207207+ .div_out = MXL_DIV_OUT_4,208208+ .clock_out = MXL_CLOCK_OUT_DISABLE,209209+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,210210+ .top = MXL5005S_TOP_25P2,211211+ .mod_mode = MXL_DIGITAL_MODE,212212+ .if_mode = MXL_ZERO_IF,213213+ .AgcMasterByte = 0x00,214214+};215215+216216+static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)217217+{218218+ deb_info("%s:\n", __func__);219219+ return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,220220+ &ec168_mxl5003s_config) == NULL ? -ENODEV : 0;221221+}222222+223223+static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)224224+{225225+ struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};226226+ deb_info("%s: onoff:%d\n", __func__, onoff);227227+ if (onoff)228228+ req.index = 0x0102;229229+ return ec168_ctrl_msg(adap->dev, &req);230230+}231231+232232+static int ec168_download_firmware(struct usb_device *udev,233233+ const struct firmware *fw)234234+{235235+ int i, len, packets, remainder, ret;236236+ u16 addr = 0x0000; /* firmware start address */237237+ struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};238238+ deb_info("%s:\n", __func__);239239+240240+ #define FW_PACKET_MAX_DATA 2048241241+ packets = fw->size / FW_PACKET_MAX_DATA;242242+ remainder = fw->size % FW_PACKET_MAX_DATA;243243+ len = FW_PACKET_MAX_DATA;244244+ for (i = 0; i <= packets; i++) {245245+ if (i == packets) /* set size of the last packet */246246+ len = remainder;247247+248248+ req.size = len;249249+ req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);250250+ req.index = addr;251251+ addr += FW_PACKET_MAX_DATA;252252+253253+ ret = ec168_rw_udev(udev, &req);254254+ if (ret) {255255+ err("firmware download failed:%d packet:%d", ret, i);256256+ goto error;257257+ }258258+ }259259+ req.size = 0;260260+261261+ /* set "warm"? */262262+ req.cmd = SET_CONFIG;263263+ req.value = 0;264264+ req.index = 0x0001;265265+ ret = ec168_rw_udev(udev, &req);266266+ if (ret)267267+ goto error;268268+269269+ /* really needed - no idea what does */270270+ req.cmd = GPIO;271271+ req.value = 0;272272+ req.index = 0x0206;273273+ ret = ec168_rw_udev(udev, &req);274274+ if (ret)275275+ goto error;276276+277277+ /* activate tuner I2C? */278278+ req.cmd = WRITE_I2C;279279+ req.value = 0;280280+ req.index = 0x00c6;281281+ ret = ec168_rw_udev(udev, &req);282282+ if (ret)283283+ goto error;284284+285285+ return ret;286286+error:287287+ deb_info("%s: failed:%d\n", __func__, ret);288288+ return ret;289289+}290290+291291+static int ec168_identify_state(struct usb_device *udev,292292+ struct dvb_usb_device_properties *props,293293+ struct dvb_usb_device_description **desc, int *cold)294294+{295295+ int ret;296296+ u8 reply;297297+ struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};298298+ deb_info("%s:\n", __func__);299299+300300+ ret = ec168_rw_udev(udev, &req);301301+ if (ret)302302+ goto error;303303+304304+ deb_info("%s: reply:%02x\n", __func__, reply);305305+306306+ if (reply == 0x01)307307+ *cold = 0;308308+ else309309+ *cold = 1;310310+311311+ return ret;312312+error:313313+ deb_info("%s: failed:%d\n", __func__, ret);314314+ return ret;315315+}316316+317317+/* DVB USB Driver stuff */318318+static struct dvb_usb_device_properties ec168_properties;319319+320320+static int ec168_probe(struct usb_interface *intf,321321+ const struct usb_device_id *id)322322+{323323+ int ret;324324+ deb_info("%s: interface:%d\n", __func__,325325+ intf->cur_altsetting->desc.bInterfaceNumber);326326+327327+ ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL,328328+ adapter_nr);329329+ if (ret)330330+ goto error;331331+332332+ return ret;333333+error:334334+ deb_info("%s: failed:%d\n", __func__, ret);335335+ return ret;336336+}337337+338338+#define E3C_EC168_1689 0339339+#define E3C_EC168_FFFA 1340340+#define E3C_EC168_FFFB 2341341+#define E3C_EC168_1001 3342342+#define E3C_EC168_1002 4343343+344344+static struct usb_device_id ec168_id[] = {345345+ [E3C_EC168_1689] =346346+ {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)},347347+ [E3C_EC168_FFFA] =348348+ {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)},349349+ [E3C_EC168_FFFB] =350350+ {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)},351351+ [E3C_EC168_1001] =352352+ {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)},353353+ [E3C_EC168_1002] =354354+ {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)},355355+ {} /* terminating entry */356356+};357357+358358+MODULE_DEVICE_TABLE(usb, ec168_id);359359+360360+static struct dvb_usb_device_properties ec168_properties = {361361+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,362362+363363+ .usb_ctrl = DEVICE_SPECIFIC,364364+ .download_firmware = ec168_download_firmware,365365+ .firmware = "dvb-usb-ec168.fw",366366+ .no_reconnect = 1,367367+368368+ .size_of_priv = 0,369369+370370+ .num_adapters = 1,371371+ .adapter = {372372+ {373373+ .streaming_ctrl = ec168_streaming_ctrl,374374+ .frontend_attach = ec168_ec100_frontend_attach,375375+ .tuner_attach = ec168_mxl5003s_tuner_attach,376376+ .stream = {377377+ .type = USB_BULK,378378+ .count = 6,379379+ .endpoint = 0x82,380380+ .u = {381381+ .bulk = {382382+ .buffersize = (32*512),383383+ }384384+ }385385+ },386386+ }387387+ },388388+389389+ .identify_state = ec168_identify_state,390390+391391+ .i2c_algo = &ec168_i2c_algo,392392+393393+ .num_device_descs = 1,394394+ .devices = {395395+ {396396+ .name = "E3C EC168 DVB-T USB2.0 reference design",397397+ .cold_ids = {398398+ &ec168_id[E3C_EC168_1689],399399+ &ec168_id[E3C_EC168_FFFA],400400+ &ec168_id[E3C_EC168_FFFB],401401+ &ec168_id[E3C_EC168_1001],402402+ &ec168_id[E3C_EC168_1002],403403+ NULL},404404+ .warm_ids = {NULL},405405+ },406406+ }407407+};408408+409409+static struct usb_driver ec168_driver = {410410+ .name = "dvb_usb_ec168",411411+ .probe = ec168_probe,412412+ .disconnect = dvb_usb_device_exit,413413+ .id_table = ec168_id,414414+};415415+416416+/* module stuff */417417+static int __init ec168_module_init(void)418418+{419419+ int ret;420420+ deb_info("%s:\n", __func__);421421+ ret = usb_register(&ec168_driver);422422+ if (ret)423423+ err("module init failed:%d", ret);424424+425425+ return ret;426426+}427427+428428+static void __exit ec168_module_exit(void)429429+{430430+ deb_info("%s:\n", __func__);431431+ /* deregister this driver from the USB subsystem */432432+ usb_deregister(&ec168_driver);433433+}434434+435435+module_init(ec168_module_init);436436+module_exit(ec168_module_exit);437437+438438+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");439439+MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver");440440+MODULE_LICENSE("GPL");
+73
drivers/media/dvb/dvb-usb/ec168.h
···11+/*22+ * E3C EC168 DVB USB driver33+ *44+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ * You should have received a copy of the GNU General Public License1717+ * along with this program; if not, write to the Free Software1818+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.1919+ *2020+ */2121+2222+#ifndef EC168_H2323+#define EC168_H2424+2525+#define DVB_USB_LOG_PREFIX "ec168"2626+#include "dvb-usb.h"2727+2828+#define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args)2929+#define deb_rc(args...) dprintk(dvb_usb_ec168_debug, 0x02, args)3030+#define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args)3131+#define deb_reg(args...) dprintk(dvb_usb_ec168_debug, 0x08, args)3232+#define deb_i2c(args...) dprintk(dvb_usb_ec168_debug, 0x10, args)3333+#define deb_fw(args...) dprintk(dvb_usb_ec168_debug, 0x20, args)3434+3535+#define ec168_debug_dump(r, t, v, i, b, l, func) { \3636+ int loop_; \3737+ func("%02x %02x %02x %02x %02x %02x %02x %02x", \3838+ t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \3939+ if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \4040+ func(" >>> "); \4141+ else \4242+ func(" <<< "); \4343+ for (loop_ = 0; loop_ < l; loop_++) \4444+ func("%02x ", b[loop_]); \4545+ func("\n");\4646+}4747+4848+#define EC168_USB_TIMEOUT 10004949+5050+struct ec168_req {5151+ u8 cmd; /* [1] */5252+ u16 value; /* [2|3] */5353+ u16 index; /* [4|5] */5454+ u16 size; /* [6|7] */5555+ u8 *data;5656+};5757+5858+enum ec168_cmd {5959+ DOWNLOAD_FIRMWARE = 0x00,6060+ CONFIG = 0x01,6161+ DEMOD_RW = 0x03,6262+ GPIO = 0x04,6363+ STREAMING_CTRL = 0x10,6464+ READ_I2C = 0x20,6565+ WRITE_I2C = 0x21,6666+ HID_DOWNLOAD = 0x30,6767+ GET_CONFIG,6868+ SET_CONFIG,6969+ READ_DEMOD,7070+ WRITE_DEMOD,7171+};7272+7373+#endif