diff --git a/packages/linux/patches/3.7.10/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/3.7.10/linux-995-CX24120-13Z_frontend.patch new file mode 100755 index 0000000000..32e45a1e88 --- /dev/null +++ b/packages/linux/patches/3.7.10/linux-995-CX24120-13Z_frontend.patch @@ -0,0 +1,1577 @@ +http://patchwork.linuxtv.org/patch/10575/ +modified for 3.7.10 + +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400 +@@ -91,6 +91,8 @@ + int feedcount; + int pid_filtering; + int fullts_streaming_state; ++ /* the stream will be activated by an externally (by the fe for example) */ ++ int need_external_stream_control; + + /* bus specific callbacks */ + flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, +@@ -177,6 +179,8 @@ + struct dvb_demux_feed *dvbdmxfeed, int onoff); + void flexcop_hw_filter_init(struct flexcop_device *fc); + ++extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff); ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); + + void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400 +@@ -12,6 +12,7 @@ + #include "cx24113.h" + #include "cx24123.h" + #include "isl6421.h" ++#include "cx24120.h" + #include "mt352.h" + #include "bcm3510.h" + #include "nxt200x.h" +@@ -26,6 +27,15 @@ + #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ + (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) + ++#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120) ++static int flexcop_fe_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, char* name) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ return request_firmware(fw, name, fc->dev); ++} ++#endif ++ + /* lnb control */ + #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) + static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +@@ -445,13 +455,6 @@ + + /* AirStar ATSC 1st generation */ + #if FE_SUPPORTED(BCM3510) +-static int flexcop_fe_request_firmware(struct dvb_frontend *fe, +- const struct firmware **fw, char* name) +-{ +- struct flexcop_device *fc = fe->dvb->priv; +- return request_firmware(fw, name, fc->dev); +-} +- + static struct bcm3510_config air2pc_atsc_first_gen_config = { + .demod_address = 0x0f, + .request_firmware = flexcop_fe_request_firmware, +@@ -619,10 +622,40 @@ + #define cablestar2_attach NULL + #endif + ++/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */ ++#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421) ++static const struct cx24120_config skystar2_rev3_3_cx24120_config = { ++ .i2c_addr = 0x55, ++ .request_firmware = flexcop_fe_request_firmware, ++}; ++ ++static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) ++{ ++// struct dvb_frontend_ops *ops; ++ ++ fc->fe = dvb_attach(cx24120_attach, ++ &skystar2_rev3_3_cx24120_config, i2c); ++ if (fc->fe == NULL) return 0; ++ fc->dev_type = FC_SKYS2_REV33; ++ fc->fc_i2c_adap[2].no_base_addr = 1; ++ if ( (dvb_attach(isl6421_attach, fc->fe, ++ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) ) { ++ err("ISL6421 could NOT be attached!"); ++ return 0; ++ } ++ info("ISL6421 successfully attached."); ++// ops = &fc->fe->ops; ++ return 1; ++} ++#else ++#define skystarS2_rev33_attach NULL ++#endif ++ + static struct { + flexcop_device_type_t type; + int (*attach)(struct flexcop_device *, struct i2c_adapter *); + } flexcop_frontends[] = { ++ { FC_SKYS2_REV33, skystarS2_rev33_attach }, + { FC_SKY_REV27, skystar2_rev27_attach }, + { FC_SKY_REV28, skystar2_rev28_attach }, + { FC_SKY_REV26, skystar2_rev26_attach }, +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400 +@@ -11,6 +11,12 @@ + deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); + } + ++void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ flexcop_rcv_data_ctrl(fc, onoff); ++} ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) + { + flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); +@@ -199,6 +205,7 @@ + + /* if it was the first or last feed request change the stream-status */ + if (fc->feedcount == onoff) { ++ if (!fc->need_external_stream_control) + flexcop_rcv_data_ctrl(fc, onoff); + if (fc->stream_control) /* device specific stream control */ + fc->stream_control(fc, onoff); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400 +@@ -56,6 +56,7 @@ + [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", + [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", + [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", ++ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3", + }; + + static const char *flexcop_bus_names[] = { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400 +@@ -24,6 +24,7 @@ + FC_SKY_REV26, + FC_SKY_REV27, + FC_SKY_REV28, ++ FC_SKYS2_REV33, + } flexcop_device_type_t; + + typedef enum { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig +--- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -3,6 +3,7 @@ + depends on DVB_CORE && I2C + depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB + default y ++ select DVB_CX24120 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400 +@@ -0,0 +1,1053 @@ ++/* ++ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver ++ Version 0.0.4a 03.04.2012 ++ ++ Copyright (C) 2009 Sergey Tyurin ++ Updated 2012 by Jannis Achstetter ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "cx24120.h" ++#include "cx24120_const.h" ++ ++//========================== ++#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \ ++ printk(args); } } while (0) ++#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \ ++ printk(args); } while (0) ++#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \ ++ printk(args); } while (0) ++//========================== ++ ++static int cx24120_debug=0; ++static int reg_debug=0; ++MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware"); ++module_param(cx24120_debug, int, 0644); ++MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)"); ++ ++// ############################## ++struct cx24120_state { ++ struct i2c_adapter *i2c; ++ const struct cx24120_config *config; ++ struct dvb_frontend frontend; ++ u8 need_set_mpeg_out; ++ u8 attached; ++ u8 dvb_s2_mode; ++ u8 cold_init; ++}; ++// ##################################### ++// #### Command message to firmware #### ++struct cx24120_cmd { // total size = 36 ++ u8 id; // [00] - message id ++ u8 arg[30]; // [04] - message first byte ++ u8 len; // [34] - message lengh or first registers to read ++ u8 reg; // [35] - number of registers to read ++}; ++ ++//=================================================================== ++static int cx24120_readreg(struct cx24120_state *state, u8 reg) ++{ ++ int ret; ++ u8 buf = 0; ++ struct i2c_msg msg[] = { ++ { .addr = state->config->i2c_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = ® }, ++ ++ { .addr = state->config->i2c_addr, ++ .flags = I2C_M_RD, ++ .len = 1, ++ .buf = &buf } ++ }; ++ ret = i2c_transfer(state->i2c, msg, 2); ++ if (ret != 2) { ++ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf); ++ return buf; ++} // end cx24120_readreg ++//=================================================================== ++static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = 2 }; ++ int ret; ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data); ++ return 0; ++} // end cx24120_writereg ++//=================================================================== ++static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr) ++{ ++ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */ ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = len }; ++ int ret; ++ ++ do { ++ buf[0] = reg; ++ msg.len = len > 4 ? 4 : len; ++ memcpy(&buf[1], values, msg.len); ++ len -= msg.len; // data length revers counter ++ values += msg.len; // incr data pointer ++ if (incr) reg += msg.len; ++ msg.len++; /* don't forget the addr byte */ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); ++ return ret; ++ } ++ if (reg_debug) { ++ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages ++ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug ++ reg, buf[1], buf[2], buf[3], buf[4]); ++ } ++ } ++ } while (len); ++ return 0; ++} // end cx24120_writeregN ++//=================================================================== ++static struct dvb_frontend_ops cx24120_ops; ++//=================================================================== ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c) ++{ ++ struct cx24120_state *state = NULL; ++ int demod_rev; ++ ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n"); ++ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n"); ++ state = kzalloc(sizeof(struct cx24120_state), ++ GFP_KERNEL); ++ if (state == NULL) { ++ err("### Unable to allocate memory for cx24120_state structure. :(\n"); ++ goto error; ++ } ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ /* check if the demod is present and has proper type */ ++ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION); ++ switch (demod_rev) { ++ case 0x07: ++ info("Demod CX24120 rev. 0x07 detected.\n"); ++ break; ++ case 0x05: ++ info("Demod CX24120 rev. 0x05 detected.\n"); ++ break; ++ default: ++ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev); ++ goto error; ++ } ++ /* create dvb_frontend */ ++ state->attached = 0x10; // set attached flag ++ state->cold_init=0; ++ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n"); ++ return &state->frontend; ++ ++error: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach ++//=================================================================== ++static int cx24120_test_rom(struct cx24120_state *state) ++{ ++ int err, ret; ++ err = cx24120_readreg(state, 0xFD); ++ if (err & 4 ) ++ { ++ ret = cx24120_readreg(state, 0xDF) & 0xFE; ++ err = cx24120_writereg(state, 0xDF, ret); ++ } ++ return err; ++} // end cx24120_test_rom ++//=================================================================== ++static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) | ++ (cx24120_readreg(state, CX24120_REG_QUALITY_L)); ++ dbginfo("read SNR index = %d\n", *snr); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr ++//=================================================================== ++static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word ++ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word ++ dbginfo("read BER index = %d\n", *ber); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd); ++//=================================================================== ++static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag) ++{ ++ u8 tristate; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ??? ++ cmd.arg[0] = 1; ++ cmd.arg[1] = 0; ++ tristate = flag ? 0 : (u8)(-1); ++ cmd.arg[2] = tristate; ++ cmd.arg[3] = 1; ++ cmd.len = 4; ++ ++ if(flag) dbginfo("MPEG output DISABLED\n"); ++ else dbginfo("MPEG output ENABLED\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_global_config ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd) ++{ ++ u8 xxzz; ++ u32 msg_cmd_mask; ++ int ret, ficus; ++ ++ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled? ++ // if yes: ++ xxzz = cmd->id - 0x11; // look for specific message id ++ if ( xxzz <= 0x13 ) { ++ msg_cmd_mask = 1 << xxzz; ++ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output ++ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b ++ cx24120_msg_mpeg_output_global_config(state, 0); ++ msleep(100); ++ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag ++ } ++ } ++ } ++ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target ++ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data ++ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end ++ ++ ficus = 1000; ++ while ( cx24120_readreg(state, 0x1F)) { // is command done??? ++ msleep(1); ++ if( !(--ficus)) { ++ err("Too long waiting 'done' state from reg(0x1F). :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ dbginfo("Successfully send message 0x%02x\n", cmd->id); ++ ++ if ( cmd->reg > 30 ) { ++ err("Too much registers to read. cmd->reg = %d", cmd->reg); ++ return -EREMOTEIO; ++ } ++ ficus = 0; ++ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read ++ while ( ficus < cmd->reg ){ // starts from reg No cmd->len ++ // number of registers to read is cmd->reg ++ // and write results starts from cmd->arg[0]. ++ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1)); ++ ++ficus; ++ } ++ } ++ return 0; ++} // end cx24120_message_send ++//=================================================================== ++static int cx24120_set_frontend(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u32 srate, freq; ++ fe_code_rate_t fec; ++ fe_spectral_inversion_t inversion; ++ u8 smbr1, smbr2; ++ int ret; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs ++ cmd.len = 15; ++ ++ freq = p->frequency; ++ srate = p->symbol_rate; ++ fec = p->fec_inner; ++ inversion = p->inversion; ++ ++ // check symbol rate ++ if ( srate > 31000000 ) { // if symbol rate > 31 000 ++ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp ++ smbr2 = (-(srate < 31000001) & 6) + 4; // edi ++ } else { ++ smbr1 = 3; ++ smbr2 = 6; ++ } ++ ++ ret = cx24120_writereg(state, 0xE6, smbr1); ++ ret = cx24120_readreg(state, 0xF0); ++ ret &= 0xFFFFFFF0; ++ ret |= smbr2; ++ ret = cx24120_writereg(state, 0xF0, ret); ++ ++ cmd.arg[0] = 0; // CMD_TUNER_REQUEST ++ ++ // Frequency ++ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */ ++ cmd.arg[2] = (freq & 0x00FF00) >> 8; ++ cmd.arg[3] = (freq & 0x0000FF); ++ ++ // Symbol Rate ++ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8; ++ cmd.arg[5] = ((srate/1000) & 0x00FF); ++ ++ // Inversion ++ if ( inversion ) { ++ if ( inversion == 1 ) cmd.arg[6] = 4; ++ else cmd.arg[6] = 0x0C; ++ } else { ++ cmd.arg[6] = 0; ++ } ++ ++ // FEC ++ switch ( fec ) // fec = p->u.qpsk.fec_inner ++ { ++ case 1: // FEC_1_2 ++ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset ++ case 2: // FEC_2_3 ++ cmd.arg[7] = 0x2F; break; ++ case 3: // FEC_3_4 ++ cmd.arg[7] = 0x30; break; ++ case 5: // FEC_5_6 ++ cmd.arg[7] = 0x31; break; ++ case 7: // FEC_7_8 ++ cmd.arg[7] = 0x32; break; ++ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9, ++ // FEC_AUTO, FEC_3_5, FEC_9_10 ++ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode ++ cmd.arg[7] = 0; ++ cmd.arg[11] = 0; ++ } else { ++ cmd.arg[7] = 0x2E; ++ cmd.arg[11] = 0xAC; ++ } ++ break; ++ } ++ cmd.arg[8] = 0x13; ++ cmd.arg[9] = 0x88; ++ cmd.arg[10] = 0; ++ cmd.arg[12] = smbr2; ++ cmd.arg[13] = smbr1; ++ cmd.arg[14] = 0; ++ ++ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ????? ++ ++ return cx24120_message_send(state, &cmd); ++ ++} ++EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend ++//=================================================================== ++void cx24120_message_fill(struct cx24120_cmd *cmd, ++ u8 msg_id, ++ u8 *msg_addr, ++ u8 msg_len, ++ u8 num_regs) ++{ ++ cmd->id = msg_id; ++ memcpy(&cmd->arg[0], msg_addr, msg_len); ++ cmd->len = msg_len; ++ cmd->reg = num_regs; ++} // end cx24120_message_fill ++//=================================================================== ++static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int result, sigstr_h, sigstr_l; ++ ++ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/); ++ ++ if( !(cx24120_message_send(state, &cmd)) ) { ++ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8; ++ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L ); ++ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l)); ++ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF; ++ dbginfo("Signal strength= 0x%x\n", *signal_strength); ++ result = 0; ++ } else { ++ err("error reading signal strength\n"); ++ result = -EREMOTEIO; ++ } ++ return result; ++} ++EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength ++//=================================================================== ++static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num, ++ struct cx24120_skystar2_mpeg_config *config_msg) ++{ ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id ++ cmd.len = 7; ++ cmd.arg[0] = num; // sequental number - can be 0,1,2 ++ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) | ++ ((config_msg->x1 >> 1) & 0x01); ++ cmd.arg[2] = 0x05; ++ cmd.arg[3] = 0x02; ++ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01); ++ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F); ++ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */ ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_config ++//=================================================================== ++static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_BURST; ++ cmd.arg[0] = 0x00; ++ if (burst) ++ cmd.arg[1] = 0x01; ++ dbginfo("burst sent.\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst ++//=================================================================== ++static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ dbginfo("cmd(0x23,4) - tone = %d\n", tone); ++ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { ++ err("Invalid tone=%d\n", tone); ++ return -EINVAL; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETTONE; // 0x23 ++ cmd.len = 4; ++ if (!tone) ++ cmd.arg[3] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone ++//=================================================================== ++static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETVOLTAGE; // ++ cmd.len = 2; ++ if (!(voltage - 1)) ++ cmd.arg[1] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage ++//=================================================================== ++static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int back_count; ++ ++ dbginfo("Start sending diseqc sequence===============\n"); ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_MSG1; // 0x20 ++ cmd.len = 11; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x03; ++ cmd.arg[3] = 0x16; ++ cmd.arg[4] = 0x28; ++ cmd.arg[5] = 0x01; ++ cmd.arg[6] = 0x01; ++ cmd.arg[7] = 0x14; ++ cmd.arg[8] = 0x19; ++ cmd.arg[9] = 0x14; ++ cmd.arg[10] = 0x1E; ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 1st message(0x%x) filed==========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ cmd.id = CMD_DISEQC_MSG2; // 0x21 ++ cmd.len = d->msg_len + 6; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x01; ++ cmd.arg[2] = 0x02; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x00; ++ cmd.arg[5] = d->msg_len; ++ ++ memcpy(&cmd.arg[6], &d->msg, d->msg_len); ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 2d message(0x%x) filed========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ back_count = 100; ++ do { ++ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) { ++ dbginfo("diseqc sequence sent success==========.\n"); ++ return 0; ++ } ++ msleep(5); ++ --back_count; ++ } while ( back_count ); ++ err("Too long waiting for diseqc.=============\n"); ++ return -ETIMEDOUT; ++} ++EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg ++//=================================================================== ++static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int ret, clock_seq_num, GettedFEC; ++ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id; ++ ++ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A ++ dbginfo("status = 0x%x\n", ret); ++ *status = 0; ++ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL; ++ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER; ++ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC); ++ ++ if ( ret & CX24120_HAS_LOCK ) { // 0x08 ++ *status |= FE_HAS_LOCK; ++ if ( state->need_set_mpeg_out & 1 ) { // just tuned??? ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_CLOCK_READ; ++ cmd.arg[0] = 0x00; ++ cmd.len = 1; // cmd.reg != 0, so it is first register to read ++ cmd.reg = 6; // number of registers to read (0x01-0x06) ++ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result ++ // 0x02-0x07 ++ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14 ++ GettedFEC = ret; // 0x0d= 13 ++ dbginfo("Get FEC: %d\n", ret); ++ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2? ++ switch (ret-4) { ++ case 0: ++ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only ++ case 1: ++ case 8: ++ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only ++ case 2: ++ case 9: ++ mode_code = 0x02; goto mode_8PSK; // FEC_2_3 ++ case 3: ++ case 10: ++ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+ ++ case 4: ++ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only ++ case 5: ++ case 11: ++ mode_code = 0x05; goto mode_8PSK; // FEC_5_6 ++ case 6: ++ case 12: ++ mode_code = 0x08; goto mode_8PSK; // FEC_8_9 ++ case 7: ++ case 13: ++ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only ++ default: ++ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4); ++ mode_code = 0x01; // set like for mode 0 ++ mode_8PSK: ++ if ( ret > 11 ) { // 14 ++ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag ++ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code); ++ } else { ++ mode_QPSK: ++ mode_8PSK_flag = 0x00; ++ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4); ++ } ++ break; ++ } // end switch ++ } // end if dvb_s2_mode // dvb-s2 ++ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S ++ switch ( ret - 2 ) { ++ case 0: ++ mode_code = 2; break; // FEC_2_3 ++ case 1: ++ mode_code = 3; break; // FEC_3_4 ++ case 2: ++ mode_code = 4; break; // FEC_4_5 ++ case 3: ++ mode_code = 5; break; // FEC_5_6 ++ case 4: ++ mode_code = 6; break; // FEC_6_7 ++ case 5: ++ mode_code = 7; break; // FEC_7_8 ++ default: ++ mode_code = 1;break; // FEC_1_2 ++ } ++ mode_8PSK_flag = 0; ++ } // end of switch for dvb-s ++ ++ attached_flag = 0x10; ++ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner ++ attached_flag = 0; ++ ret = 0; ++ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2 ++ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ??? ++ // bit 4 bit 5 bit 0 bit 3 ++ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible, ++ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag ++ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5 ++ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n", ++ clock_id, mode_8PSK_flag, mode_code); ++ ++ clock_seq_num = 0; ++ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) || ++ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) || ++ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) ) ++ { ++ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num, ++ * clock_ratios_table[clock_seq_num].ratio_id, ++ * clock_ratios_table[clock_seq_num].mode_xPSK, ++ * clock_ratios_table[clock_seq_num].fec_mode); ++ */ ++ ++clock_seq_num; ++ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) { ++ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n"); ++ goto settings_end; ++ } ++ } ++ //############################### ++ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n", ++ GettedFEC, ++ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early ++ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16 ++ clock_seq_num, ++ clock_ratios_table[clock_seq_num].m_rat, ++ clock_ratios_table[clock_seq_num].n_rat, ++ clock_ratios_table[clock_seq_num].rate); ++ //############################### ++ cmd.id = CMD_CLOCK_SET; ++ cmd.len = 10; ++ cmd.reg = 0; ++ cmd.arg[0] = 0; ++ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner ++ ++ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF; ++ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF; ++ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF; ++ ++ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF; ++ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF; ++ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF; ++ ++ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF; ++ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF; ++ ++ cx24120_message_send(state, &cmd); ++ ++ settings_end: ++ msleep(200); ++ cx24120_msg_mpeg_output_global_config(state, 1); ++ state->dvb_s2_mode |= 0x02; // set mpeg flag ++ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag ++ } ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status ++//=================================================================== ++int cx24120_init(struct dvb_frontend *fe) ++{ ++ const struct firmware *fw; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u8 ret, ret_EA, reg1, fL, fH; ++ u32 vco, xtal_khz; ++ u64 inv_vco, res, xxyyzz; ++ int reset_result; ++ ++ if( state->cold_init ) return 0; ++ ++ ret = cx24120_writereg(state, 0xEA, 0x00); ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_readreg(state, 0xFC) & 0xFE; ++ ret = cx24120_writereg(state, 0xFC, ret); ++ ret = cx24120_writereg(state, 0xC3, 0x04); ++ ret = cx24120_writereg(state, 0xC4, 0x04); ++ ret = cx24120_writereg(state, 0xCE, 0x00); ++ ret = cx24120_writereg(state, 0xCF, 0x00); ++ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE; ++ ret = cx24120_writereg(state, 0xEA, ret_EA); ++ ret = cx24120_writereg(state, 0xEB, 0x0C); ++ ret = cx24120_writereg(state, 0xEC, 0x06); ++ ret = cx24120_writereg(state, 0xED, 0x05); ++ ret = cx24120_writereg(state, 0xEE, 0x03); ++ ret = cx24120_writereg(state, 0xEF, 0x05); ++ ret = cx24120_writereg(state, 0xF3, 0x03); ++ ret = cx24120_writereg(state, 0xF4, 0x44); ++ ++ reg1 = 0xF0; ++ do { ++ cx24120_writereg(state, reg1, 0x04); ++ cx24120_writereg(state, reg1 - 10, 0x02); ++ ++reg1; ++ } while ( reg1 != 0xF3 ); ++ ++ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01)); ++ reg1 = 0xC5; ++ do { ++ ret = cx24120_writereg(state, reg1, 0x00); ++ ret = cx24120_writereg(state, reg1 + 1, 0x00); ++ reg1 += 2; ++ } while ( reg1 != 0xCB ); ++ ++ ret = cx24120_writereg(state, 0xE4, 0x03); ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ ++ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE); ++ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE); ++ if (ret) { ++ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret); ++ return ret; ++ } ++ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n", ++ (int)fw->size, // firmware_size in bytes u32* ++ fw->data[0], // fw 1st byte ++ fw->data[1], // fw 2d byte ++ fw->data[fw->size - 2], // fw before last byte ++ fw->data[fw->size - 1]); // fw last byte ++ ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_writereg(state, 0xE0, 0x76); ++ ret = cx24120_writereg(state, 0xF7, 0x81); ++ ret = cx24120_writereg(state, 0xF8, 0x00); ++ ret = cx24120_writereg(state, 0xF9, 0x00); ++ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00); ++ ret = cx24120_writereg(state, 0xF7, 0xC0); ++ ret = cx24120_writereg(state, 0xE0, 0x00); ++ ret = (fw->size - 2) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a ++ ret = ((fw->size - 2) >> 8) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf ++ ret = cx24120_writereg(state, 0xF7, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x07); ++ msleep(500); ++ ++ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware ++ if ( ret == fw->data[fw->size - 1] ) { ++ dbginfo("Firmware uploaded successfully\n"); ++ reset_result = 0; ++ } else { ++ err("Firmware upload failed. Last byte returned=0x%x\n", ret ); ++ reset_result = -EREMOTEIO; ++ } ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ release_firmware(fw); ++ if (reset_result) ++ return reset_result; ++ ++ //================== Start tuner ++ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error tuner start! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_VCO_SET; // 0x10 ++ cmd.len = 12; ++ ++ // ###################### ++ // Calc VCO ++ xtal_khz = 10111; ++ xxyyzz = 0x400000000ULL; // 17179869184 ++ vco = xtal_khz * 10 * 4; // 404440 ++ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE ++ res = xxyyzz % vco; // 66864 = 0x010530 ++ ++ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco; ++ ++ fH = (inv_vco >> 8) & 0xFF; ++ fL = (inv_vco) & 0xFF; ++ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH); ++ // ###################### ++ ++ cmd.arg[0] = 0x06; ++ cmd.arg[1] = 0x2B; ++ cmd.arg[2] = 0xD8; ++ cmd.arg[3] = fH; // 0xA5 ++ cmd.arg[4] = fL; // 0xEE ++ cmd.arg[5] = 0x03; ++ cmd.arg[6] = 0x9D; ++ cmd.arg[7] = 0xFC; ++ cmd.arg[8] = 0x06; ++ cmd.arg[9] = 0x03; ++ cmd.arg[10] = 0x27; ++ cmd.arg[11] = 0x7F; ++ ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error set VCO! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ // set bandwidth ++ cmd.id = CMD_BANDWIDTH; // 0x15 ++ cmd.len = 12; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x00; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x05; ++ cmd.arg[5] = 0x02; ++ cmd.arg[6] = 0x02; ++ cmd.arg[7] = 0x00; ++ cmd.arg[8] = 0x05; ++ cmd.arg[9] = 0x02; ++ cmd.arg[10] = 0x02; ++ cmd.arg[11] = 0x00; ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("Error set bandwidth! :(\n"); ++ return -EREMOTEIO; ++ } ++ ret = cx24120_readreg(state, 0xBA); ++ if ( ret > 3) { ++ dbginfo("Reset-readreg 0xBA: %x\n", ret); ++ err("Error intitilizing tuner! :(\n"); ++ return -EREMOTEIO; ++ } ++ dbginfo("Tuner initialized correctly.\n"); ++ ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ if (cx24120_msg_mpeg_output_global_config(state, 0) || ++ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) ) ++ { ++ err("Error initilizing mpeg output. :(\n"); ++ return -EREMOTEIO; ++ } else { ++ cmd.id = 0x3C; // 60 ++ cmd.len = 0x03; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x10; ++ cmd.arg[2] = 0x10; ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error sending final init message. :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ state->cold_init=1; ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_init); // end cx24120_reset ++//=================================================================== ++static int cx24120_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ int delay_cnt, sd_idx = 0; ++ fe_status_t status; ++ ++ if (re_tune) { ++ ++// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n", ++// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate); ++ ++ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) { ++ ++sd_idx; ++ } ++ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay); ++ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2 ++ dbginfo("trying DVB-S =================\n"); ++ cx24120_set_frontend(fe); ++ ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S =================\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S LOCKED================\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S =================\n"); ++ ++ cx24120_read_status(fe, &status); ++ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S ++ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n"); ++ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ? ++ p->fec_inner = FEC_AUTO; ++ cx24120_set_frontend(fe); ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S2 LOCKED++++++++++++++++\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n"); ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune ++//=================================================================== ++static int cx24120_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++EXPORT_SYMBOL(cx24120_get_algo); ++//=================================================================== ++static int cx24120_sleep(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_sleep); ++//=================================================================== ++/*static int cx24120_wakeup(struct dvb_frontend *fe) ++ * { ++ * return 0; ++ * } ++ * EXPORT_SYMBOL(cx24120_wakeup); ++ */ ++//=================================================================== ++static int cx24120_get_frontend(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_get_frontend); ++//=================================================================== ++static void cx24120_release(struct dvb_frontend *fe) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ dbginfo("Clear state structure\n"); ++ kfree(state); ++} ++EXPORT_SYMBOL(cx24120_release); ++//=================================================================== ++static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) | ++ cx24120_readreg(state, CX24120_REG_UCB_L); ++ dbginfo("Blocks = %d\n", *ucblocks); ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ucblocks); ++// ######################################################################################## ++static struct dvb_frontend_ops cx24120_ops = { ++ ++ .delsys = { SYS_DVBS2 }, ++ .info = { ++ .name = "Conexant CX24120/CX24118", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = // 0x500006ff ++ FE_CAN_INVERSION_AUTO | //0x00 000 001 ++ FE_CAN_FEC_1_2 | //0x00 000 002 ++ FE_CAN_FEC_2_3 | //0x00 000 004 ++ FE_CAN_FEC_3_4 | //0x00 000 008 ++ FE_CAN_FEC_4_5 | //0x00 000 010 ++ FE_CAN_FEC_5_6 | //0x00 000 020 ++ FE_CAN_FEC_6_7 | //0x00 000 040 ++ FE_CAN_FEC_7_8 | //0x00 000 080 ++ FE_CAN_FEC_AUTO | //0x00 000 200 ++ FE_CAN_QPSK | //0x00 000 400 ++//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */ ++ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */ ++ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */ ++ }, //sum=50 000 6FF ++ .release = cx24120_release, ++ ++ .init = cx24120_init, ++ .sleep = cx24120_sleep, ++ ++ .tune = cx24120_tune, ++ .get_frontend_algo = cx24120_get_algo, ++ .set_frontend = cx24120_set_frontend, ++ ++ .get_frontend = cx24120_get_frontend, ++ .read_status = cx24120_read_status, ++ .read_ber = cx24120_read_ber, ++ .read_signal_strength = cx24120_read_signal_strength, ++ .read_snr = cx24120_read_snr, ++ .read_ucblocks = cx24120_read_ucblocks, ++ ++ .diseqc_send_master_cmd = cx24120_send_diseqc_msg, ++ ++ .diseqc_send_burst = cx24120_diseqc_send_burst, ++ .set_tone = cx24120_set_tone, ++ .set_voltage = cx24120_set_voltage, ++}; ++//=================================================================== ++MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)"); ++MODULE_AUTHOR("Sergey Tyurin"); ++MODULE_LICENSE("GPL"); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400 +@@ -0,0 +1,259 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * DVBS/S2 Satellite demod/tuner driver static definitins ++ * ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw" ++ ++// ############################## ++// ### cx24120 i2c registers ### ++#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register: ++#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc. ++#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result ++ ++#define CX24120_REG_FECMODE (0x39) // FEC status ++#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ... ++#define CX24120_REG_QUALITY_H (0x40) // SNR high byte ++#define CX24120_REG_QUALITY_L (0x41) // SNR low byte ++ ++#define CX24120_REG_BER_HH (0x47) // BER high byte of high word ++#define CX24120_REG_BER_HL (0x48) // BER low byte of high word ++#define CX24120_REG_BER_LH (0x49) // BER high byte of low word ++#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word ++ ++#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ??? ++#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte ++ ++#define CX24120_REG_UCB_H (0x50) // UCB high byte ++#define CX24120_REG_UCB_L (0x51) // UCB low byte ++ ++#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5 ++ ++// ############################## ++/* Command messages */ ++enum command_message_id { ++ CMD_VCO_SET = 0x10, // cmdlen = 12; ++ CMD_TUNEREQUEST = 0x11, // cmd.len = 15; ++ ++ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4; ++ CMD_MPEG_INIT = 0x14, // cmd.len = 7; ++ CMD_BANDWIDTH = 0x15, // cmd.len = 12; ++ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06 ++ CMD_CLOCK_SET = 0x17, // cmd.len = 10; ++ ++ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11; ++ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6; ++ CMD_SETVOLTAGE = 0x22, // cmd.len = 2; ++ CMD_SETTONE = 0x23, // cmd.len = 4; ++ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!! ++ ++ CMD_READ_SNR = 0x1A, // Read signal strength ++ CMD_START_TUNER = 0x1B, // ??? ++ ++ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03; ++}; ++// ############################## ++/* signal status */ ++#define CX24120_HAS_SIGNAL (0x01) ++#define CX24120_HAS_CARRIER (0x02) ++#define CX24120_HAS_VITERBI (0x04) ++#define CX24120_HAS_LOCK (0x08) ++#define CX24120_HAS_UNK1 (0x10) ++#define CX24120_HAS_UNK2 (0x20) ++#define CX24120_STATUS_MASK (0x0f) ++#define CX24120_SIGNAL_MASK (0xc0) ++ ++static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 }; ++static u8 cx24120_msg_read_sigstr[] = {0,0}; ++ ++static struct cx24120_skystar2_mpeg_config { ++ u8 x1; ++ u8 x2; ++ u8 x3; ++} initial_mpeg_config = { ++ 0xA1, // 10100001 ++ 0x76, // 01110110 ++ 0x07, // 00000111 ++}; ++ ++static struct cx24120_symrate_delay { ++ u32 symrate; ++ u32 delay; ++} symrates_pairs[] = { ++ { 3000000, 15000 }, ++ { 6000000, 10000 }, ++ { 8000000, 5000 }, ++ { 10000000, 2000 }, ++ {0x0FFFFFFFF, 400 }, ++}; ++ ++static struct cx24120_clock_ratios_table { ++ u32 ratio_id; ++ u32 mode_xPSK; ++ u32 fec_mode; ++ u32 m_rat; ++ u32 n_rat; ++ u32 rate; ++} clock_ratios_table[] = { ++{ 21 , 0 , 1 , 770068 , 763515 , 258 }, ++{ 21 , 0 , 100 , 97409 , 80370 , 310 }, ++{ 21 , 0 , 2 , 137293 , 101802 , 345 }, ++{ 21 , 0 , 3 , 4633447 , 3054060 , 388 }, ++{ 21 , 0 , 4 , 2472041 , 1527030 , 414 }, ++{ 21 , 0 , 5 , 85904 , 50901 , 432 }, ++{ 21 , 0 , 8 , 2751229 , 1527030 , 461 }, ++{ 21 , 0 , 101 , 1392872 , 763515 , 467 }, ++{ 21 , 99 , 100 , 1850771 , 1019430 , 464 }, ++{ 21 , 99 , 2 , 137293 , 67962 , 517 }, ++{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 21 , 99 , 5 , 85904 , 33981 , 647 }, ++{ 21 , 99 , 8 , 2751229 , 1019430 , 690 }, ++{ 21 , 99 , 101 , 1392872 , 509715 , 699 }, ++{ 29 , 0 , 1 , 770068 , 782127 , 252 }, ++{ 29 , 0 , 100 , 1850771 , 1564254 , 302 }, ++{ 29 , 0 , 2 , 686465 , 521418 , 337 }, ++{ 29 , 0 , 3 , 4633447 , 3128508 , 379 }, ++{ 29 , 0 , 4 , 2472041 , 1564254 , 404 }, ++{ 29 , 0 , 5 , 429520 , 260709 , 421 }, ++{ 29 , 0 , 8 , 2751229 , 1564254 , 450 }, ++{ 29 , 0 , 101 , 1392872 , 782127 , 455 }, ++{ 29 , 99 , 100 , 1850771 , 1043118 , 454 }, ++{ 29 , 99 , 2 , 686465 , 347706 , 505 }, ++{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 29 , 99 , 5 , 429520 , 173853 , 632 }, ++{ 29 , 99 , 8 , 2751229 , 1043118 , 675 }, ++{ 29 , 99 , 101 , 1392872 , 521559 , 683 }, ++{ 17 , 0 , 1 , 766052 , 763515 , 256 }, ++{ 17 , 0 , 100 , 96901 , 80370 , 308 }, ++{ 17 , 0 , 2 , 136577 , 101802 , 343 }, ++{ 17 , 0 , 3 , 4609283 , 3054060 , 386 }, ++{ 17 , 0 , 4 , 2459149 , 1527030 , 412 }, ++{ 17 , 0 , 5 , 85456 , 50901 , 429 }, ++{ 17 , 0 , 8 , 2736881 , 1527030 , 458 }, ++{ 17 , 0 , 101 , 1385608 , 763515 , 464 }, ++{ 17 , 99 , 100 , 1841119 , 1019430 , 462 }, ++{ 17 , 99 , 2 , 136577 , 67962 , 514 }, ++{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 17 , 99 , 5 , 85456 , 33981 , 643 }, ++{ 17 , 99 , 8 , 2736881 , 1019430 , 687 }, ++{ 17 , 99 , 101 , 1385608 , 509715 , 695 }, ++{ 25 , 0 , 1 , 766052 , 782127 , 250 }, ++{ 25 , 0 , 100 , 1841119 , 1564254 , 301 }, ++{ 25 , 0 , 2 , 682885 , 521418 , 335 }, ++{ 25 , 0 , 3 , 4609283 , 3128508 , 377 }, ++{ 25 , 0 , 4 , 2459149 , 1564254 , 402 }, ++{ 25 , 0 , 5 , 427280 , 260709 , 419 }, ++{ 25 , 0 , 8 , 2736881 , 1564254 , 447 }, ++{ 25 , 0 , 101 , 1385608 , 782127 , 453 }, ++{ 25 , 99 , 100 , 1841119 , 1043118 , 451 }, ++{ 25 , 99 , 2 , 682885 , 347706 , 502 }, ++{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 25 , 99 , 5 , 427280 , 173853 , 629 }, ++{ 25 , 99 , 8 , 2736881 , 1043118 , 671 }, ++{ 25 , 99 , 101 , 1385608 , 521559 , 680 }, ++{ 5 , 0 , 1 , 273088 , 254505 , 274 }, ++{ 5 , 0 , 100 , 17272 , 13395 , 330 }, ++{ 5 , 0 , 2 , 24344 , 16967 , 367 }, ++{ 5 , 0 , 3 , 410788 , 254505 , 413 }, ++{ 5 , 0 , 4 , 438328 , 254505 , 440 }, ++{ 5 , 0 , 5 , 30464 , 16967 , 459 }, ++{ 5 , 0 , 8 , 487832 , 254505 , 490 }, ++{ 5 , 0 , 101 , 493952 , 254505 , 496 }, ++{ 5 , 99 , 100 , 328168 , 169905 , 494 }, ++{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD ++{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 5 , 99 , 5 , 30464 , 11327 , 688 }, ++{ 5 , 99 , 8 , 487832 , 169905 , 735 }, ++{ 5 , 99 , 101 , 493952 , 169905 , 744 }, ++{ 13 , 0 , 1 , 273088 , 260709 , 268 }, ++{ 13 , 0 , 100 , 328168 , 260709 , 322 }, ++{ 13 , 0 , 2 , 121720 , 86903 , 358 }, ++{ 13 , 0 , 3 , 410788 , 260709 , 403 }, ++{ 13 , 0 , 4 , 438328 , 260709 , 430 }, ++{ 13 , 0 , 5 , 152320 , 86903 , 448 }, ++{ 13 , 0 , 8 , 487832 , 260709 , 479 }, ++{ 13 , 0 , 101 , 493952 , 260709 , 485 }, ++{ 13 , 99 , 100 , 328168 , 173853 , 483 }, ++{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk ++{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 13 , 99 , 5 , 152320 , 57951 , 672 }, ++{ 13 , 99 , 8 , 487832 , 173853 , 718 }, ++{ 13 , 99 , 101 , 493952 , 173853 , 727 }, ++{ 1 , 0 , 1 , 815248 , 763515 , 273 }, ++{ 1 , 0 , 100 , 51562 , 40185 , 328 }, ++{ 1 , 0 , 2 , 72674 , 50901 , 365 }, ++{ 1 , 0 , 3 , 1226323 , 763515 , 411 }, ++{ 1 , 0 , 4 , 1308538 , 763515 , 438 }, ++{ 1 , 0 , 5 , 90944 , 50901 , 457 }, ++{ 1 , 0 , 8 , 1456322 , 763515 , 488 }, ++{ 1 , 0 , 101 , 1474592 , 763515 , 494 }, ++{ 1 , 99 , 100 , 979678 , 509715 , 492 }, ++{ 1 , 99 , 2 , 72674 , 33981 , 547 }, ++{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2 ++{ 1 , 99 , 5 , 90944 , 33981 , 685 }, ++{ 1 , 99 , 8 , 1456322 , 509715 , 731 }, ++{ 1 , 99 , 101 , 1474592 , 509715 , 740 }, ++{ 9 , 0 , 1 , 815248 , 782127 , 266 }, ++{ 9 , 0 , 100 , 979678 , 782127 , 320 }, ++{ 9 , 0 , 2 , 363370 , 260709 , 356 }, ++{ 9 , 0 , 3 , 1226323 , 782127 , 401 }, ++{ 9 , 0 , 4 , 1308538 , 782127 , 428 }, ++{ 9 , 0 , 5 , 454720 , 260709 , 446 }, ++{ 9 , 0 , 8 , 1456322 , 782127 , 476 }, ++{ 9 , 0 , 101 , 1474592 , 782127 , 482 }, ++{ 9 , 99 , 100 , 979678 , 521559 , 480 }, ++{ 9 , 99 , 2 , 363370 , 173853 , 535 }, ++{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 9 , 99 , 5 , 454720 , 173853 , 669 }, ++{ 9 , 99 , 8 , 1456322 , 521559 , 714 }, ++{ 9 , 99 , 101 , 1474592 , 521559 , 723 }, ++{ 18 , 0 , 1 , 535 , 588 , 233 }, ++{ 18 , 0 , 2 , 1070 , 882 , 311 }, ++{ 18 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 16 , 0 , 1 , 763 , 816 , 239 }, ++{ 16 , 0 , 2 , 1526 , 1224 , 319 }, ++{ 16 , 0 , 3 , 2289 , 1632 , 359 }, ++{ 16 , 0 , 5 , 3815 , 2448 , 399 }, ++{ 16 , 0 , 7 , 5341 , 3264 , 419 }, ++{ 22 , 0 , 1 , 535 , 588 , 233 }, ++{ 22 , 0 , 2 , 1070 , 882 , 311 }, ++{ 22 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 20 , 0 , 1 , 143429 , 152592 , 241 }, ++{ 20 , 0 , 2 , 286858 , 228888 , 321 }, ++{ 20 , 0 , 3 , 430287 , 305184 , 361 }, ++{ 20 , 0 , 5 , 717145 , 457776 , 401 }, ++{ 20 , 0 , 7 , 1004003 , 610368 , 421 }, ++{ 2 , 0 , 1 , 584 , 588 , 254 }, ++{ 2 , 0 , 2 , 1169 , 882 , 339 }, ++{ 2 , 0 , 6 , 3507 , 2058 , 436 }, ++{ 0 , 0 , 1 , 812 , 816 , 255 }, ++{ 0 , 0 , 2 , 1624 , 1224 , 340 }, ++{ 0 , 0 , 3 , 2436 , 1632 , 382 }, ++{ 0 , 0 , 5 , 4060 , 2448 , 425 }, ++{ 0 , 0 , 7 , 5684 , 3264 , 446 }, ++{ 6 , 0 , 1 , 584 , 588 , 254 }, ++{ 6 , 0 , 2 , 1168 , 882 , 339 }, ++{ 6 , 0 , 6 , 3504 , 2058 , 436 }, ++{ 4 , 0 , 1 , 152592 , 152592 , 256 }, ++{ 4 , 0 , 2 , 305184 , 228888 , 341 }, ++{ 4 , 0 , 3 , 457776 , 305184 , 384 }, ++{ 4 , 0 , 5 , 762960 , 457776 , 427 }, ++{ 4 , 0 , 7 , 1068144 , 610368 , 448 }, ++}; +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400 +@@ -0,0 +1,59 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * ++ * Copyright (C) 2008 Patrick Boettcher ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef CX24120_H ++#define CX24120_H ++ ++#include ++ ++struct firmware; ++struct dvb_frontend; ++struct i2c_adapter; ++ ++struct cx24120_config ++{ ++ u8 i2c_addr; ++ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name); ++ void (*stream_control)(struct dvb_frontend *fe, u8 onoff); ++}; ++ ++#if defined(CONFIG_DVB_CX24120) || \ ++ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c); ++extern int cx24120_reset(struct dvb_frontend *fe); ++#else ++static inline ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++static inline int cx24120_reset(struct dvb_frontend *fe) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return -ENODEV; ++} ++#endif ++ ++#endif +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig +--- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -4,6 +4,13 @@ + comment "Multistandard (satellite) frontends" + depends on DVB_CORE + ++config DVB_CX24120 ++ tristate "Conexant CX24120 based" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend. ++ + config DVB_STB0899 + tristate "STB0899 based" + depends on DVB_CORE && I2C +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile +--- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400 +@@ -19,6 +19,10 @@ + obj-$(CONFIG_DVB_CX22700) += cx22700.o + obj-$(CONFIG_DVB_S5H1432) += s5h1432.o + obj-$(CONFIG_DVB_CX24110) += cx24110.o ++ ++# inserted by Custler ++obj-$(CONFIG_DVB_CX24120) += cx24120.o ++ + obj-$(CONFIG_DVB_TDA8083) += tda8083.o + obj-$(CONFIG_DVB_L64781) += l64781.o + obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o