Lines Matching +full:max +full:- +full:burst +full:- +full:len

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
5 Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
6 Copyright (C) 2006-2007 Georg Acher
7 Copyright (C) 2007-2008 Darron Broad
45 #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
74 /* Select DVB-S demodulator, else DVB-S2 */
115 /* DiSEqC burst */
119 /* DiSEqC tone burst */
128 MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
169 u8 len; member
183 u8 burst; member
190 struct i2c_msg msg = { .addr = state->config->demod_address, in cx24116_writereg()
191 .flags = 0, .buf = buf, .len = 2 }; in cx24116_writereg()
198 err = i2c_transfer(state->i2c, &msg, 1); in cx24116_writereg()
202 return -EREMOTEIO; in cx24116_writereg()
210 const u8 *data, u16 len) in cx24116_writeregN() argument
216 buf = kmalloc(len + 1, GFP_KERNEL); in cx24116_writeregN()
218 return -ENOMEM; in cx24116_writeregN()
221 memcpy(buf + 1, data, len); in cx24116_writeregN()
223 msg.addr = state->config->demod_address; in cx24116_writeregN()
226 msg.len = len + 1; in cx24116_writeregN()
229 printk(KERN_INFO "cx24116: %s: write regN 0x%02x, len = %d\n", in cx24116_writeregN()
230 __func__, reg, len); in cx24116_writeregN()
232 ret = i2c_transfer(state->i2c, &msg, 1); in cx24116_writeregN()
236 ret = -EREMOTEIO; in cx24116_writeregN()
250 { .addr = state->config->demod_address, .flags = 0, in cx24116_readreg()
251 .buf = b0, .len = 1 }, in cx24116_readreg()
252 { .addr = state->config->demod_address, .flags = I2C_M_RD, in cx24116_readreg()
253 .buf = b1, .len = 1 } in cx24116_readreg()
256 ret = i2c_transfer(state->i2c, msg, 2); in cx24116_readreg()
278 state->dnxt.inversion_val = 0x00; in cx24116_set_inversion()
281 state->dnxt.inversion_val = 0x04; in cx24116_set_inversion()
284 state->dnxt.inversion_val = 0x0C; in cx24116_set_inversion()
287 return -EINVAL; in cx24116_set_inversion()
290 state->dnxt.inversion = inversion; in cx24116_set_inversion()
300 * ---- -------- ----------- --------
301 * QPSK FEC_1_2 0x02 0x02+X DVB-S
302 * QPSK FEC_2_3 0x04 0x02+X DVB-S
303 * QPSK FEC_3_4 0x08 0x02+X DVB-S
304 * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
305 * QPSK FEC_5_6 0x20 0x02+X DVB-S
306 * QPSK FEC_6_7 0x40 0x02+X DVB-S
307 * QPSK FEC_7_8 0x80 0x02+X DVB-S
308 * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
309 * QPSK AUTO 0xff 0x02+X DVB-S
311 * For DVB-S high byte probably represents FEC
314 * on DVB-S and remaining bits represent some
328 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
330 * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
331 * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
332 * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
333 * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
334 * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
335 * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
336 * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
337 * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
339 * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
340 * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
341 * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
342 * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
343 * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
344 * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
346 * For DVB-S2 low bytes selects both modulator
379 /* NBC-QPSK */
404 int i, ret = -EOPNOTSUPP; in cx24116_lookup_fecmod()
434 state->dnxt.fec = fec; in cx24116_set_fec()
435 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val; in cx24116_set_fec()
436 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask; in cx24116_set_fec()
438 state->dnxt.fec_mask, state->dnxt.fec_val); in cx24116_set_fec()
448 if ((rate > state->frontend.ops.info.symbol_rate_max) || in cx24116_set_symbolrate()
449 (rate < state->frontend.ops.info.symbol_rate_min)) { in cx24116_set_symbolrate()
451 return -EOPNOTSUPP; in cx24116_set_symbolrate()
454 state->dnxt.symbol_rate = rate; in cx24116_set_symbolrate()
465 struct cx24116_state *state = fe->demodulator_priv; in cx24116_firmware_ondemand()
473 if (state->skip_fw_load) in cx24116_firmware_ondemand()
481 state->i2c->dev.parent); in cx24116_firmware_ondemand()
492 state->skip_fw_load = 1; in cx24116_firmware_ondemand()
505 state->skip_fw_load = 0; in cx24116_firmware_ondemand()
516 struct cx24116_state *state = fe->demodulator_priv; in cx24116_cmd_execute()
530 for (i = 0; i < cmd->len ; i++) { in cx24116_cmd_execute()
531 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]); in cx24116_cmd_execute()
532 cx24116_writereg(state, i, cmd->args[i]); in cx24116_cmd_execute()
544 return -EREMOTEIO; in cx24116_cmd_execute()
553 struct cx24116_state *state = fe->demodulator_priv; in cx24116_load_firmware()
555 int i, ret, len, max, remaining; in cx24116_load_firmware() local
560 fw->size, in cx24116_load_firmware()
561 fw->data[0], in cx24116_load_firmware()
562 fw->data[1], in cx24116_load_firmware()
563 fw->data[fw->size-2], in cx24116_load_firmware()
564 fw->data[fw->size-1]); in cx24116_load_firmware()
567 if (state->config->reset_device) in cx24116_load_firmware()
568 state->config->reset_device(fe); in cx24116_load_firmware()
592 /* Split firmware to the max I2C write len and write. in cx24116_load_firmware()
594 if (state->config->i2c_wr_max) in cx24116_load_firmware()
595 max = state->config->i2c_wr_max; in cx24116_load_firmware()
597 max = INT_MAX; /* enough for 32k firmware */ in cx24116_load_firmware()
599 for (remaining = fw->size; remaining > 0; remaining -= max - 1) { in cx24116_load_firmware()
600 len = remaining; in cx24116_load_firmware()
601 if (len > max - 1) in cx24116_load_firmware()
602 len = max - 1; in cx24116_load_firmware()
604 cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining], in cx24116_load_firmware()
605 len); in cx24116_load_firmware()
623 cmd.len = 0x0a; in cx24116_load_firmware()
634 cmd.len = 0x03; in cx24116_load_firmware()
646 if (state->config->mpg_clk_pos_pol) in cx24116_load_firmware()
647 cmd.args[0x04] = state->config->mpg_clk_pos_pol; in cx24116_load_firmware()
651 cmd.len = 0x06; in cx24116_load_firmware()
658 cmd.len = 0x02; in cx24116_load_firmware()
674 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_status()
697 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_ber()
713 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_signal_strength()
722 cmd.len = 0x01; in cx24116_read_signal_strength()
731 *signal_strength = 0 - sig_reading; in cx24116_read_signal_strength()
742 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_snr_pct()
772 * ESNO, from 0->30db (values 0->300). We provide this value by
777 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_snr_esno()
799 struct cx24116_state *state = fe->demodulator_priv; in cx24116_read_ucblocks()
812 struct cx24116_state *state = fe->demodulator_priv; in cx24116_clone_params()
813 state->dcur = state->dnxt; in cx24116_clone_params()
819 struct cx24116_state *state = fe->demodulator_priv; in cx24116_wait_for_lnb()
834 return -ETIMEDOUT; /* -EBUSY ? */ in cx24116_wait_for_lnb()
857 cmd.len = 0x02; in cx24116_set_voltage()
874 return -EINVAL; in cx24116_set_tone()
883 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ in cx24116_set_tone()
900 cmd.len = 0x04; in cx24116_set_tone()
903 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ in cx24116_set_tone()
911 struct cx24116_state *state = fe->demodulator_priv; in cx24116_diseqc_init()
924 cmd.len = 0x08; in cx24116_diseqc_init()
930 state->dsec_cmd.args[0x00] = CMD_LNBSEND; in cx24116_diseqc_init()
932 /* DiSEqC burst */ in cx24116_diseqc_init()
933 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; in cx24116_diseqc_init()
936 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; in cx24116_diseqc_init()
937 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; in cx24116_diseqc_init()
939 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; in cx24116_diseqc_init()
942 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; in cx24116_diseqc_init()
945 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS; in cx24116_diseqc_init()
950 /* Send DiSEqC message with derived burst (hack) || previous burst */
954 struct cx24116_state *state = fe->demodulator_priv; in cx24116_send_diseqc_msg()
958 if (d->msg_len > sizeof(d->msg)) in cx24116_send_diseqc_msg()
959 return -EINVAL; in cx24116_send_diseqc_msg()
964 for (i = 0 ; i < d->msg_len ;) { in cx24116_send_diseqc_msg()
965 printk(KERN_INFO "0x%02x", d->msg[i]); in cx24116_send_diseqc_msg()
966 if (++i < d->msg_len) in cx24116_send_diseqc_msg()
973 for (i = 0; i < d->msg_len; i++) in cx24116_send_diseqc_msg()
974 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; in cx24116_send_diseqc_msg()
977 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; in cx24116_send_diseqc_msg()
980 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS + in cx24116_send_diseqc_msg()
981 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; in cx24116_send_diseqc_msg()
989 /* Message is sent without burst */ in cx24116_send_diseqc_msg()
990 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0; in cx24116_send_diseqc_msg()
994 * Message is sent with derived else cached burst in cx24116_send_diseqc_msg()
1011 if (d->msg_len >= 4 && d->msg[2] == 0x38) in cx24116_send_diseqc_msg()
1012 state->dsec_cmd.args[CX24116_DISEQC_BURST] = in cx24116_send_diseqc_msg()
1013 ((d->msg[3] & 4) >> 2); in cx24116_send_diseqc_msg()
1015 dprintk("%s burst=%d\n", __func__, in cx24116_send_diseqc_msg()
1016 state->dsec_cmd.args[CX24116_DISEQC_BURST]); in cx24116_send_diseqc_msg()
1028 ret = cx24116_cmd_execute(fe, &state->dsec_cmd); in cx24116_send_diseqc_msg()
1038 * 12.5ms burst + in cx24116_send_diseqc_msg()
1041 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + in cx24116_send_diseqc_msg()
1047 /* Send DiSEqC burst */
1049 enum fe_sec_mini_cmd burst) in cx24116_diseqc_send_burst() argument
1051 struct cx24116_state *state = fe->demodulator_priv; in cx24116_diseqc_send_burst()
1054 dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst); in cx24116_diseqc_send_burst()
1056 /* DiSEqC burst */ in cx24116_diseqc_send_burst()
1057 if (burst == SEC_MINI_A) in cx24116_diseqc_send_burst()
1058 state->dsec_cmd.args[CX24116_DISEQC_BURST] = in cx24116_diseqc_send_burst()
1060 else if (burst == SEC_MINI_B) in cx24116_diseqc_send_burst()
1061 state->dsec_cmd.args[CX24116_DISEQC_BURST] = in cx24116_diseqc_send_burst()
1064 return -EINVAL; in cx24116_diseqc_send_burst()
1068 /* Burst is cached */ in cx24116_diseqc_send_burst()
1071 /* Burst is to be sent with cached message */ in cx24116_diseqc_send_burst()
1082 ret = cx24116_cmd_execute(fe, &state->dsec_cmd); in cx24116_diseqc_send_burst()
1093 * 12.5ms burst + in cx24116_diseqc_send_burst()
1096 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60); in cx24116_diseqc_send_burst()
1103 struct cx24116_state *state = fe->demodulator_priv; in cx24116_release()
1123 state->config = config; in cx24116_attach()
1124 state->i2c = i2c; in cx24116_attach()
1136 memcpy(&state->frontend.ops, &cx24116_ops, in cx24116_attach()
1138 state->frontend.demodulator_priv = state; in cx24116_attach()
1139 return &state->frontend; in cx24116_attach()
1150 struct cx24116_state *state = fe->demodulator_priv; in cx24116_initfe()
1164 cmd.len = 0x02; in cx24116_initfe()
1173 /* HVR-4000 needs this */ in cx24116_initfe()
1182 struct cx24116_state *state = fe->demodulator_priv; in cx24116_sleep()
1191 cmd.len = 0x02; in cx24116_sleep()
1204 /* dvb-core told us to tune, the tv property cache will be complete,
1209 struct cx24116_state *state = fe->demodulator_priv; in cx24116_set_frontend()
1210 struct dtv_frontend_properties *c = &fe->dtv_property_cache; in cx24116_set_frontend()
1217 switch (c->delivery_system) { in cx24116_set_frontend()
1219 dprintk("%s: DVB-S delivery system selected\n", __func__); in cx24116_set_frontend()
1221 /* Only QPSK is supported for DVB-S */ in cx24116_set_frontend()
1222 if (c->modulation != QPSK) { in cx24116_set_frontend()
1224 __func__, c->modulation); in cx24116_set_frontend()
1225 return -EOPNOTSUPP; in cx24116_set_frontend()
1228 /* Pilot doesn't exist in DVB-S, turn bit off */ in cx24116_set_frontend()
1229 state->dnxt.pilot_val = CX24116_PILOT_OFF; in cx24116_set_frontend()
1231 /* DVB-S only supports 0.35 */ in cx24116_set_frontend()
1232 if (c->rolloff != ROLLOFF_35) { in cx24116_set_frontend()
1234 __func__, c->rolloff); in cx24116_set_frontend()
1235 return -EOPNOTSUPP; in cx24116_set_frontend()
1237 state->dnxt.rolloff_val = CX24116_ROLLOFF_035; in cx24116_set_frontend()
1241 dprintk("%s: DVB-S2 delivery system selected\n", __func__); in cx24116_set_frontend()
1244 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2, in cx24116_set_frontend()
1247 if (c->modulation != PSK_8 && c->modulation != QPSK) { in cx24116_set_frontend()
1249 __func__, c->modulation); in cx24116_set_frontend()
1250 return -EOPNOTSUPP; in cx24116_set_frontend()
1253 switch (c->pilot) { in cx24116_set_frontend()
1255 state->dnxt.pilot_val = (c->modulation == QPSK) in cx24116_set_frontend()
1260 state->dnxt.pilot_val = CX24116_PILOT_OFF; in cx24116_set_frontend()
1263 state->dnxt.pilot_val = CX24116_PILOT_ON; in cx24116_set_frontend()
1267 __func__, c->pilot); in cx24116_set_frontend()
1268 return -EOPNOTSUPP; in cx24116_set_frontend()
1271 switch (c->rolloff) { in cx24116_set_frontend()
1273 state->dnxt.rolloff_val = CX24116_ROLLOFF_020; in cx24116_set_frontend()
1276 state->dnxt.rolloff_val = CX24116_ROLLOFF_025; in cx24116_set_frontend()
1279 state->dnxt.rolloff_val = CX24116_ROLLOFF_035; in cx24116_set_frontend()
1284 __func__, c->rolloff); in cx24116_set_frontend()
1285 return -EOPNOTSUPP; in cx24116_set_frontend()
1291 __func__, c->delivery_system); in cx24116_set_frontend()
1292 return -EOPNOTSUPP; in cx24116_set_frontend()
1294 state->dnxt.delsys = c->delivery_system; in cx24116_set_frontend()
1295 state->dnxt.modulation = c->modulation; in cx24116_set_frontend()
1296 state->dnxt.frequency = c->frequency; in cx24116_set_frontend()
1297 state->dnxt.pilot = c->pilot; in cx24116_set_frontend()
1298 state->dnxt.rolloff = c->rolloff; in cx24116_set_frontend()
1300 ret = cx24116_set_inversion(state, c->inversion); in cx24116_set_frontend()
1304 /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */ in cx24116_set_frontend()
1305 ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner); in cx24116_set_frontend()
1309 ret = cx24116_set_symbolrate(state, c->symbol_rate); in cx24116_set_frontend()
1316 dprintk("%s: delsys = %d\n", __func__, state->dcur.delsys); in cx24116_set_frontend()
1317 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation); in cx24116_set_frontend()
1318 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); in cx24116_set_frontend()
1320 state->dcur.pilot, state->dcur.pilot_val); in cx24116_set_frontend()
1323 state->dcur.rolloff, state->dcur.rolloff_val); in cx24116_set_frontend()
1324 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); in cx24116_set_frontend()
1326 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val); in cx24116_set_frontend()
1328 state->dcur.inversion, state->dcur.inversion_val); in cx24116_set_frontend()
1331 if (state->config->set_ts_params) in cx24116_set_frontend()
1332 state->config->set_ts_params(fe, 0); in cx24116_set_frontend()
1337 cmd.len = 0x02; in cx24116_set_frontend()
1346 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16; in cx24116_set_frontend()
1347 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8; in cx24116_set_frontend()
1348 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff); in cx24116_set_frontend()
1351 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8; in cx24116_set_frontend()
1352 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff); in cx24116_set_frontend()
1355 cmd.args[0x06] = state->dcur.inversion_val; in cx24116_set_frontend()
1358 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val; in cx24116_set_frontend()
1364 cmd.args[0x0c] = state->dcur.rolloff_val; in cx24116_set_frontend()
1365 cmd.args[0x0d] = state->dcur.fec_mask; in cx24116_set_frontend()
1367 if (state->dcur.symbol_rate > 30000000) { in cx24116_set_frontend()
1385 cmd.len = 0x13; in cx24116_set_frontend()
1387 /* We need to support pilot and non-pilot tuning in the in cx24116_set_frontend()
1420 /* Toggle pilot bit when in auto-pilot */ in cx24116_set_frontend()
1421 if (state->dcur.pilot == PILOT_AUTO) in cx24116_set_frontend()
1423 } while (--retune); in cx24116_set_frontend()
1428 cmd.len = 0x02; in cx24116_set_frontend()
1437 * fe->dtv_property_cache with fepriv->parameters_in, where the in cx24116_tune()
1439 * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is in cx24116_tune()