Hi all, some (longer) time ago, I posted to this list concerning the CX24120-frontend (http://www.spinics.net/lists/linux-media/msg33717.html). By now I modified the patch to work with linux-3.4-r1 (after the DVB-interface changes): [ 2.434181] b2c2-flexcop: B2C2 FlexcopII/II(b)/III digital TV receiver chip loaded successfully [ 2.434240] flexcop-pci: will use the HW PID filter. [ 2.434242] flexcop-pci: card revision 2 [ 2.438105] DVB: registering new adapter (FlexCop Digital TV device) [ 2.440018] b2c2-flexcop: MAC address = 00:08:c9:e0:87:57 [ 2.440024] CX24120: cx24120_attach: -> Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner [ 2.440025] CX24120: cx24120_attach: -> Driver version: 'SVT - 0.0.4a 03.04.2012' [ 2.440149] CX24120: cx24120_attach: -> Demod CX24120 rev. 0x07 detected. [ 2.440150] CX24120: cx24120_attach: -> Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED. [ 2.440440] b2c2-flexcop: ISL6421 successfully attached. [ 2.440440] b2c2-flexcop: found 'Conexant CX24120/CX24118' . [ 2.440442] DVB: registering adapter 0 frontend 0 (Conexant CX24120/CX24118)... [ 2.440648] b2c2-flexcop: initialization of 'Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3' at the 'PCI' bus controlled by a 'FlexCopIIb' complete As stated in the original message, the patch is not written by me, the author is Sergey Tyurin, I just modified it so it keeps working with current kernels. Since I don't know an appropiate location for publishing this, I thought this is best sent upstream. This patch was tested with some channels (SDTV, HDTV and audio only (radio)) from Astra-19.2E in Europe. If you have any comments abouth things that stop the patch from going upstream, please feel free to tell me and I'll see if I can change them. Best regards, Jannis Achstetter
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/dvb/b2c2/flexcop-common.h --- linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/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/dvb/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/dvb/b2c2/flexcop-fe-tuner.c --- linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/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/dvb/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/dvb/b2c2/flexcop-hw-filter.c --- linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/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/dvb/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/dvb/b2c2/flexcop-misc.c --- linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/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/dvb/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/dvb/b2c2/flexcop-reg.h --- linux-3.4-r1/drivers/media/dvb/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/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/dvb/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/dvb/b2c2/Kconfig --- linux-3.4-r1/drivers/media/dvb/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 +++ linux-3.4-r1-S2/drivers/media/dvb/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 @@ -1,6 +1,7 @@ config DVB_B2C2_FLEXCOP tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" depends on DVB_CORE && I2C + select DVB_CX24120 if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE 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 <forum.free-x.de> + Updated 2012 by Jannis Achstetter <jannis_achstetter@xxxxxx> + + 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 <linux/slab.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/firmware.h> +#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 <forum.free-x.de> + * Updated 2012 by Jannis Achstetter <jannis_achstetter@xxxxxx> + * + * 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 <pb@xxxxxxxxxxx> + * Copyright (C) 2009 Sergey Tyurin <forum.free-x.de> + * Updated 2012 by Jannis Achstetter <jannis_achstetter@xxxxxx> + * + * 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 <linux/dvb/frontend.h> + +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 @@ -18,6 +18,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 @@ -20,6 +20,7 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_S5H1432) += s5h1432.o obj-$(CONFIG_DVB_CX24110) += cx24110.o +obj-$(CONFIG_DVB_CX24120) += cx24120.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o