Path: blob/master/drivers/media/dvb/dvb-usb/dw2102.c
15111 views
/* DVB USB framework compliant Linux driver for the1* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,2* TeVii S600, S630, S650, S660, S480,3* Prof 1100, 7500,4* Geniatech SU3000 Cards5* Copyright (C) 2008-2011 Igor M. Liplianin ([email protected])6*7* This program is free software; you can redistribute it and/or modify it8* under the terms of the GNU General Public License as published by the9* Free Software Foundation, version 2.10*11* see Documentation/dvb/README.dvb-usb for more information12*/13#include "dw2102.h"14#include "si21xx.h"15#include "stv0299.h"16#include "z0194a.h"17#include "stv0288.h"18#include "stb6000.h"19#include "eds1547.h"20#include "cx24116.h"21#include "tda1002x.h"22#include "mt312.h"23#include "zl10039.h"24#include "ds3000.h"25#include "stv0900.h"26#include "stv6110.h"27#include "stb6100.h"28#include "stb6100_proc.h"2930#ifndef USB_PID_DW210231#define USB_PID_DW2102 0x210232#endif3334#ifndef USB_PID_DW210435#define USB_PID_DW2104 0x210436#endif3738#ifndef USB_PID_DW310139#define USB_PID_DW3101 0x310140#endif4142#ifndef USB_PID_CINERGY_S43#define USB_PID_CINERGY_S 0x006444#endif4546#ifndef USB_PID_TEVII_S63047#define USB_PID_TEVII_S630 0xd63048#endif4950#ifndef USB_PID_TEVII_S65051#define USB_PID_TEVII_S650 0xd65052#endif5354#ifndef USB_PID_TEVII_S66055#define USB_PID_TEVII_S660 0xd66056#endif5758#ifndef USB_PID_TEVII_S480_159#define USB_PID_TEVII_S480_1 0xd48160#endif6162#ifndef USB_PID_TEVII_S480_263#define USB_PID_TEVII_S480_2 0xd48264#endif6566#ifndef USB_PID_PROF_110067#define USB_PID_PROF_1100 0xb01268#endif6970#define DW210X_READ_MSG 071#define DW210X_WRITE_MSG 17273#define REG_1F_SYMBOLRATE_BYTE0 0x1f74#define REG_20_SYMBOLRATE_BYTE1 0x2075#define REG_21_SYMBOLRATE_BYTE2 0x2176/* on my own*/77#define DW2102_VOLTAGE_CTRL (0x1800)78#define SU3000_STREAM_CTRL (0x1900)79#define DW2102_RC_QUERY (0x1a00)80#define DW2102_LED_CTRL (0x1b00)8182#define err_str "did not find the firmware file. (%s) " \83"Please see linux/Documentation/dvb/ for more details " \84"on firmware-problems."8586struct rc_map_dvb_usb_table_table {87struct rc_map_table *rc_keys;88int rc_keys_size;89};9091struct su3000_state {92u8 initialized;93};9495struct s6x0_state {96int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);97};9899/* debug */100static int dvb_usb_dw2102_debug;101module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);102MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."103DVB_USB_DEBUG_STATUS);104105/* keymaps */106static int ir_keymap;107module_param_named(keymap, ir_keymap, int, 0644);108MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."109" 256=none");110111/* demod probe */112static int demod_probe = 1;113module_param_named(demod, demod_probe, int, 0644);114MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "115"4=stv0903+stb6100(or-able)).");116117DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);118119static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,120u16 index, u8 * data, u16 len, int flags)121{122int ret;123u8 *u8buf;124unsigned int pipe = (flags == DW210X_READ_MSG) ?125usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);126u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;127128u8buf = kmalloc(len, GFP_KERNEL);129if (!u8buf)130return -ENOMEM;131132133if (flags == DW210X_WRITE_MSG)134memcpy(u8buf, data, len);135ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,136value, index , u8buf, len, 2000);137138if (flags == DW210X_READ_MSG)139memcpy(data, u8buf, len);140141kfree(u8buf);142return ret;143}144145/* I2C */146static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],147int num)148{149struct dvb_usb_device *d = i2c_get_adapdata(adap);150int i = 0, ret = 0;151u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};152u16 value;153154if (!d)155return -ENODEV;156if (mutex_lock_interruptible(&d->i2c_mutex) < 0)157return -EAGAIN;158159switch (num) {160case 2:161/* read stv0299 register */162value = msg[0].buf[0];/* register */163for (i = 0; i < msg[1].len; i++) {164ret = dw210x_op_rw(d->udev, 0xb5, value + i, 0,165buf6, 2, DW210X_READ_MSG);166msg[1].buf[i] = buf6[0];167}168break;169case 1:170switch (msg[0].addr) {171case 0x68:172/* write to stv0299 register */173buf6[0] = 0x2a;174buf6[1] = msg[0].buf[0];175buf6[2] = msg[0].buf[1];176ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,177buf6, 3, DW210X_WRITE_MSG);178break;179case 0x60:180if (msg[0].flags == 0) {181/* write to tuner pll */182buf6[0] = 0x2c;183buf6[1] = 5;184buf6[2] = 0xc0;185buf6[3] = msg[0].buf[0];186buf6[4] = msg[0].buf[1];187buf6[5] = msg[0].buf[2];188buf6[6] = msg[0].buf[3];189ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,190buf6, 7, DW210X_WRITE_MSG);191} else {192/* read from tuner */193ret = dw210x_op_rw(d->udev, 0xb5, 0, 0,194buf6, 1, DW210X_READ_MSG);195msg[0].buf[0] = buf6[0];196}197break;198case (DW2102_RC_QUERY):199ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,200buf6, 2, DW210X_READ_MSG);201msg[0].buf[0] = buf6[0];202msg[0].buf[1] = buf6[1];203break;204case (DW2102_VOLTAGE_CTRL):205buf6[0] = 0x30;206buf6[1] = msg[0].buf[0];207ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,208buf6, 2, DW210X_WRITE_MSG);209break;210}211212break;213}214215mutex_unlock(&d->i2c_mutex);216return num;217}218219static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,220struct i2c_msg msg[], int num)221{222struct dvb_usb_device *d = i2c_get_adapdata(adap);223int ret = 0;224u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};225226if (!d)227return -ENODEV;228if (mutex_lock_interruptible(&d->i2c_mutex) < 0)229return -EAGAIN;230231switch (num) {232case 2:233/* read si2109 register by number */234buf6[0] = msg[0].addr << 1;235buf6[1] = msg[0].len;236buf6[2] = msg[0].buf[0];237ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,238buf6, msg[0].len + 2, DW210X_WRITE_MSG);239/* read si2109 register */240ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,241buf6, msg[1].len + 2, DW210X_READ_MSG);242memcpy(msg[1].buf, buf6 + 2, msg[1].len);243244break;245case 1:246switch (msg[0].addr) {247case 0x68:248/* write to si2109 register */249buf6[0] = msg[0].addr << 1;250buf6[1] = msg[0].len;251memcpy(buf6 + 2, msg[0].buf, msg[0].len);252ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,253msg[0].len + 2, DW210X_WRITE_MSG);254break;255case(DW2102_RC_QUERY):256ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,257buf6, 2, DW210X_READ_MSG);258msg[0].buf[0] = buf6[0];259msg[0].buf[1] = buf6[1];260break;261case(DW2102_VOLTAGE_CTRL):262buf6[0] = 0x30;263buf6[1] = msg[0].buf[0];264ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,265buf6, 2, DW210X_WRITE_MSG);266break;267}268break;269}270271mutex_unlock(&d->i2c_mutex);272return num;273}274275static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)276{277struct dvb_usb_device *d = i2c_get_adapdata(adap);278int ret = 0;279280if (!d)281return -ENODEV;282if (mutex_lock_interruptible(&d->i2c_mutex) < 0)283return -EAGAIN;284285switch (num) {286case 2: {287/* read */288/* first write first register number */289u8 ibuf[msg[1].len + 2], obuf[3];290obuf[0] = msg[0].addr << 1;291obuf[1] = msg[0].len;292obuf[2] = msg[0].buf[0];293ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,294obuf, msg[0].len + 2, DW210X_WRITE_MSG);295/* second read registers */296ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,297ibuf, msg[1].len + 2, DW210X_READ_MSG);298memcpy(msg[1].buf, ibuf + 2, msg[1].len);299300break;301}302case 1:303switch (msg[0].addr) {304case 0x68: {305/* write to register */306u8 obuf[msg[0].len + 2];307obuf[0] = msg[0].addr << 1;308obuf[1] = msg[0].len;309memcpy(obuf + 2, msg[0].buf, msg[0].len);310ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,311obuf, msg[0].len + 2, DW210X_WRITE_MSG);312break;313}314case 0x61: {315/* write to tuner */316u8 obuf[msg[0].len + 2];317obuf[0] = msg[0].addr << 1;318obuf[1] = msg[0].len;319memcpy(obuf + 2, msg[0].buf, msg[0].len);320ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,321obuf, msg[0].len + 2, DW210X_WRITE_MSG);322break;323}324case(DW2102_RC_QUERY): {325u8 ibuf[2];326ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,327ibuf, 2, DW210X_READ_MSG);328memcpy(msg[0].buf, ibuf , 2);329break;330}331case(DW2102_VOLTAGE_CTRL): {332u8 obuf[2];333obuf[0] = 0x30;334obuf[1] = msg[0].buf[0];335ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,336obuf, 2, DW210X_WRITE_MSG);337break;338}339}340341break;342}343344mutex_unlock(&d->i2c_mutex);345return num;346}347348static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)349{350struct dvb_usb_device *d = i2c_get_adapdata(adap);351int ret = 0;352int len, i, j;353354if (!d)355return -ENODEV;356if (mutex_lock_interruptible(&d->i2c_mutex) < 0)357return -EAGAIN;358359for (j = 0; j < num; j++) {360switch (msg[j].addr) {361case(DW2102_RC_QUERY): {362u8 ibuf[2];363ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,364ibuf, 2, DW210X_READ_MSG);365memcpy(msg[j].buf, ibuf , 2);366break;367}368case(DW2102_VOLTAGE_CTRL): {369u8 obuf[2];370obuf[0] = 0x30;371obuf[1] = msg[j].buf[0];372ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,373obuf, 2, DW210X_WRITE_MSG);374break;375}376/*case 0x55: cx24116377case 0x6a: stv0903378case 0x68: ds3000, stv0903379case 0x60: ts2020, stv6110, stb6100 */380default: {381if (msg[j].flags == I2C_M_RD) {382/* read registers */383u8 ibuf[msg[j].len + 2];384ret = dw210x_op_rw(d->udev, 0xc3,385(msg[j].addr << 1) + 1, 0,386ibuf, msg[j].len + 2,387DW210X_READ_MSG);388memcpy(msg[j].buf, ibuf + 2, msg[j].len);389mdelay(10);390} else if (((msg[j].buf[0] == 0xb0) &&391(msg[j].addr == 0x68)) ||392((msg[j].buf[0] == 0xf7) &&393(msg[j].addr == 0x55))) {394/* write firmware */395u8 obuf[19];396obuf[0] = msg[j].addr << 1;397obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);398obuf[2] = msg[j].buf[0];399len = msg[j].len - 1;400i = 1;401do {402memcpy(obuf + 3, msg[j].buf + i,403(len > 16 ? 16 : len));404ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,405obuf, (len > 16 ? 16 : len) + 3,406DW210X_WRITE_MSG);407i += 16;408len -= 16;409} while (len > 0);410} else {411/* write registers */412u8 obuf[msg[j].len + 2];413obuf[0] = msg[j].addr << 1;414obuf[1] = msg[j].len;415memcpy(obuf + 2, msg[j].buf, msg[j].len);416ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,417obuf, msg[j].len + 2,418DW210X_WRITE_MSG);419}420break;421}422}423424}425426mutex_unlock(&d->i2c_mutex);427return num;428}429430static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],431int num)432{433struct dvb_usb_device *d = i2c_get_adapdata(adap);434int ret = 0, i;435436if (!d)437return -ENODEV;438if (mutex_lock_interruptible(&d->i2c_mutex) < 0)439return -EAGAIN;440441switch (num) {442case 2: {443/* read */444/* first write first register number */445u8 ibuf[msg[1].len + 2], obuf[3];446obuf[0] = msg[0].addr << 1;447obuf[1] = msg[0].len;448obuf[2] = msg[0].buf[0];449ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,450obuf, msg[0].len + 2, DW210X_WRITE_MSG);451/* second read registers */452ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,453ibuf, msg[1].len + 2, DW210X_READ_MSG);454memcpy(msg[1].buf, ibuf + 2, msg[1].len);455456break;457}458case 1:459switch (msg[0].addr) {460case 0x60:461case 0x0c: {462/* write to register */463u8 obuf[msg[0].len + 2];464obuf[0] = msg[0].addr << 1;465obuf[1] = msg[0].len;466memcpy(obuf + 2, msg[0].buf, msg[0].len);467ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,468obuf, msg[0].len + 2, DW210X_WRITE_MSG);469break;470}471case(DW2102_RC_QUERY): {472u8 ibuf[2];473ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,474ibuf, 2, DW210X_READ_MSG);475memcpy(msg[0].buf, ibuf , 2);476break;477}478}479480break;481}482483for (i = 0; i < num; i++) {484deb_xfer("%02x:%02x: %s ", i, msg[i].addr,485msg[i].flags == 0 ? ">>>" : "<<<");486debug_dump(msg[i].buf, msg[i].len, deb_xfer);487}488489mutex_unlock(&d->i2c_mutex);490return num;491}492493static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],494int num)495{496struct dvb_usb_device *d = i2c_get_adapdata(adap);497struct usb_device *udev;498int ret = 0;499int len, i, j;500501if (!d)502return -ENODEV;503udev = d->udev;504if (mutex_lock_interruptible(&d->i2c_mutex) < 0)505return -EAGAIN;506507for (j = 0; j < num; j++) {508switch (msg[j].addr) {509case (DW2102_RC_QUERY): {510u8 ibuf[5];511ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,512ibuf, 5, DW210X_READ_MSG);513memcpy(msg[j].buf, ibuf + 3, 2);514break;515}516case (DW2102_VOLTAGE_CTRL): {517u8 obuf[2];518519obuf[0] = 1;520obuf[1] = msg[j].buf[1];/* off-on */521ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,522obuf, 2, DW210X_WRITE_MSG);523obuf[0] = 3;524obuf[1] = msg[j].buf[0];/* 13v-18v */525ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,526obuf, 2, DW210X_WRITE_MSG);527break;528}529case (DW2102_LED_CTRL): {530u8 obuf[2];531532obuf[0] = 5;533obuf[1] = msg[j].buf[0];534ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,535obuf, 2, DW210X_WRITE_MSG);536break;537}538/*case 0x55: cx24116539case 0x6a: stv0903540case 0x68: ds3000, stv0903541case 0x60: ts2020, stv6110, stb6100542case 0xa0: eeprom */543default: {544if (msg[j].flags == I2C_M_RD) {545/* read registers */546u8 ibuf[msg[j].len];547ret = dw210x_op_rw(d->udev, 0x91, 0, 0,548ibuf, msg[j].len,549DW210X_READ_MSG);550memcpy(msg[j].buf, ibuf, msg[j].len);551break;552} else if ((msg[j].buf[0] == 0xb0) &&553(msg[j].addr == 0x68)) {554/* write firmware */555u8 obuf[19];556obuf[0] = (msg[j].len > 16 ?55718 : msg[j].len + 1);558obuf[1] = msg[j].addr << 1;559obuf[2] = msg[j].buf[0];560len = msg[j].len - 1;561i = 1;562do {563memcpy(obuf + 3, msg[j].buf + i,564(len > 16 ? 16 : len));565ret = dw210x_op_rw(d->udev, 0x80, 0, 0,566obuf, (len > 16 ? 16 : len) + 3,567DW210X_WRITE_MSG);568i += 16;569len -= 16;570} while (len > 0);571} else if (j < (num - 1)) {572/* write register addr before read */573u8 obuf[msg[j].len + 2];574obuf[0] = msg[j + 1].len;575obuf[1] = (msg[j].addr << 1);576memcpy(obuf + 2, msg[j].buf, msg[j].len);577ret = dw210x_op_rw(d->udev,578udev->descriptor.idProduct ==5790x7500 ? 0x92 : 0x90, 0, 0,580obuf, msg[j].len + 2,581DW210X_WRITE_MSG);582break;583} else {584/* write registers */585u8 obuf[msg[j].len + 2];586obuf[0] = msg[j].len + 1;587obuf[1] = (msg[j].addr << 1);588memcpy(obuf + 2, msg[j].buf, msg[j].len);589ret = dw210x_op_rw(d->udev, 0x80, 0, 0,590obuf, msg[j].len + 2,591DW210X_WRITE_MSG);592break;593}594break;595}596}597}598599mutex_unlock(&d->i2c_mutex);600return num;601}602603static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],604int num)605{606struct dvb_usb_device *d = i2c_get_adapdata(adap);607u8 obuf[0x40], ibuf[0x40];608609if (!d)610return -ENODEV;611if (mutex_lock_interruptible(&d->i2c_mutex) < 0)612return -EAGAIN;613614switch (num) {615case 1:616switch (msg[0].addr) {617case SU3000_STREAM_CTRL:618obuf[0] = msg[0].buf[0] + 0x36;619obuf[1] = 3;620obuf[2] = 0;621if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)622err("i2c transfer failed.");623break;624case DW2102_RC_QUERY:625obuf[0] = 0x10;626if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)627err("i2c transfer failed.");628msg[0].buf[1] = ibuf[0];629msg[0].buf[0] = ibuf[1];630break;631default:632/* always i2c write*/633obuf[0] = 0x08;634obuf[1] = msg[0].addr;635obuf[2] = msg[0].len;636637memcpy(&obuf[3], msg[0].buf, msg[0].len);638639if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,640ibuf, 1, 0) < 0)641err("i2c transfer failed.");642643}644break;645case 2:646/* always i2c read */647obuf[0] = 0x09;648obuf[1] = msg[0].len;649obuf[2] = msg[1].len;650obuf[3] = msg[0].addr;651memcpy(&obuf[4], msg[0].buf, msg[0].len);652653if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,654ibuf, msg[1].len + 1, 0) < 0)655err("i2c transfer failed.");656657memcpy(msg[1].buf, &ibuf[1], msg[1].len);658break;659default:660warn("more than 2 i2c messages at a time is not handled yet.");661break;662}663mutex_unlock(&d->i2c_mutex);664return num;665}666667static u32 dw210x_i2c_func(struct i2c_adapter *adapter)668{669return I2C_FUNC_I2C;670}671672static struct i2c_algorithm dw2102_i2c_algo = {673.master_xfer = dw2102_i2c_transfer,674.functionality = dw210x_i2c_func,675};676677static struct i2c_algorithm dw2102_serit_i2c_algo = {678.master_xfer = dw2102_serit_i2c_transfer,679.functionality = dw210x_i2c_func,680};681682static struct i2c_algorithm dw2102_earda_i2c_algo = {683.master_xfer = dw2102_earda_i2c_transfer,684.functionality = dw210x_i2c_func,685};686687static struct i2c_algorithm dw2104_i2c_algo = {688.master_xfer = dw2104_i2c_transfer,689.functionality = dw210x_i2c_func,690};691692static struct i2c_algorithm dw3101_i2c_algo = {693.master_xfer = dw3101_i2c_transfer,694.functionality = dw210x_i2c_func,695};696697static struct i2c_algorithm s6x0_i2c_algo = {698.master_xfer = s6x0_i2c_transfer,699.functionality = dw210x_i2c_func,700};701702static struct i2c_algorithm su3000_i2c_algo = {703.master_xfer = su3000_i2c_transfer,704.functionality = dw210x_i2c_func,705};706707static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])708{709int i;710u8 ibuf[] = {0, 0};711u8 eeprom[256], eepromline[16];712713for (i = 0; i < 256; i++) {714if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {715err("read eeprom failed.");716return -1;717} else {718eepromline[i%16] = ibuf[0];719eeprom[i] = ibuf[0];720}721if ((i % 16) == 15) {722deb_xfer("%02x: ", i - 15);723debug_dump(eepromline, 16, deb_xfer);724}725}726727memcpy(mac, eeprom + 8, 6);728return 0;729};730731static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])732{733int i, ret;734u8 ibuf[] = { 0 }, obuf[] = { 0 };735u8 eeprom[256], eepromline[16];736struct i2c_msg msg[] = {737{738.addr = 0xa0 >> 1,739.flags = 0,740.buf = obuf,741.len = 1,742}, {743.addr = 0xa0 >> 1,744.flags = I2C_M_RD,745.buf = ibuf,746.len = 1,747}748};749750for (i = 0; i < 256; i++) {751obuf[0] = i;752ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);753if (ret != 2) {754err("read eeprom failed.");755return -1;756} else {757eepromline[i % 16] = ibuf[0];758eeprom[i] = ibuf[0];759}760761if ((i % 16) == 15) {762deb_xfer("%02x: ", i - 15);763debug_dump(eepromline, 16, deb_xfer);764}765}766767memcpy(mac, eeprom + 16, 6);768return 0;769};770771static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)772{773static u8 command_start[] = {0x00};774static u8 command_stop[] = {0x01};775struct i2c_msg msg = {776.addr = SU3000_STREAM_CTRL,777.flags = 0,778.buf = onoff ? command_start : command_stop,779.len = 1780};781782i2c_transfer(&adap->dev->i2c_adap, &msg, 1);783784return 0;785}786787static int su3000_power_ctrl(struct dvb_usb_device *d, int i)788{789struct su3000_state *state = (struct su3000_state *)d->priv;790u8 obuf[] = {0xde, 0};791792info("%s: %d, initialized %d\n", __func__, i, state->initialized);793794if (i && !state->initialized) {795state->initialized = 1;796/* reset board */797dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);798}799800return 0;801}802803static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])804{805int i;806u8 obuf[] = { 0x1f, 0xf0 };807u8 ibuf[] = { 0 };808struct i2c_msg msg[] = {809{810.addr = 0x51,811.flags = 0,812.buf = obuf,813.len = 2,814}, {815.addr = 0x51,816.flags = I2C_M_RD,817.buf = ibuf,818.len = 1,819820}821};822823for (i = 0; i < 6; i++) {824obuf[1] = 0xf0 + i;825if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)826break;827else828mac[i] = ibuf[0];829830debug_dump(mac, 6, printk);831}832833return 0;834}835836static int su3000_identify_state(struct usb_device *udev,837struct dvb_usb_device_properties *props,838struct dvb_usb_device_description **desc,839int *cold)840{841info("%s\n", __func__);842843*cold = 0;844return 0;845}846847static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)848{849static u8 command_13v[] = {0x00, 0x01};850static u8 command_18v[] = {0x01, 0x01};851static u8 command_off[] = {0x00, 0x00};852struct i2c_msg msg = {853.addr = DW2102_VOLTAGE_CTRL,854.flags = 0,855.buf = command_off,856.len = 2,857};858859struct dvb_usb_adapter *udev_adap =860(struct dvb_usb_adapter *)(fe->dvb->priv);861if (voltage == SEC_VOLTAGE_18)862msg.buf = command_18v;863else if (voltage == SEC_VOLTAGE_13)864msg.buf = command_13v;865866i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);867868return 0;869}870871static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)872{873struct dvb_usb_adapter *d =874(struct dvb_usb_adapter *)(fe->dvb->priv);875struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;876877dw210x_set_voltage(fe, voltage);878if (st->old_set_voltage)879st->old_set_voltage(fe, voltage);880881return 0;882}883884static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)885{886static u8 led_off[] = { 0 };887static u8 led_on[] = { 1 };888struct i2c_msg msg = {889.addr = DW2102_LED_CTRL,890.flags = 0,891.buf = led_off,892.len = 1893};894struct dvb_usb_adapter *udev_adap =895(struct dvb_usb_adapter *)(fe->dvb->priv);896897if (offon)898msg.buf = led_on;899i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);900}901902static struct stv0299_config sharp_z0194a_config = {903.demod_address = 0x68,904.inittab = sharp_z0194a_inittab,905.mclk = 88000000UL,906.invert = 1,907.skip_reinit = 0,908.lock_output = STV0299_LOCKOUTPUT_1,909.volt13_op0_op1 = STV0299_VOLT13_OP1,910.min_delay_ms = 100,911.set_symbol_rate = sharp_z0194a_set_symbol_rate,912};913914static struct cx24116_config dw2104_config = {915.demod_address = 0x55,916.mpg_clk_pos_pol = 0x01,917};918919static struct si21xx_config serit_sp1511lhb_config = {920.demod_address = 0x68,921.min_delay_ms = 100,922923};924925static struct tda10023_config dw3101_tda10023_config = {926.demod_address = 0x0c,927.invert = 1,928};929930static struct mt312_config zl313_config = {931.demod_address = 0x0e,932};933934static struct ds3000_config dw2104_ds3000_config = {935.demod_address = 0x68,936};937938static struct stv0900_config dw2104a_stv0900_config = {939.demod_address = 0x6a,940.demod_mode = 0,941.xtal = 27000000,942.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */943.diseqc_mode = 2,/* 2/3 PWM */944.tun1_maddress = 0,/* 0x60 */945.tun1_adc = 0,/* 2 Vpp */946.path1_mode = 3,947};948949static struct stb6100_config dw2104a_stb6100_config = {950.tuner_address = 0x60,951.refclock = 27000000,952};953954static struct stv0900_config dw2104_stv0900_config = {955.demod_address = 0x68,956.demod_mode = 0,957.xtal = 8000000,958.clkmode = 3,959.diseqc_mode = 2,960.tun1_maddress = 0,961.tun1_adc = 1,/* 1 Vpp */962.path1_mode = 3,963};964965static struct stv6110_config dw2104_stv6110_config = {966.i2c_address = 0x60,967.mclk = 16000000,968.clk_div = 1,969};970971static struct stv0900_config prof_7500_stv0900_config = {972.demod_address = 0x6a,973.demod_mode = 0,974.xtal = 27000000,975.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */976.diseqc_mode = 2,/* 2/3 PWM */977.tun1_maddress = 0,/* 0x60 */978.tun1_adc = 0,/* 2 Vpp */979.path1_mode = 3,980.tun1_type = 3,981.set_lock_led = dw210x_led_ctrl,982};983984static struct ds3000_config su3000_ds3000_config = {985.demod_address = 0x68,986.ci_mode = 1,987};988989static int dw2104_frontend_attach(struct dvb_usb_adapter *d)990{991struct dvb_tuner_ops *tuner_ops = NULL;992993if (demod_probe & 4) {994d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,995&d->dev->i2c_adap, 0);996if (d->fe != NULL) {997if (dvb_attach(stb6100_attach, d->fe,998&dw2104a_stb6100_config,999&d->dev->i2c_adap)) {1000tuner_ops = &d->fe->ops.tuner_ops;1001tuner_ops->set_frequency = stb6100_set_freq;1002tuner_ops->get_frequency = stb6100_get_freq;1003tuner_ops->set_bandwidth = stb6100_set_bandw;1004tuner_ops->get_bandwidth = stb6100_get_bandw;1005d->fe->ops.set_voltage = dw210x_set_voltage;1006info("Attached STV0900+STB6100!\n");1007return 0;1008}1009}1010}10111012if (demod_probe & 2) {1013d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,1014&d->dev->i2c_adap, 0);1015if (d->fe != NULL) {1016if (dvb_attach(stv6110_attach, d->fe,1017&dw2104_stv6110_config,1018&d->dev->i2c_adap)) {1019d->fe->ops.set_voltage = dw210x_set_voltage;1020info("Attached STV0900+STV6110A!\n");1021return 0;1022}1023}1024}10251026if (demod_probe & 1) {1027d->fe = dvb_attach(cx24116_attach, &dw2104_config,1028&d->dev->i2c_adap);1029if (d->fe != NULL) {1030d->fe->ops.set_voltage = dw210x_set_voltage;1031info("Attached cx24116!\n");1032return 0;1033}1034}10351036d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,1037&d->dev->i2c_adap);1038if (d->fe != NULL) {1039d->fe->ops.set_voltage = dw210x_set_voltage;1040info("Attached DS3000!\n");1041return 0;1042}10431044return -EIO;1045}10461047static struct dvb_usb_device_properties dw2102_properties;1048static struct dvb_usb_device_properties dw2104_properties;1049static struct dvb_usb_device_properties s6x0_properties;10501051static int dw2102_frontend_attach(struct dvb_usb_adapter *d)1052{1053if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {1054/*dw2102_properties.adapter->tuner_attach = NULL;*/1055d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,1056&d->dev->i2c_adap);1057if (d->fe != NULL) {1058d->fe->ops.set_voltage = dw210x_set_voltage;1059info("Attached si21xx!\n");1060return 0;1061}1062}10631064if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {1065d->fe = dvb_attach(stv0288_attach, &earda_config,1066&d->dev->i2c_adap);1067if (d->fe != NULL) {1068if (dvb_attach(stb6000_attach, d->fe, 0x61,1069&d->dev->i2c_adap)) {1070d->fe->ops.set_voltage = dw210x_set_voltage;1071info("Attached stv0288!\n");1072return 0;1073}1074}1075}10761077if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {1078/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/1079d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,1080&d->dev->i2c_adap);1081if (d->fe != NULL) {1082d->fe->ops.set_voltage = dw210x_set_voltage;1083info("Attached stv0299!\n");1084return 0;1085}1086}1087return -EIO;1088}10891090static int dw3101_frontend_attach(struct dvb_usb_adapter *d)1091{1092d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,1093&d->dev->i2c_adap, 0x48);1094if (d->fe != NULL) {1095info("Attached tda10023!\n");1096return 0;1097}1098return -EIO;1099}11001101static int zl100313_frontend_attach(struct dvb_usb_adapter *d)1102{1103d->fe = dvb_attach(mt312_attach, &zl313_config,1104&d->dev->i2c_adap);1105if (d->fe != NULL) {1106if (dvb_attach(zl10039_attach, d->fe, 0x60,1107&d->dev->i2c_adap)) {1108d->fe->ops.set_voltage = dw210x_set_voltage;1109info("Attached zl100313+zl10039!\n");1110return 0;1111}1112}11131114return -EIO;1115}11161117static int stv0288_frontend_attach(struct dvb_usb_adapter *d)1118{1119u8 obuf[] = {7, 1};11201121d->fe = dvb_attach(stv0288_attach, &earda_config,1122&d->dev->i2c_adap);11231124if (d->fe == NULL)1125return -EIO;11261127if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))1128return -EIO;11291130d->fe->ops.set_voltage = dw210x_set_voltage;11311132dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);11331134info("Attached stv0288+stb6000!\n");11351136return 0;11371138}11391140static int ds3000_frontend_attach(struct dvb_usb_adapter *d)1141{1142struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;1143u8 obuf[] = {7, 1};11441145d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,1146&d->dev->i2c_adap);11471148if (d->fe == NULL)1149return -EIO;11501151st->old_set_voltage = d->fe->ops.set_voltage;1152d->fe->ops.set_voltage = s660_set_voltage;11531154dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);11551156info("Attached ds3000+ds2020!\n");11571158return 0;1159}11601161static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)1162{1163u8 obuf[] = {7, 1};11641165d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,1166&d->dev->i2c_adap, 0);1167if (d->fe == NULL)1168return -EIO;11691170d->fe->ops.set_voltage = dw210x_set_voltage;11711172dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);11731174info("Attached STV0900+STB6100A!\n");11751176return 0;1177}11781179static int su3000_frontend_attach(struct dvb_usb_adapter *d)1180{1181u8 obuf[3] = { 0xe, 0x80, 0 };1182u8 ibuf[] = { 0 };11831184if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)1185err("command 0x0e transfer failed.");11861187obuf[0] = 0xe;1188obuf[1] = 0x83;1189obuf[2] = 0;11901191if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)1192err("command 0x0e transfer failed.");11931194obuf[0] = 0xe;1195obuf[1] = 0x83;1196obuf[2] = 1;11971198if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)1199err("command 0x0e transfer failed.");12001201obuf[0] = 0x51;12021203if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)1204err("command 0x51 transfer failed.");12051206d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,1207&d->dev->i2c_adap);1208if (d->fe == NULL)1209return -EIO;12101211info("Attached DS3000!\n");12121213return 0;1214}12151216static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)1217{1218dvb_attach(dvb_pll_attach, adap->fe, 0x60,1219&adap->dev->i2c_adap, DVB_PLL_OPERA1);1220return 0;1221}12221223static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)1224{1225dvb_attach(dvb_pll_attach, adap->fe, 0x60,1226&adap->dev->i2c_adap, DVB_PLL_TUA6034);12271228return 0;1229}12301231static struct rc_map_table rc_map_dw210x_table[] = {1232{ 0xf80a, KEY_POWER2 }, /*power*/1233{ 0xf80c, KEY_MUTE }, /*mute*/1234{ 0xf811, KEY_1 },1235{ 0xf812, KEY_2 },1236{ 0xf813, KEY_3 },1237{ 0xf814, KEY_4 },1238{ 0xf815, KEY_5 },1239{ 0xf816, KEY_6 },1240{ 0xf817, KEY_7 },1241{ 0xf818, KEY_8 },1242{ 0xf819, KEY_9 },1243{ 0xf810, KEY_0 },1244{ 0xf81c, KEY_CHANNELUP }, /*ch+*/1245{ 0xf80f, KEY_CHANNELDOWN }, /*ch-*/1246{ 0xf81a, KEY_VOLUMEUP }, /*vol+*/1247{ 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/1248{ 0xf804, KEY_RECORD }, /*rec*/1249{ 0xf809, KEY_FAVORITES }, /*fav*/1250{ 0xf808, KEY_REWIND }, /*rewind*/1251{ 0xf807, KEY_FASTFORWARD }, /*fast*/1252{ 0xf80b, KEY_PAUSE }, /*pause*/1253{ 0xf802, KEY_ESC }, /*cancel*/1254{ 0xf803, KEY_TAB }, /*tab*/1255{ 0xf800, KEY_UP }, /*up*/1256{ 0xf81f, KEY_OK }, /*ok*/1257{ 0xf801, KEY_DOWN }, /*down*/1258{ 0xf805, KEY_CAMERA }, /*cap*/1259{ 0xf806, KEY_STOP }, /*stop*/1260{ 0xf840, KEY_ZOOM }, /*full*/1261{ 0xf81e, KEY_TV }, /*tvmode*/1262{ 0xf81b, KEY_LAST }, /*recall*/1263};12641265static struct rc_map_table rc_map_tevii_table[] = {1266{ 0xf80a, KEY_POWER },1267{ 0xf80c, KEY_MUTE },1268{ 0xf811, KEY_1 },1269{ 0xf812, KEY_2 },1270{ 0xf813, KEY_3 },1271{ 0xf814, KEY_4 },1272{ 0xf815, KEY_5 },1273{ 0xf816, KEY_6 },1274{ 0xf817, KEY_7 },1275{ 0xf818, KEY_8 },1276{ 0xf819, KEY_9 },1277{ 0xf810, KEY_0 },1278{ 0xf81c, KEY_MENU },1279{ 0xf80f, KEY_VOLUMEDOWN },1280{ 0xf81a, KEY_LAST },1281{ 0xf80e, KEY_OPEN },1282{ 0xf804, KEY_RECORD },1283{ 0xf809, KEY_VOLUMEUP },1284{ 0xf808, KEY_CHANNELUP },1285{ 0xf807, KEY_PVR },1286{ 0xf80b, KEY_TIME },1287{ 0xf802, KEY_RIGHT },1288{ 0xf803, KEY_LEFT },1289{ 0xf800, KEY_UP },1290{ 0xf81f, KEY_OK },1291{ 0xf801, KEY_DOWN },1292{ 0xf805, KEY_TUNER },1293{ 0xf806, KEY_CHANNELDOWN },1294{ 0xf840, KEY_PLAYPAUSE },1295{ 0xf81e, KEY_REWIND },1296{ 0xf81b, KEY_FAVORITES },1297{ 0xf81d, KEY_BACK },1298{ 0xf84d, KEY_FASTFORWARD },1299{ 0xf844, KEY_EPG },1300{ 0xf84c, KEY_INFO },1301{ 0xf841, KEY_AB },1302{ 0xf843, KEY_AUDIO },1303{ 0xf845, KEY_SUBTITLE },1304{ 0xf84a, KEY_LIST },1305{ 0xf846, KEY_F1 },1306{ 0xf847, KEY_F2 },1307{ 0xf85e, KEY_F3 },1308{ 0xf85c, KEY_F4 },1309{ 0xf852, KEY_F5 },1310{ 0xf85a, KEY_F6 },1311{ 0xf856, KEY_MODE },1312{ 0xf858, KEY_SWITCHVIDEOMODE },1313};13141315static struct rc_map_table rc_map_tbs_table[] = {1316{ 0xf884, KEY_POWER },1317{ 0xf894, KEY_MUTE },1318{ 0xf887, KEY_1 },1319{ 0xf886, KEY_2 },1320{ 0xf885, KEY_3 },1321{ 0xf88b, KEY_4 },1322{ 0xf88a, KEY_5 },1323{ 0xf889, KEY_6 },1324{ 0xf88f, KEY_7 },1325{ 0xf88e, KEY_8 },1326{ 0xf88d, KEY_9 },1327{ 0xf892, KEY_0 },1328{ 0xf896, KEY_CHANNELUP },1329{ 0xf891, KEY_CHANNELDOWN },1330{ 0xf893, KEY_VOLUMEUP },1331{ 0xf88c, KEY_VOLUMEDOWN },1332{ 0xf883, KEY_RECORD },1333{ 0xf898, KEY_PAUSE },1334{ 0xf899, KEY_OK },1335{ 0xf89a, KEY_SHUFFLE },1336{ 0xf881, KEY_UP },1337{ 0xf890, KEY_LEFT },1338{ 0xf882, KEY_RIGHT },1339{ 0xf888, KEY_DOWN },1340{ 0xf895, KEY_FAVORITES },1341{ 0xf897, KEY_SUBTITLE },1342{ 0xf89d, KEY_ZOOM },1343{ 0xf89f, KEY_EXIT },1344{ 0xf89e, KEY_MENU },1345{ 0xf89c, KEY_EPG },1346{ 0xf880, KEY_PREVIOUS },1347{ 0xf89b, KEY_MODE }1348};13491350static struct rc_map_table rc_map_su3000_table[] = {1351{ 0x25, KEY_POWER }, /* right-bottom Red */1352{ 0x0a, KEY_MUTE }, /* -/-- */1353{ 0x01, KEY_1 },1354{ 0x02, KEY_2 },1355{ 0x03, KEY_3 },1356{ 0x04, KEY_4 },1357{ 0x05, KEY_5 },1358{ 0x06, KEY_6 },1359{ 0x07, KEY_7 },1360{ 0x08, KEY_8 },1361{ 0x09, KEY_9 },1362{ 0x00, KEY_0 },1363{ 0x20, KEY_UP }, /* CH+ */1364{ 0x21, KEY_DOWN }, /* CH+ */1365{ 0x12, KEY_VOLUMEUP }, /* Brightness Up */1366{ 0x13, KEY_VOLUMEDOWN },/* Brightness Down */1367{ 0x1f, KEY_RECORD },1368{ 0x17, KEY_PLAY },1369{ 0x16, KEY_PAUSE },1370{ 0x0b, KEY_STOP },1371{ 0x27, KEY_FASTFORWARD },/* >> */1372{ 0x26, KEY_REWIND }, /* << */1373{ 0x0d, KEY_OK }, /* Mute */1374{ 0x11, KEY_LEFT }, /* VOL- */1375{ 0x10, KEY_RIGHT }, /* VOL+ */1376{ 0x29, KEY_BACK }, /* button under 9 */1377{ 0x2c, KEY_MENU }, /* TTX */1378{ 0x2b, KEY_EPG }, /* EPG */1379{ 0x1e, KEY_RED }, /* OSD */1380{ 0x0e, KEY_GREEN }, /* Window */1381{ 0x2d, KEY_YELLOW }, /* button under << */1382{ 0x0f, KEY_BLUE }, /* bottom yellow button */1383{ 0x14, KEY_AUDIO }, /* Snapshot */1384{ 0x38, KEY_TV }, /* TV/Radio */1385{ 0x0c, KEY_ESC } /* upper Red button */1386};13871388static struct rc_map_dvb_usb_table_table keys_tables[] = {1389{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },1390{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },1391{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },1392{ rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },1393};13941395static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)1396{1397struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;1398int keymap_size = d->props.rc.legacy.rc_map_size;1399u8 key[2];1400struct i2c_msg msg = {1401.addr = DW2102_RC_QUERY,1402.flags = I2C_M_RD,1403.buf = key,1404.len = 21405};1406int i;1407/* override keymap */1408if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {1409keymap = keys_tables[ir_keymap - 1].rc_keys ;1410keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;1411} else if (ir_keymap > ARRAY_SIZE(keys_tables))1412return 0; /* none */14131414*state = REMOTE_NO_KEY_PRESSED;1415if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {1416for (i = 0; i < keymap_size ; i++) {1417if (rc5_data(&keymap[i]) == msg.buf[0]) {1418*state = REMOTE_KEY_PRESSED;1419*event = keymap[i].keycode;1420break;1421}14221423}14241425if ((*state) == REMOTE_KEY_PRESSED)1426deb_rc("%s: found rc key: %x, %x, event: %x\n",1427__func__, key[0], key[1], (*event));1428else if (key[0] != 0xff)1429deb_rc("%s: unknown rc key: %x, %x\n",1430__func__, key[0], key[1]);14311432}14331434return 0;1435}14361437static struct usb_device_id dw2102_table[] = {1438{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},1439{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},1440{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},1441{USB_DEVICE(0x9022, USB_PID_TEVII_S650)},1442{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},1443{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},1444{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},1445{USB_DEVICE(0x3011, USB_PID_PROF_1100)},1446{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},1447{USB_DEVICE(0x3034, 0x7500)},1448{USB_DEVICE(0x1f4d, 0x3000)},1449{USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},1450{USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},1451{USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},1452{USB_DEVICE(0x1f4d, 0x3100)},1453{ }1454};14551456MODULE_DEVICE_TABLE(usb, dw2102_table);14571458static int dw2102_load_firmware(struct usb_device *dev,1459const struct firmware *frmwr)1460{1461u8 *b, *p;1462int ret = 0, i;1463u8 reset;1464u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};1465const struct firmware *fw;1466const char *fw_2101 = "dvb-usb-dw2101.fw";14671468switch (dev->descriptor.idProduct) {1469case 0x2101:1470ret = request_firmware(&fw, fw_2101, &dev->dev);1471if (ret != 0) {1472err(err_str, fw_2101);1473return ret;1474}1475break;1476default:1477fw = frmwr;1478break;1479}1480info("start downloading DW210X firmware");1481p = kmalloc(fw->size, GFP_KERNEL);1482reset = 1;1483/*stop the CPU*/1484dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);1485dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);14861487if (p != NULL) {1488memcpy(p, fw->data, fw->size);1489for (i = 0; i < fw->size; i += 0x40) {1490b = (u8 *) p + i;1491if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,1492DW210X_WRITE_MSG) != 0x40) {1493err("error while transferring firmware");1494ret = -EINVAL;1495break;1496}1497}1498/* restart the CPU */1499reset = 0;1500if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,1501DW210X_WRITE_MSG) != 1) {1502err("could not restart the USB controller CPU.");1503ret = -EINVAL;1504}1505if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,1506DW210X_WRITE_MSG) != 1) {1507err("could not restart the USB controller CPU.");1508ret = -EINVAL;1509}1510/* init registers */1511switch (dev->descriptor.idProduct) {1512case USB_PID_TEVII_S650:1513dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;1514dw2104_properties.rc.legacy.rc_map_size =1515ARRAY_SIZE(rc_map_tevii_table);1516case USB_PID_DW2104:1517reset = 1;1518dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,1519DW210X_WRITE_MSG);1520/* break omitted intentionally */1521case USB_PID_DW3101:1522reset = 0;1523dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,1524DW210X_WRITE_MSG);1525break;1526case USB_PID_CINERGY_S:1527case USB_PID_DW2102:1528dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,1529DW210X_WRITE_MSG);1530dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,1531DW210X_READ_MSG);1532/* check STV0299 frontend */1533dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,1534DW210X_READ_MSG);1535if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {1536dw2102_properties.i2c_algo = &dw2102_i2c_algo;1537dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;1538break;1539} else {1540/* check STV0288 frontend */1541reset16[0] = 0xd0;1542reset16[1] = 1;1543reset16[2] = 0;1544dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,1545DW210X_WRITE_MSG);1546dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,1547DW210X_READ_MSG);1548if (reset16[2] == 0x11) {1549dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;1550break;1551}1552}1553case 0x2101:1554dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,1555DW210X_READ_MSG);1556dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,1557DW210X_READ_MSG);1558dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,1559DW210X_READ_MSG);1560dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,1561DW210X_READ_MSG);1562break;1563}15641565msleep(100);1566kfree(p);1567}1568return ret;1569}15701571static struct dvb_usb_device_properties dw2102_properties = {1572.caps = DVB_USB_IS_AN_I2C_ADAPTER,1573.usb_ctrl = DEVICE_SPECIFIC,1574.firmware = "dvb-usb-dw2102.fw",1575.no_reconnect = 1,15761577.i2c_algo = &dw2102_serit_i2c_algo,15781579.rc.legacy = {1580.rc_map_table = rc_map_dw210x_table,1581.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),1582.rc_interval = 150,1583.rc_query = dw2102_rc_query,1584},15851586.generic_bulk_ctrl_endpoint = 0x81,1587/* parameter for the MPEG2-data transfer */1588.num_adapters = 1,1589.download_firmware = dw2102_load_firmware,1590.read_mac_address = dw210x_read_mac_address,1591.adapter = {1592{1593.frontend_attach = dw2102_frontend_attach,1594.stream = {1595.type = USB_BULK,1596.count = 8,1597.endpoint = 0x82,1598.u = {1599.bulk = {1600.buffersize = 4096,1601}1602}1603},1604}1605},1606.num_device_descs = 3,1607.devices = {1608{"DVBWorld DVB-S 2102 USB2.0",1609{&dw2102_table[0], NULL},1610{NULL},1611},1612{"DVBWorld DVB-S 2101 USB2.0",1613{&dw2102_table[1], NULL},1614{NULL},1615},1616{"TerraTec Cinergy S USB",1617{&dw2102_table[4], NULL},1618{NULL},1619},1620}1621};16221623static struct dvb_usb_device_properties dw2104_properties = {1624.caps = DVB_USB_IS_AN_I2C_ADAPTER,1625.usb_ctrl = DEVICE_SPECIFIC,1626.firmware = "dvb-usb-dw2104.fw",1627.no_reconnect = 1,16281629.i2c_algo = &dw2104_i2c_algo,1630.rc.legacy = {1631.rc_map_table = rc_map_dw210x_table,1632.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),1633.rc_interval = 150,1634.rc_query = dw2102_rc_query,1635},16361637.generic_bulk_ctrl_endpoint = 0x81,1638/* parameter for the MPEG2-data transfer */1639.num_adapters = 1,1640.download_firmware = dw2102_load_firmware,1641.read_mac_address = dw210x_read_mac_address,1642.adapter = {1643{1644.frontend_attach = dw2104_frontend_attach,1645.stream = {1646.type = USB_BULK,1647.count = 8,1648.endpoint = 0x82,1649.u = {1650.bulk = {1651.buffersize = 4096,1652}1653}1654},1655}1656},1657.num_device_descs = 2,1658.devices = {1659{ "DVBWorld DW2104 USB2.0",1660{&dw2102_table[2], NULL},1661{NULL},1662},1663{ "TeVii S650 USB2.0",1664{&dw2102_table[3], NULL},1665{NULL},1666},1667}1668};16691670static struct dvb_usb_device_properties dw3101_properties = {1671.caps = DVB_USB_IS_AN_I2C_ADAPTER,1672.usb_ctrl = DEVICE_SPECIFIC,1673.firmware = "dvb-usb-dw3101.fw",1674.no_reconnect = 1,16751676.i2c_algo = &dw3101_i2c_algo,1677.rc.legacy = {1678.rc_map_table = rc_map_dw210x_table,1679.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),1680.rc_interval = 150,1681.rc_query = dw2102_rc_query,1682},16831684.generic_bulk_ctrl_endpoint = 0x81,1685/* parameter for the MPEG2-data transfer */1686.num_adapters = 1,1687.download_firmware = dw2102_load_firmware,1688.read_mac_address = dw210x_read_mac_address,1689.adapter = {1690{1691.frontend_attach = dw3101_frontend_attach,1692.tuner_attach = dw3101_tuner_attach,1693.stream = {1694.type = USB_BULK,1695.count = 8,1696.endpoint = 0x82,1697.u = {1698.bulk = {1699.buffersize = 4096,1700}1701}1702},1703}1704},1705.num_device_descs = 1,1706.devices = {1707{ "DVBWorld DVB-C 3101 USB2.0",1708{&dw2102_table[5], NULL},1709{NULL},1710},1711}1712};17131714static struct dvb_usb_device_properties s6x0_properties = {1715.caps = DVB_USB_IS_AN_I2C_ADAPTER,1716.usb_ctrl = DEVICE_SPECIFIC,1717.size_of_priv = sizeof(struct s6x0_state),1718.firmware = "dvb-usb-s630.fw",1719.no_reconnect = 1,17201721.i2c_algo = &s6x0_i2c_algo,1722.rc.legacy = {1723.rc_map_table = rc_map_tevii_table,1724.rc_map_size = ARRAY_SIZE(rc_map_tevii_table),1725.rc_interval = 150,1726.rc_query = dw2102_rc_query,1727},17281729.generic_bulk_ctrl_endpoint = 0x81,1730.num_adapters = 1,1731.download_firmware = dw2102_load_firmware,1732.read_mac_address = s6x0_read_mac_address,1733.adapter = {1734{1735.frontend_attach = zl100313_frontend_attach,1736.stream = {1737.type = USB_BULK,1738.count = 8,1739.endpoint = 0x82,1740.u = {1741.bulk = {1742.buffersize = 4096,1743}1744}1745},1746}1747},1748.num_device_descs = 1,1749.devices = {1750{"TeVii S630 USB",1751{&dw2102_table[6], NULL},1752{NULL},1753},1754}1755};17561757struct dvb_usb_device_properties *p1100;1758static struct dvb_usb_device_description d1100 = {1759"Prof 1100 USB ",1760{&dw2102_table[7], NULL},1761{NULL},1762};17631764struct dvb_usb_device_properties *s660;1765static struct dvb_usb_device_description d660 = {1766"TeVii S660 USB",1767{&dw2102_table[8], NULL},1768{NULL},1769};17701771static struct dvb_usb_device_description d480_1 = {1772"TeVii S480.1 USB",1773{&dw2102_table[12], NULL},1774{NULL},1775};17761777static struct dvb_usb_device_description d480_2 = {1778"TeVii S480.2 USB",1779{&dw2102_table[13], NULL},1780{NULL},1781};17821783struct dvb_usb_device_properties *p7500;1784static struct dvb_usb_device_description d7500 = {1785"Prof 7500 USB DVB-S2",1786{&dw2102_table[9], NULL},1787{NULL},1788};17891790static struct dvb_usb_device_properties su3000_properties = {1791.caps = DVB_USB_IS_AN_I2C_ADAPTER,1792.usb_ctrl = DEVICE_SPECIFIC,1793.size_of_priv = sizeof(struct su3000_state),1794.power_ctrl = su3000_power_ctrl,1795.num_adapters = 1,1796.identify_state = su3000_identify_state,1797.i2c_algo = &su3000_i2c_algo,17981799.rc.legacy = {1800.rc_map_table = rc_map_su3000_table,1801.rc_map_size = ARRAY_SIZE(rc_map_su3000_table),1802.rc_interval = 150,1803.rc_query = dw2102_rc_query,1804},18051806.read_mac_address = su3000_read_mac_address,18071808.generic_bulk_ctrl_endpoint = 0x01,18091810.adapter = {1811{1812.streaming_ctrl = su3000_streaming_ctrl,1813.frontend_attach = su3000_frontend_attach,1814.stream = {1815.type = USB_BULK,1816.count = 8,1817.endpoint = 0x82,1818.u = {1819.bulk = {1820.buffersize = 4096,1821}1822}1823}1824}1825},1826.num_device_descs = 3,1827.devices = {1828{ "SU3000HD DVB-S USB2.0",1829{ &dw2102_table[10], NULL },1830{ NULL },1831},1832{ "Terratec Cinergy S2 USB HD",1833{ &dw2102_table[11], NULL },1834{ NULL },1835},1836{ "X3M TV SPC1400HD PCI",1837{ &dw2102_table[14], NULL },1838{ NULL },1839},1840}1841};18421843static int dw2102_probe(struct usb_interface *intf,1844const struct usb_device_id *id)1845{1846p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);1847if (!p1100)1848return -ENOMEM;1849/* copy default structure */1850memcpy(p1100, &s6x0_properties,1851sizeof(struct dvb_usb_device_properties));1852/* fill only different fields */1853p1100->firmware = "dvb-usb-p1100.fw";1854p1100->devices[0] = d1100;1855p1100->rc.legacy.rc_map_table = rc_map_tbs_table;1856p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);1857p1100->adapter->frontend_attach = stv0288_frontend_attach;18581859s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);1860if (!s660) {1861kfree(p1100);1862return -ENOMEM;1863}1864memcpy(s660, &s6x0_properties,1865sizeof(struct dvb_usb_device_properties));1866s660->firmware = "dvb-usb-s660.fw";1867s660->num_device_descs = 3;1868s660->devices[0] = d660;1869s660->devices[1] = d480_1;1870s660->devices[2] = d480_2;1871s660->adapter->frontend_attach = ds3000_frontend_attach;18721873p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);1874if (!p7500) {1875kfree(p1100);1876kfree(s660);1877return -ENOMEM;1878}1879memcpy(p7500, &s6x0_properties,1880sizeof(struct dvb_usb_device_properties));1881p7500->firmware = "dvb-usb-p7500.fw";1882p7500->devices[0] = d7500;1883p7500->rc.legacy.rc_map_table = rc_map_tbs_table;1884p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);1885p7500->adapter->frontend_attach = prof_7500_frontend_attach;18861887if (0 == dvb_usb_device_init(intf, &dw2102_properties,1888THIS_MODULE, NULL, adapter_nr) ||18890 == dvb_usb_device_init(intf, &dw2104_properties,1890THIS_MODULE, NULL, adapter_nr) ||18910 == dvb_usb_device_init(intf, &dw3101_properties,1892THIS_MODULE, NULL, adapter_nr) ||18930 == dvb_usb_device_init(intf, &s6x0_properties,1894THIS_MODULE, NULL, adapter_nr) ||18950 == dvb_usb_device_init(intf, p1100,1896THIS_MODULE, NULL, adapter_nr) ||18970 == dvb_usb_device_init(intf, s660,1898THIS_MODULE, NULL, adapter_nr) ||18990 == dvb_usb_device_init(intf, p7500,1900THIS_MODULE, NULL, adapter_nr) ||19010 == dvb_usb_device_init(intf, &su3000_properties,1902THIS_MODULE, NULL, adapter_nr))1903return 0;19041905return -ENODEV;1906}19071908static struct usb_driver dw2102_driver = {1909.name = "dw2102",1910.probe = dw2102_probe,1911.disconnect = dvb_usb_device_exit,1912.id_table = dw2102_table,1913};19141915static int __init dw2102_module_init(void)1916{1917int ret = usb_register(&dw2102_driver);1918if (ret)1919err("usb_register failed. Error number %d", ret);19201921return ret;1922}19231924static void __exit dw2102_module_exit(void)1925{1926usb_deregister(&dw2102_driver);1927}19281929module_init(dw2102_module_init);1930module_exit(dw2102_module_exit);19311932MODULE_AUTHOR("Igor M. Liplianin (c) [email protected]");1933MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"1934" DVB-C 3101 USB2.0,"1935" TeVii S600, S630, S650, S660, S480,"1936" Prof 1100, 7500 USB2.0,"1937" Geniatech SU3000 devices");1938MODULE_VERSION("0.1");1939MODULE_LICENSE("GPL");194019411942