Loading drivers/media/dvb/frontends/cx24116.c +256 −237 Original line number Diff line number Diff line Loading @@ -41,10 +41,14 @@ #include "dvb_frontend.h" #include "cx24116.h" static int debug = 0; static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); #define dprintk(args...) \ do { \ if (debug) printk ("cx24116: " args); \ if (debug) \ printk("cx24116: " args); \ } while (0) #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" Loading Loading @@ -116,12 +120,15 @@ static int debug = 0; /* DiSEqC tone burst */ static int toneburst = 1; module_param(toneburst, int, 0644); MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); /* SNR measurements */ static int esno_snr = 0; static int esno_snr; module_param(esno_snr, int, 0644); MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)"); enum cmds { enum cmds { CMD_SET_VCO = 0x10, CMD_TUNEREQUEST = 0x11, CMD_MPEGCONFIG = 0x13, Loading @@ -138,8 +145,7 @@ enum cmds }; /* The Demod/Tuner can't easily provide these, we cache them */ struct cx24116_tuning { struct cx24116_tuning { u32 frequency; u32 symbol_rate; fe_spectral_inversion_t inversion; Loading @@ -158,14 +164,12 @@ struct cx24116_tuning }; /* Basic commands that are sent to the firmware */ struct cx24116_cmd { struct cx24116_cmd { u8 len; u8 args[CX24116_ARGLEN]; }; struct cx24116_state { struct cx24116_state { struct i2c_adapter *i2c; const struct cx24116_config *config; Loading @@ -190,7 +194,8 @@ static int cx24116_writereg(struct cx24116_state* state, int reg, int data) printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { err = i2c_transfer(state->i2c, &msg, 1); if (err != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x," " value == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; Loading @@ -200,7 +205,8 @@ static int cx24116_writereg(struct cx24116_state* state, int reg, int data) } /* Bulk byte writes to a single I2C address, for 32k firmware load */ static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len) static int cx24116_writeregN(struct cx24116_state *state, int reg, u8 *data, u16 len) { int ret = -EREMOTEIO; struct i2c_msg msg; Loading @@ -225,7 +231,8 @@ static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 printk("cx24116: %s: write regN 0x%02x, len = %d\n", __func__, reg, len); if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x\n", __func__, ret, reg); ret = -EREMOTEIO; Loading @@ -243,8 +250,10 @@ static int cx24116_readreg(struct cx24116_state* state, u8 reg) u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c_transfer(state->i2c, msg, 2); Loading @@ -255,7 +264,8 @@ static int cx24116_readreg(struct cx24116_state* state, u8 reg) } if (debug > 1) printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]); printk("cx24116: read reg 0x%02x, value 0x%02x\n", reg, b1[0]); return b1[0]; } Loading Loading @@ -396,11 +406,9 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state, dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f); for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) { for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) { if ((m == CX24116_MODFEC_MODES[i].modulation) && (f == CX24116_MODFEC_MODES[i].fec) ) { (f == CX24116_MODFEC_MODES[i].fec)) { ret = i; break; } Loading Loading @@ -446,7 +454,8 @@ static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) return 0; } static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); static int cx24116_load_firmware(struct dvb_frontend *fe, const struct firmware *fw); static int cx24116_firmware_ondemand(struct dvb_frontend *fe) { Loading @@ -456,8 +465,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend* fe) dprintk("%s()\n", __func__); if (cx24116_readreg(state, 0x20) > 0) { if (cx24116_readreg(state, 0x20) > 0) { if (state->skip_fw_load) return 0; Loading Loading @@ -499,26 +507,23 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) dprintk("%s()\n", __func__); /* Load the firmware if required */ if ( (ret = cx24116_firmware_ondemand(fe)) != 0) { ret = cx24116_firmware_ondemand(fe); if (ret != 0) { printk("%s(): Unable initialise the firmware\n", __func__); return ret; } /* Write the command */ for(i = 0; i < cmd->len ; i++) { for (i = 0; i < cmd->len ; i++) { dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]); cx24116_writereg(state, i, cmd->args[i]); } /* Start execution and wait for cmd to terminate */ cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01); while( cx24116_readreg(state, CX24116_REG_EXECUTE) ) { while (cx24116_readreg(state, CX24116_REG_EXECUTE)) { msleep(10); if(i++ > 64) { if (i++ > 64) { /* Avoid looping forever if the firmware does no respond */ printk("%s() Firmware not responding\n", __func__); return -EREMOTEIO; Loading @@ -527,7 +532,8 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) return 0; } static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) static int cx24116_load_firmware(struct dvb_frontend *fe, const struct firmware *fw) { struct cx24116_state *state = fe->demodulator_priv; struct cx24116_cmd cmd; Loading @@ -535,13 +541,12 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware unsigned char vers[4]; dprintk("%s\n", __func__); dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" ,fw->size ,fw->data[0] ,fw->data[1] ,fw->data[ fw->size-2 ] ,fw->data[ fw->size-1 ] ); dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", fw->size, fw->data[0], fw->data[1], fw->data[fw->size-2], fw->data[fw->size-1]); /* Toggle 88x SRST pin to reset demod */ if (state->config->reset_device) Loading Loading @@ -636,10 +641,12 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware return 0; } static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) static int cx24116_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { /* The isl6421 module will override this function in the fops. */ dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__); dprintk("%s() This should never appear if the isl6421 module " "is loaded correctly\n", __func__); return -EOPNOTSUPP; } Loading Loading @@ -681,7 +688,8 @@ static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) } /* TODO Determine function and scale appropriately */ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) static int cx24116_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { struct cx24116_state *state = fe->demodulator_priv; struct cx24116_cmd cmd; Loading @@ -697,11 +705,14 @@ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_str if (ret != 0) return ret; sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) | sig_reading = (cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) | (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6); *signal_strength = 0 - sig_reading; dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); return 0; } Loading @@ -714,7 +725,8 @@ static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr) static const u32 snr_tab[] = { /* 10 x Table (rounded up) */ 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667, 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667, 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667, 0x18000 }; dprintk("%s()\n", __func__); Loading Loading @@ -798,7 +810,8 @@ static int cx24116_wait_for_lnb(struct dvb_frontend* fe) return -ETIMEDOUT; /* -EBUSY ? */ } static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) static int cx24116_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) { struct cx24116_cmd cmd; int ret; Loading Loading @@ -890,7 +903,8 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe) } /* Send DiSEqC message with derived burst (hack) || previous burst */ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) { struct cx24116_state *state = fe->demodulator_priv; int i, ret; Loading Loading @@ -918,7 +932,8 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; /* Command length */ state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; state->dsec_cmd.len = CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; /* DiSEqC toneburst */ if (toneburst == CX24116_DISEQC_MESGCACHE) Loading Loading @@ -949,9 +964,11 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma * Z = BAND (0=LOW, 1=HIGH(22K)) */ if (d->msg_len >= 4 && d->msg[2] == 0x38) state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); if (debug) dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); } /* Wait for LNB ready */ Loading @@ -976,13 +993,15 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma * 12.5ms burst + * >15ms delay (XXX determine if FW does this, see set_tone) */ msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) ); msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60)); return 0; } /* Send DiSEqC burst */ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) static int cx24116_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) { struct cx24116_state *state = fe->demodulator_priv; int ret; Loading @@ -991,9 +1010,11 @@ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t /* DiSEqC burst */ if (burst == SEC_MINI_A) state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; else if (burst == SEC_MINI_B) state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; else return -EINVAL; Loading Loading @@ -1077,6 +1098,8 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, error2: kfree(state); error1: return NULL; } EXPORT_SYMBOL(cx24116_attach); /* * Initialise or wake up device * Loading Loading @@ -1133,13 +1156,15 @@ static int cx24116_sleep(struct dvb_frontend* fe) return 0; } static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property *tvp) { dprintk("%s(..)\n", __func__); return 0; } static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp) static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { dprintk("%s(..)\n", __func__); return 0; Loading @@ -1148,7 +1173,8 @@ static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tv /* dvb-core told us to tune, the tv property cache will be complete, * it's safe for is to pull values and use them for tuning purposes. */ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) static int cx24116_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { struct cx24116_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; Loading Loading @@ -1238,14 +1264,17 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par state->dnxt.pilot = c->pilot; state->dnxt.rolloff = c->rolloff; if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) ret = cx24116_set_inversion(state, c->inversion); if (ret != 0) return ret; /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */ if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0) ret = cx24116_set_fec(state, c->modulation, c->fec_inner); if (ret != 0) return ret; if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0) ret = cx24116_set_symbolrate(state, c->symbol_rate); if (ret != 0) return ret; /* discard the 'current' tuning parameters and prepare to tune */ Loading Loading @@ -1327,7 +1356,8 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par */ do { /* Reset status register */ status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; cx24116_writereg(state, CX24116_REG_SSTATUS, status); /* Tune */ Loading Loading @@ -1356,8 +1386,7 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par /* Toggle pilot bit when in auto-pilot */ if (state->dcur.pilot == PILOT_AUTO) cmd.args[0x07] ^= CX24116_PILOT_ON; } while(--retune); } while (--retune); tuned: /* Set/Reset B/W */ cmd.args[0x00] = CMD_BANDWIDTH; Loading Loading @@ -1407,17 +1436,7 @@ static struct dvb_frontend_ops cx24116_ops = { .set_frontend = cx24116_set_frontend, }; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); module_param(toneburst, int, 0644); MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); module_param(esno_snr, int, 0644); MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)"); MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(cx24116_attach); drivers/media/dvb/frontends/cx24116.h +10 −9 Original line number Diff line number Diff line Loading @@ -23,8 +23,7 @@ #include <linux/dvb/frontend.h> struct cx24116_config { struct cx24116_config { /* the demodulator's i2c address */ u8 demod_address; Loading @@ -39,15 +38,17 @@ struct cx24116_config }; #if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, extern struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c); #else static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, static inline struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif // CONFIG_DVB_CX24116 #endif #endif /* CX24116_H */ Loading
drivers/media/dvb/frontends/cx24116.c +256 −237 Original line number Diff line number Diff line Loading @@ -41,10 +41,14 @@ #include "dvb_frontend.h" #include "cx24116.h" static int debug = 0; static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); #define dprintk(args...) \ do { \ if (debug) printk ("cx24116: " args); \ if (debug) \ printk("cx24116: " args); \ } while (0) #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" Loading Loading @@ -116,12 +120,15 @@ static int debug = 0; /* DiSEqC tone burst */ static int toneburst = 1; module_param(toneburst, int, 0644); MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); /* SNR measurements */ static int esno_snr = 0; static int esno_snr; module_param(esno_snr, int, 0644); MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)"); enum cmds { enum cmds { CMD_SET_VCO = 0x10, CMD_TUNEREQUEST = 0x11, CMD_MPEGCONFIG = 0x13, Loading @@ -138,8 +145,7 @@ enum cmds }; /* The Demod/Tuner can't easily provide these, we cache them */ struct cx24116_tuning { struct cx24116_tuning { u32 frequency; u32 symbol_rate; fe_spectral_inversion_t inversion; Loading @@ -158,14 +164,12 @@ struct cx24116_tuning }; /* Basic commands that are sent to the firmware */ struct cx24116_cmd { struct cx24116_cmd { u8 len; u8 args[CX24116_ARGLEN]; }; struct cx24116_state { struct cx24116_state { struct i2c_adapter *i2c; const struct cx24116_config *config; Loading @@ -190,7 +194,8 @@ static int cx24116_writereg(struct cx24116_state* state, int reg, int data) printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { err = i2c_transfer(state->i2c, &msg, 1); if (err != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x," " value == 0x%02x)\n", __func__, err, reg, data); return -EREMOTEIO; Loading @@ -200,7 +205,8 @@ static int cx24116_writereg(struct cx24116_state* state, int reg, int data) } /* Bulk byte writes to a single I2C address, for 32k firmware load */ static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len) static int cx24116_writeregN(struct cx24116_state *state, int reg, u8 *data, u16 len) { int ret = -EREMOTEIO; struct i2c_msg msg; Loading @@ -225,7 +231,8 @@ static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 printk("cx24116: %s: write regN 0x%02x, len = %d\n", __func__, reg, len); if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x\n", __func__, ret, reg); ret = -EREMOTEIO; Loading @@ -243,8 +250,10 @@ static int cx24116_readreg(struct cx24116_state* state, u8 reg) u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c_transfer(state->i2c, msg, 2); Loading @@ -255,7 +264,8 @@ static int cx24116_readreg(struct cx24116_state* state, u8 reg) } if (debug > 1) printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]); printk("cx24116: read reg 0x%02x, value 0x%02x\n", reg, b1[0]); return b1[0]; } Loading Loading @@ -396,11 +406,9 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state, dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f); for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) { for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) { if ((m == CX24116_MODFEC_MODES[i].modulation) && (f == CX24116_MODFEC_MODES[i].fec) ) { (f == CX24116_MODFEC_MODES[i].fec)) { ret = i; break; } Loading Loading @@ -446,7 +454,8 @@ static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) return 0; } static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); static int cx24116_load_firmware(struct dvb_frontend *fe, const struct firmware *fw); static int cx24116_firmware_ondemand(struct dvb_frontend *fe) { Loading @@ -456,8 +465,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend* fe) dprintk("%s()\n", __func__); if (cx24116_readreg(state, 0x20) > 0) { if (cx24116_readreg(state, 0x20) > 0) { if (state->skip_fw_load) return 0; Loading Loading @@ -499,26 +507,23 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) dprintk("%s()\n", __func__); /* Load the firmware if required */ if ( (ret = cx24116_firmware_ondemand(fe)) != 0) { ret = cx24116_firmware_ondemand(fe); if (ret != 0) { printk("%s(): Unable initialise the firmware\n", __func__); return ret; } /* Write the command */ for(i = 0; i < cmd->len ; i++) { for (i = 0; i < cmd->len ; i++) { dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]); cx24116_writereg(state, i, cmd->args[i]); } /* Start execution and wait for cmd to terminate */ cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01); while( cx24116_readreg(state, CX24116_REG_EXECUTE) ) { while (cx24116_readreg(state, CX24116_REG_EXECUTE)) { msleep(10); if(i++ > 64) { if (i++ > 64) { /* Avoid looping forever if the firmware does no respond */ printk("%s() Firmware not responding\n", __func__); return -EREMOTEIO; Loading @@ -527,7 +532,8 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) return 0; } static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) static int cx24116_load_firmware(struct dvb_frontend *fe, const struct firmware *fw) { struct cx24116_state *state = fe->demodulator_priv; struct cx24116_cmd cmd; Loading @@ -535,13 +541,12 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware unsigned char vers[4]; dprintk("%s\n", __func__); dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" ,fw->size ,fw->data[0] ,fw->data[1] ,fw->data[ fw->size-2 ] ,fw->data[ fw->size-1 ] ); dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", fw->size, fw->data[0], fw->data[1], fw->data[fw->size-2], fw->data[fw->size-1]); /* Toggle 88x SRST pin to reset demod */ if (state->config->reset_device) Loading Loading @@ -636,10 +641,12 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware return 0; } static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) static int cx24116_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { /* The isl6421 module will override this function in the fops. */ dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__); dprintk("%s() This should never appear if the isl6421 module " "is loaded correctly\n", __func__); return -EOPNOTSUPP; } Loading Loading @@ -681,7 +688,8 @@ static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) } /* TODO Determine function and scale appropriately */ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) static int cx24116_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { struct cx24116_state *state = fe->demodulator_priv; struct cx24116_cmd cmd; Loading @@ -697,11 +705,14 @@ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_str if (ret != 0) return ret; sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) | sig_reading = (cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) | (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6); *signal_strength = 0 - sig_reading; dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); return 0; } Loading @@ -714,7 +725,8 @@ static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr) static const u32 snr_tab[] = { /* 10 x Table (rounded up) */ 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667, 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667, 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667, 0x18000 }; dprintk("%s()\n", __func__); Loading Loading @@ -798,7 +810,8 @@ static int cx24116_wait_for_lnb(struct dvb_frontend* fe) return -ETIMEDOUT; /* -EBUSY ? */ } static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) static int cx24116_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) { struct cx24116_cmd cmd; int ret; Loading Loading @@ -890,7 +903,8 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe) } /* Send DiSEqC message with derived burst (hack) || previous burst */ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) { struct cx24116_state *state = fe->demodulator_priv; int i, ret; Loading Loading @@ -918,7 +932,8 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; /* Command length */ state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; state->dsec_cmd.len = CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; /* DiSEqC toneburst */ if (toneburst == CX24116_DISEQC_MESGCACHE) Loading Loading @@ -949,9 +964,11 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma * Z = BAND (0=LOW, 1=HIGH(22K)) */ if (d->msg_len >= 4 && d->msg[2] == 0x38) state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); if (debug) dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); } /* Wait for LNB ready */ Loading @@ -976,13 +993,15 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma * 12.5ms burst + * >15ms delay (XXX determine if FW does this, see set_tone) */ msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) ); msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60)); return 0; } /* Send DiSEqC burst */ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) static int cx24116_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) { struct cx24116_state *state = fe->demodulator_priv; int ret; Loading @@ -991,9 +1010,11 @@ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t /* DiSEqC burst */ if (burst == SEC_MINI_A) state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; else if (burst == SEC_MINI_B) state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; else return -EINVAL; Loading Loading @@ -1077,6 +1098,8 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, error2: kfree(state); error1: return NULL; } EXPORT_SYMBOL(cx24116_attach); /* * Initialise or wake up device * Loading Loading @@ -1133,13 +1156,15 @@ static int cx24116_sleep(struct dvb_frontend* fe) return 0; } static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property *tvp) { dprintk("%s(..)\n", __func__); return 0; } static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp) static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { dprintk("%s(..)\n", __func__); return 0; Loading @@ -1148,7 +1173,8 @@ static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tv /* dvb-core told us to tune, the tv property cache will be complete, * it's safe for is to pull values and use them for tuning purposes. */ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) static int cx24116_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { struct cx24116_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; Loading Loading @@ -1238,14 +1264,17 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par state->dnxt.pilot = c->pilot; state->dnxt.rolloff = c->rolloff; if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) ret = cx24116_set_inversion(state, c->inversion); if (ret != 0) return ret; /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */ if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0) ret = cx24116_set_fec(state, c->modulation, c->fec_inner); if (ret != 0) return ret; if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0) ret = cx24116_set_symbolrate(state, c->symbol_rate); if (ret != 0) return ret; /* discard the 'current' tuning parameters and prepare to tune */ Loading Loading @@ -1327,7 +1356,8 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par */ do { /* Reset status register */ status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; cx24116_writereg(state, CX24116_REG_SSTATUS, status); /* Tune */ Loading Loading @@ -1356,8 +1386,7 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par /* Toggle pilot bit when in auto-pilot */ if (state->dcur.pilot == PILOT_AUTO) cmd.args[0x07] ^= CX24116_PILOT_ON; } while(--retune); } while (--retune); tuned: /* Set/Reset B/W */ cmd.args[0x00] = CMD_BANDWIDTH; Loading Loading @@ -1407,17 +1436,7 @@ static struct dvb_frontend_ops cx24116_ops = { .set_frontend = cx24116_set_frontend, }; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); module_param(toneburst, int, 0644); MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); module_param(esno_snr, int, 0644); MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)"); MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(cx24116_attach);
drivers/media/dvb/frontends/cx24116.h +10 −9 Original line number Diff line number Diff line Loading @@ -23,8 +23,7 @@ #include <linux/dvb/frontend.h> struct cx24116_config { struct cx24116_config { /* the demodulator's i2c address */ u8 demod_address; Loading @@ -39,15 +38,17 @@ struct cx24116_config }; #if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, extern struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c); #else static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, static inline struct dvb_frontend *cx24116_attach( const struct cx24116_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif // CONFIG_DVB_CX24116 #endif #endif /* CX24116_H */