diff options
Diffstat (limited to 'drivers/media/dvb/frontends/ds3000.c')
-rw-r--r-- | drivers/media/dvb/frontends/ds3000.c | 645 |
1 files changed, 304 insertions, 341 deletions
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c index fc61d9230db..90bf573308b 100644 --- a/drivers/media/dvb/frontends/ds3000.c +++ b/drivers/media/dvb/frontends/ds3000.c | |||
@@ -229,31 +229,11 @@ static u8 ds3000_dvbs2_init_tab[] = { | |||
229 | 0xb8, 0x00, | 229 | 0xb8, 0x00, |
230 | }; | 230 | }; |
231 | 231 | ||
232 | /* DS3000 doesn't need some parameters as input and auto-detects them */ | ||
233 | /* save input from the application of those parameters */ | ||
234 | struct ds3000_tuning { | ||
235 | u32 frequency; | ||
236 | u32 symbol_rate; | ||
237 | fe_spectral_inversion_t inversion; | ||
238 | enum fe_code_rate fec; | ||
239 | |||
240 | /* input values */ | ||
241 | u8 inversion_val; | ||
242 | fe_modulation_t delivery; | ||
243 | u8 rolloff; | ||
244 | }; | ||
245 | |||
246 | struct ds3000_state { | 232 | struct ds3000_state { |
247 | struct i2c_adapter *i2c; | 233 | struct i2c_adapter *i2c; |
248 | const struct ds3000_config *config; | 234 | const struct ds3000_config *config; |
249 | |||
250 | struct dvb_frontend frontend; | 235 | struct dvb_frontend frontend; |
251 | |||
252 | struct ds3000_tuning dcur; | ||
253 | struct ds3000_tuning dnxt; | ||
254 | |||
255 | u8 skip_fw_load; | 236 | u8 skip_fw_load; |
256 | |||
257 | /* previous uncorrected block counter for DVB-S2 */ | 237 | /* previous uncorrected block counter for DVB-S2 */ |
258 | u16 prevUCBS2; | 238 | u16 prevUCBS2; |
259 | }; | 239 | }; |
@@ -305,7 +285,7 @@ static int ds3000_writeFW(struct ds3000_state *state, int reg, | |||
305 | struct i2c_msg msg; | 285 | struct i2c_msg msg; |
306 | u8 *buf; | 286 | u8 *buf; |
307 | 287 | ||
308 | buf = kmalloc(3, GFP_KERNEL); | 288 | buf = kmalloc(33, GFP_KERNEL); |
309 | if (buf == NULL) { | 289 | if (buf == NULL) { |
310 | printk(KERN_ERR "Unable to kmalloc\n"); | 290 | printk(KERN_ERR "Unable to kmalloc\n"); |
311 | ret = -ENOMEM; | 291 | ret = -ENOMEM; |
@@ -317,10 +297,10 @@ static int ds3000_writeFW(struct ds3000_state *state, int reg, | |||
317 | msg.addr = state->config->demod_address; | 297 | msg.addr = state->config->demod_address; |
318 | msg.flags = 0; | 298 | msg.flags = 0; |
319 | msg.buf = buf; | 299 | msg.buf = buf; |
320 | msg.len = 3; | 300 | msg.len = 33; |
321 | 301 | ||
322 | for (i = 0; i < len; i += 2) { | 302 | for (i = 0; i < len; i += 32) { |
323 | memcpy(buf + 1, data + i, 2); | 303 | memcpy(buf + 1, data + i, 32); |
324 | 304 | ||
325 | dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len); | 305 | dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len); |
326 | 306 | ||
@@ -401,45 +381,6 @@ static int ds3000_tuner_readreg(struct ds3000_state *state, u8 reg) | |||
401 | return b1[0]; | 381 | return b1[0]; |
402 | } | 382 | } |
403 | 383 | ||
404 | static int ds3000_set_inversion(struct ds3000_state *state, | ||
405 | fe_spectral_inversion_t inversion) | ||
406 | { | ||
407 | dprintk("%s(%d)\n", __func__, inversion); | ||
408 | |||
409 | switch (inversion) { | ||
410 | case INVERSION_OFF: | ||
411 | case INVERSION_ON: | ||
412 | case INVERSION_AUTO: | ||
413 | break; | ||
414 | default: | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | |||
418 | state->dnxt.inversion = inversion; | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int ds3000_set_symbolrate(struct ds3000_state *state, u32 rate) | ||
424 | { | ||
425 | int ret = 0; | ||
426 | |||
427 | dprintk("%s()\n", __func__); | ||
428 | |||
429 | dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate); | ||
430 | |||
431 | /* check if symbol rate is within limits */ | ||
432 | if ((state->dnxt.symbol_rate > | ||
433 | state->frontend.ops.info.symbol_rate_max) || | ||
434 | (state->dnxt.symbol_rate < | ||
435 | state->frontend.ops.info.symbol_rate_min)) | ||
436 | ret = -EOPNOTSUPP; | ||
437 | |||
438 | state->dnxt.symbol_rate = rate; | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static int ds3000_load_firmware(struct dvb_frontend *fe, | 384 | static int ds3000_load_firmware(struct dvb_frontend *fe, |
444 | const struct firmware *fw); | 385 | const struct firmware *fw); |
445 | 386 | ||
@@ -509,23 +450,31 @@ static int ds3000_load_firmware(struct dvb_frontend *fe, | |||
509 | return 0; | 450 | return 0; |
510 | } | 451 | } |
511 | 452 | ||
512 | static void ds3000_dump_registers(struct dvb_frontend *fe) | 453 | static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
513 | { | 454 | { |
514 | struct ds3000_state *state = fe->demodulator_priv; | 455 | struct ds3000_state *state = fe->demodulator_priv; |
515 | int x, y, reg = 0, val; | 456 | u8 data; |
516 | 457 | ||
517 | for (y = 0; y < 16; y++) { | 458 | dprintk("%s(%d)\n", __func__, voltage); |
518 | dprintk("%s: %02x: ", __func__, y); | 459 | |
519 | for (x = 0; x < 16; x++) { | 460 | data = ds3000_readreg(state, 0xa2); |
520 | reg = (y << 4) + x; | 461 | data |= 0x03; /* bit0 V/H, bit1 off/on */ |
521 | val = ds3000_readreg(state, reg); | 462 | |
522 | if (x != 15) | 463 | switch (voltage) { |
523 | dprintk("%02x ", val); | 464 | case SEC_VOLTAGE_18: |
524 | else | 465 | data &= ~0x03; |
525 | dprintk("%02x\n", val); | 466 | break; |
526 | } | 467 | case SEC_VOLTAGE_13: |
468 | data &= ~0x03; | ||
469 | data |= 0x01; | ||
470 | break; | ||
471 | case SEC_VOLTAGE_OFF: | ||
472 | break; | ||
527 | } | 473 | } |
528 | dprintk("%s: -- DS3000 DUMP DONE --\n", __func__); | 474 | |
475 | ds3000_writereg(state, 0xa2, data); | ||
476 | |||
477 | return 0; | ||
529 | } | 478 | } |
530 | 479 | ||
531 | static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status) | 480 | static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status) |
@@ -562,16 +511,6 @@ static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status) | |||
562 | return 0; | 511 | return 0; |
563 | } | 512 | } |
564 | 513 | ||
565 | #define FE_IS_TUNED (FE_HAS_SIGNAL + FE_HAS_LOCK) | ||
566 | static int ds3000_is_tuned(struct dvb_frontend *fe) | ||
567 | { | ||
568 | fe_status_t tunerstat; | ||
569 | |||
570 | ds3000_read_status(fe, &tunerstat); | ||
571 | |||
572 | return ((tunerstat & FE_IS_TUNED) == FE_IS_TUNED); | ||
573 | } | ||
574 | |||
575 | /* read DS3000 BER value */ | 514 | /* read DS3000 BER value */ |
576 | static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber) | 515 | static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber) |
577 | { | 516 | { |
@@ -792,13 +731,6 @@ static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | |||
792 | return 0; | 731 | return 0; |
793 | } | 732 | } |
794 | 733 | ||
795 | /* Overwrite the current tuning params, we are about to tune */ | ||
796 | static void ds3000_clone_params(struct dvb_frontend *fe) | ||
797 | { | ||
798 | struct ds3000_state *state = fe->demodulator_priv; | ||
799 | memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); | ||
800 | } | ||
801 | |||
802 | static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | 734 | static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) |
803 | { | 735 | { |
804 | struct ds3000_state *state = fe->demodulator_priv; | 736 | struct ds3000_state *state = fe->demodulator_priv; |
@@ -1016,287 +948,298 @@ static int ds3000_get_property(struct dvb_frontend *fe, | |||
1016 | return 0; | 948 | return 0; |
1017 | } | 949 | } |
1018 | 950 | ||
1019 | static int ds3000_tune(struct dvb_frontend *fe, | 951 | static int ds3000_set_carrier_offset(struct dvb_frontend *fe, |
952 | s32 carrier_offset_khz) | ||
953 | { | ||
954 | struct ds3000_state *state = fe->demodulator_priv; | ||
955 | s32 tmp; | ||
956 | |||
957 | tmp = carrier_offset_khz; | ||
958 | tmp *= 65536; | ||
959 | tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE); | ||
960 | |||
961 | if (tmp < 0) | ||
962 | tmp += 65536; | ||
963 | |||
964 | ds3000_writereg(state, 0x5f, tmp >> 8); | ||
965 | ds3000_writereg(state, 0x5e, tmp & 0xff); | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | static int ds3000_set_frontend(struct dvb_frontend *fe, | ||
1020 | struct dvb_frontend_parameters *p) | 971 | struct dvb_frontend_parameters *p) |
1021 | { | 972 | { |
1022 | struct ds3000_state *state = fe->demodulator_priv; | 973 | struct ds3000_state *state = fe->demodulator_priv; |
1023 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 974 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1024 | 975 | ||
1025 | int ret = 0, retune, i; | 976 | int i; |
1026 | u8 status, mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf; | 977 | fe_status_t status; |
978 | u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf, div4; | ||
979 | s32 offset_khz; | ||
1027 | u16 value, ndiv; | 980 | u16 value, ndiv; |
1028 | u32 f3db; | 981 | u32 f3db; |
1029 | 982 | ||
1030 | dprintk("%s() ", __func__); | 983 | dprintk("%s() ", __func__); |
1031 | 984 | ||
1032 | /* Load the firmware if required */ | 985 | if (state->config->set_ts_params) |
1033 | ret = ds3000_firmware_ondemand(fe); | 986 | state->config->set_ts_params(fe, 0); |
1034 | if (ret != 0) { | 987 | /* Tune */ |
1035 | printk(KERN_ERR "%s: Unable initialise the firmware\n", | 988 | /* unknown */ |
1036 | __func__); | 989 | ds3000_tuner_writereg(state, 0x07, 0x02); |
1037 | return ret; | 990 | ds3000_tuner_writereg(state, 0x10, 0x00); |
991 | ds3000_tuner_writereg(state, 0x60, 0x79); | ||
992 | ds3000_tuner_writereg(state, 0x08, 0x01); | ||
993 | ds3000_tuner_writereg(state, 0x00, 0x01); | ||
994 | div4 = 0; | ||
995 | |||
996 | /* calculate and set freq divider */ | ||
997 | if (p->frequency < 1146000) { | ||
998 | ds3000_tuner_writereg(state, 0x10, 0x11); | ||
999 | div4 = 1; | ||
1000 | ndiv = ((p->frequency * (6 + 8) * 4) + | ||
1001 | (DS3000_XTAL_FREQ / 2)) / | ||
1002 | DS3000_XTAL_FREQ - 1024; | ||
1003 | } else { | ||
1004 | ds3000_tuner_writereg(state, 0x10, 0x01); | ||
1005 | ndiv = ((p->frequency * (6 + 8) * 2) + | ||
1006 | (DS3000_XTAL_FREQ / 2)) / | ||
1007 | DS3000_XTAL_FREQ - 1024; | ||
1038 | } | 1008 | } |
1039 | 1009 | ||
1040 | state->dnxt.delivery = c->modulation; | 1010 | ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8); |
1041 | state->dnxt.frequency = c->frequency; | 1011 | ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff); |
1042 | state->dnxt.rolloff = 2; /* fixme */ | 1012 | |
1043 | state->dnxt.fec = c->fec_inner; | 1013 | /* set pll */ |
1014 | ds3000_tuner_writereg(state, 0x03, 0x06); | ||
1015 | ds3000_tuner_writereg(state, 0x51, 0x0f); | ||
1016 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1017 | ds3000_tuner_writereg(state, 0x50, 0x10); | ||
1018 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1019 | msleep(5); | ||
1020 | |||
1021 | /* unknown */ | ||
1022 | ds3000_tuner_writereg(state, 0x51, 0x17); | ||
1023 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1024 | ds3000_tuner_writereg(state, 0x50, 0x08); | ||
1025 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1026 | msleep(5); | ||
1027 | |||
1028 | value = ds3000_tuner_readreg(state, 0x3d); | ||
1029 | value &= 0x0f; | ||
1030 | if ((value > 4) && (value < 15)) { | ||
1031 | value -= 3; | ||
1032 | if (value < 4) | ||
1033 | value = 4; | ||
1034 | value = ((value << 3) | 0x01) & 0x79; | ||
1035 | } | ||
1044 | 1036 | ||
1045 | ret = ds3000_set_inversion(state, p->inversion); | 1037 | ds3000_tuner_writereg(state, 0x60, value); |
1046 | if (ret != 0) | 1038 | ds3000_tuner_writereg(state, 0x51, 0x17); |
1047 | return ret; | 1039 | ds3000_tuner_writereg(state, 0x51, 0x1f); |
1040 | ds3000_tuner_writereg(state, 0x50, 0x08); | ||
1041 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1042 | |||
1043 | /* set low-pass filter period */ | ||
1044 | ds3000_tuner_writereg(state, 0x04, 0x2e); | ||
1045 | ds3000_tuner_writereg(state, 0x51, 0x1b); | ||
1046 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1047 | ds3000_tuner_writereg(state, 0x50, 0x04); | ||
1048 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1049 | msleep(5); | ||
1050 | |||
1051 | f3db = ((c->symbol_rate / 1000) << 2) / 5 + 2000; | ||
1052 | if ((c->symbol_rate / 1000) < 5000) | ||
1053 | f3db += 3000; | ||
1054 | if (f3db < 7000) | ||
1055 | f3db = 7000; | ||
1056 | if (f3db > 40000) | ||
1057 | f3db = 40000; | ||
1058 | |||
1059 | /* set low-pass filter baseband */ | ||
1060 | value = ds3000_tuner_readreg(state, 0x26); | ||
1061 | mlpf = 0x2e * 207 / ((value << 1) + 151); | ||
1062 | mlpf_max = mlpf * 135 / 100; | ||
1063 | mlpf_min = mlpf * 78 / 100; | ||
1064 | if (mlpf_max > 63) | ||
1065 | mlpf_max = 63; | ||
1066 | |||
1067 | /* rounded to the closest integer */ | ||
1068 | nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2)) | ||
1069 | / (2766 * DS3000_XTAL_FREQ); | ||
1070 | if (nlpf > 23) | ||
1071 | nlpf = 23; | ||
1072 | if (nlpf < 1) | ||
1073 | nlpf = 1; | ||
1074 | |||
1075 | /* rounded to the closest integer */ | ||
1076 | mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + | ||
1077 | (1000 * f3db / 2)) / (1000 * f3db); | ||
1078 | |||
1079 | if (mlpf_new < mlpf_min) { | ||
1080 | nlpf++; | ||
1081 | mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + | ||
1082 | (1000 * f3db / 2)) / (1000 * f3db); | ||
1083 | } | ||
1048 | 1084 | ||
1049 | ret = ds3000_set_symbolrate(state, c->symbol_rate); | 1085 | if (mlpf_new > mlpf_max) |
1050 | if (ret != 0) | 1086 | mlpf_new = mlpf_max; |
1051 | return ret; | 1087 | |
1088 | ds3000_tuner_writereg(state, 0x04, mlpf_new); | ||
1089 | ds3000_tuner_writereg(state, 0x06, nlpf); | ||
1090 | ds3000_tuner_writereg(state, 0x51, 0x1b); | ||
1091 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1092 | ds3000_tuner_writereg(state, 0x50, 0x04); | ||
1093 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1094 | msleep(5); | ||
1095 | |||
1096 | /* unknown */ | ||
1097 | ds3000_tuner_writereg(state, 0x51, 0x1e); | ||
1098 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1099 | ds3000_tuner_writereg(state, 0x50, 0x01); | ||
1100 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1101 | msleep(60); | ||
1102 | |||
1103 | offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ | ||
1104 | / (6 + 8) / (div4 + 1) / 2 - p->frequency; | ||
1105 | |||
1106 | /* ds3000 global reset */ | ||
1107 | ds3000_writereg(state, 0x07, 0x80); | ||
1108 | ds3000_writereg(state, 0x07, 0x00); | ||
1109 | /* ds3000 build-in uC reset */ | ||
1110 | ds3000_writereg(state, 0xb2, 0x01); | ||
1111 | /* ds3000 software reset */ | ||
1112 | ds3000_writereg(state, 0x00, 0x01); | ||
1052 | 1113 | ||
1053 | /* discard the 'current' tuning parameters and prepare to tune */ | 1114 | switch (c->delivery_system) { |
1054 | ds3000_clone_params(fe); | 1115 | case SYS_DVBS: |
1055 | 1116 | /* initialise the demod in DVB-S mode */ | |
1056 | retune = 1; /* try 1 times */ | 1117 | for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2) |
1057 | dprintk("%s: retune = %d\n", __func__, retune); | 1118 | ds3000_writereg(state, |
1058 | dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); | 1119 | ds3000_dvbs_init_tab[i], |
1059 | dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); | 1120 | ds3000_dvbs_init_tab[i + 1]); |
1060 | dprintk("%s: FEC = %d \n", __func__, | 1121 | value = ds3000_readreg(state, 0xfe); |
1061 | state->dcur.fec); | 1122 | value &= 0xc0; |
1062 | dprintk("%s: Inversion = %d\n", __func__, state->dcur.inversion); | 1123 | value |= 0x1b; |
1063 | 1124 | ds3000_writereg(state, 0xfe, value); | |
1064 | do { | 1125 | break; |
1065 | /* Reset status register */ | 1126 | case SYS_DVBS2: |
1066 | status = 0; | 1127 | /* initialise the demod in DVB-S2 mode */ |
1067 | /* Tune */ | 1128 | for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2) |
1068 | /* TS2020 init */ | 1129 | ds3000_writereg(state, |
1069 | ds3000_tuner_writereg(state, 0x42, 0x73); | 1130 | ds3000_dvbs2_init_tab[i], |
1070 | ds3000_tuner_writereg(state, 0x05, 0x01); | 1131 | ds3000_dvbs2_init_tab[i + 1]); |
1071 | ds3000_tuner_writereg(state, 0x62, 0xf5); | 1132 | ds3000_writereg(state, 0xfe, 0x98); |
1072 | /* unknown */ | 1133 | break; |
1073 | ds3000_tuner_writereg(state, 0x07, 0x02); | 1134 | default: |
1074 | ds3000_tuner_writereg(state, 0x10, 0x00); | 1135 | return 1; |
1075 | ds3000_tuner_writereg(state, 0x60, 0x79); | 1136 | } |
1076 | ds3000_tuner_writereg(state, 0x08, 0x01); | ||
1077 | ds3000_tuner_writereg(state, 0x00, 0x01); | ||
1078 | /* calculate and set freq divider */ | ||
1079 | if (state->dcur.frequency < 1146000) { | ||
1080 | ds3000_tuner_writereg(state, 0x10, 0x11); | ||
1081 | ndiv = ((state->dcur.frequency * (6 + 8) * 4) + | ||
1082 | (DS3000_XTAL_FREQ / 2)) / | ||
1083 | DS3000_XTAL_FREQ - 1024; | ||
1084 | } else { | ||
1085 | ds3000_tuner_writereg(state, 0x10, 0x01); | ||
1086 | ndiv = ((state->dcur.frequency * (6 + 8) * 2) + | ||
1087 | (DS3000_XTAL_FREQ / 2)) / | ||
1088 | DS3000_XTAL_FREQ - 1024; | ||
1089 | } | ||
1090 | 1137 | ||
1091 | ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8); | 1138 | /* enable 27MHz clock output */ |
1092 | ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff); | 1139 | ds3000_writereg(state, 0x29, 0x80); |
1093 | 1140 | /* enable ac coupling */ | |
1094 | /* set pll */ | 1141 | ds3000_writereg(state, 0x25, 0x8a); |
1095 | ds3000_tuner_writereg(state, 0x03, 0x06); | 1142 | |
1096 | ds3000_tuner_writereg(state, 0x51, 0x0f); | 1143 | /* enhance symbol rate performance */ |
1097 | ds3000_tuner_writereg(state, 0x51, 0x1f); | 1144 | if ((c->symbol_rate / 1000) <= 5000) { |
1098 | ds3000_tuner_writereg(state, 0x50, 0x10); | 1145 | value = 29777 / (c->symbol_rate / 1000) + 1; |
1099 | ds3000_tuner_writereg(state, 0x50, 0x00); | 1146 | if (value % 2 != 0) |
1100 | msleep(5); | 1147 | value++; |
1101 | 1148 | ds3000_writereg(state, 0xc3, 0x0d); | |
1102 | /* unknown */ | 1149 | ds3000_writereg(state, 0xc8, value); |
1103 | ds3000_tuner_writereg(state, 0x51, 0x17); | 1150 | ds3000_writereg(state, 0xc4, 0x10); |
1104 | ds3000_tuner_writereg(state, 0x51, 0x1f); | 1151 | ds3000_writereg(state, 0xc7, 0x0e); |
1105 | ds3000_tuner_writereg(state, 0x50, 0x08); | 1152 | } else if ((c->symbol_rate / 1000) <= 10000) { |
1106 | ds3000_tuner_writereg(state, 0x50, 0x00); | 1153 | value = 92166 / (c->symbol_rate / 1000) + 1; |
1107 | msleep(5); | 1154 | if (value % 2 != 0) |
1108 | 1155 | value++; | |
1109 | value = ds3000_tuner_readreg(state, 0x3d); | 1156 | ds3000_writereg(state, 0xc3, 0x07); |
1110 | value &= 0x0f; | 1157 | ds3000_writereg(state, 0xc8, value); |
1111 | if ((value > 4) && (value < 15)) { | 1158 | ds3000_writereg(state, 0xc4, 0x09); |
1112 | value -= 3; | 1159 | ds3000_writereg(state, 0xc7, 0x12); |
1113 | if (value < 4) | 1160 | } else if ((c->symbol_rate / 1000) <= 20000) { |
1114 | value = 4; | 1161 | value = 64516 / (c->symbol_rate / 1000) + 1; |
1115 | value = ((value << 3) | 0x01) & 0x79; | 1162 | ds3000_writereg(state, 0xc3, value); |
1116 | } | 1163 | ds3000_writereg(state, 0xc8, 0x0e); |
1164 | ds3000_writereg(state, 0xc4, 0x07); | ||
1165 | ds3000_writereg(state, 0xc7, 0x18); | ||
1166 | } else { | ||
1167 | value = 129032 / (c->symbol_rate / 1000) + 1; | ||
1168 | ds3000_writereg(state, 0xc3, value); | ||
1169 | ds3000_writereg(state, 0xc8, 0x0a); | ||
1170 | ds3000_writereg(state, 0xc4, 0x05); | ||
1171 | ds3000_writereg(state, 0xc7, 0x24); | ||
1172 | } | ||
1117 | 1173 | ||
1118 | ds3000_tuner_writereg(state, 0x60, value); | 1174 | /* normalized symbol rate rounded to the closest integer */ |
1119 | ds3000_tuner_writereg(state, 0x51, 0x17); | 1175 | value = (((c->symbol_rate / 1000) << 16) + |
1120 | ds3000_tuner_writereg(state, 0x51, 0x1f); | 1176 | (DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE; |
1121 | ds3000_tuner_writereg(state, 0x50, 0x08); | 1177 | ds3000_writereg(state, 0x61, value & 0x00ff); |
1122 | ds3000_tuner_writereg(state, 0x50, 0x00); | 1178 | ds3000_writereg(state, 0x62, (value & 0xff00) >> 8); |
1123 | |||
1124 | /* set low-pass filter period */ | ||
1125 | ds3000_tuner_writereg(state, 0x04, 0x2e); | ||
1126 | ds3000_tuner_writereg(state, 0x51, 0x1b); | ||
1127 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1128 | ds3000_tuner_writereg(state, 0x50, 0x04); | ||
1129 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1130 | msleep(5); | ||
1131 | |||
1132 | f3db = ((state->dcur.symbol_rate / 1000) << 2) / 5 + 2000; | ||
1133 | if ((state->dcur.symbol_rate / 1000) < 5000) | ||
1134 | f3db += 3000; | ||
1135 | if (f3db < 7000) | ||
1136 | f3db = 7000; | ||
1137 | if (f3db > 40000) | ||
1138 | f3db = 40000; | ||
1139 | |||
1140 | /* set low-pass filter baseband */ | ||
1141 | value = ds3000_tuner_readreg(state, 0x26); | ||
1142 | mlpf = 0x2e * 207 / ((value << 1) + 151); | ||
1143 | mlpf_max = mlpf * 135 / 100; | ||
1144 | mlpf_min = mlpf * 78 / 100; | ||
1145 | if (mlpf_max > 63) | ||
1146 | mlpf_max = 63; | ||
1147 | |||
1148 | /* rounded to the closest integer */ | ||
1149 | nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2)) | ||
1150 | / (2766 * DS3000_XTAL_FREQ); | ||
1151 | if (nlpf > 23) | ||
1152 | nlpf = 23; | ||
1153 | if (nlpf < 1) | ||
1154 | nlpf = 1; | ||
1155 | |||
1156 | /* rounded to the closest integer */ | ||
1157 | mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + | ||
1158 | (1000 * f3db / 2)) / (1000 * f3db); | ||
1159 | 1179 | ||
1160 | if (mlpf_new < mlpf_min) { | 1180 | /* co-channel interference cancellation disabled */ |
1161 | nlpf++; | 1181 | ds3000_writereg(state, 0x56, 0x00); |
1162 | mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) + | 1182 | |
1163 | (1000 * f3db / 2)) / (1000 * f3db); | 1183 | /* equalizer disabled */ |
1164 | } | 1184 | ds3000_writereg(state, 0x76, 0x00); |
1165 | 1185 | ||
1166 | if (mlpf_new > mlpf_max) | 1186 | /*ds3000_writereg(state, 0x08, 0x03); |
1167 | mlpf_new = mlpf_max; | 1187 | ds3000_writereg(state, 0xfd, 0x22); |
1168 | 1188 | ds3000_writereg(state, 0x08, 0x07); | |
1169 | ds3000_tuner_writereg(state, 0x04, mlpf_new); | 1189 | ds3000_writereg(state, 0xfd, 0x42); |
1170 | ds3000_tuner_writereg(state, 0x06, nlpf); | 1190 | ds3000_writereg(state, 0x08, 0x07);*/ |
1171 | ds3000_tuner_writereg(state, 0x51, 0x1b); | ||
1172 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1173 | ds3000_tuner_writereg(state, 0x50, 0x04); | ||
1174 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1175 | msleep(5); | ||
1176 | |||
1177 | /* unknown */ | ||
1178 | ds3000_tuner_writereg(state, 0x51, 0x1e); | ||
1179 | ds3000_tuner_writereg(state, 0x51, 0x1f); | ||
1180 | ds3000_tuner_writereg(state, 0x50, 0x01); | ||
1181 | ds3000_tuner_writereg(state, 0x50, 0x00); | ||
1182 | msleep(60); | ||
1183 | |||
1184 | /* ds3000 global reset */ | ||
1185 | ds3000_writereg(state, 0x07, 0x80); | ||
1186 | ds3000_writereg(state, 0x07, 0x00); | ||
1187 | /* ds3000 build-in uC reset */ | ||
1188 | ds3000_writereg(state, 0xb2, 0x01); | ||
1189 | /* ds3000 software reset */ | ||
1190 | ds3000_writereg(state, 0x00, 0x01); | ||
1191 | 1191 | ||
1192 | if (state->config->ci_mode) { | ||
1192 | switch (c->delivery_system) { | 1193 | switch (c->delivery_system) { |
1193 | case SYS_DVBS: | 1194 | case SYS_DVBS: |
1194 | /* initialise the demod in DVB-S mode */ | 1195 | default: |
1195 | for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2) | 1196 | ds3000_writereg(state, 0xfd, 0x80); |
1196 | ds3000_writereg(state, | 1197 | break; |
1197 | ds3000_dvbs_init_tab[i], | ||
1198 | ds3000_dvbs_init_tab[i + 1]); | ||
1199 | value = ds3000_readreg(state, 0xfe); | ||
1200 | value &= 0xc0; | ||
1201 | value |= 0x1b; | ||
1202 | ds3000_writereg(state, 0xfe, value); | ||
1203 | break; | ||
1204 | case SYS_DVBS2: | 1198 | case SYS_DVBS2: |
1205 | /* initialise the demod in DVB-S2 mode */ | 1199 | ds3000_writereg(state, 0xfd, 0x01); |
1206 | for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2) | ||
1207 | ds3000_writereg(state, | ||
1208 | ds3000_dvbs2_init_tab[i], | ||
1209 | ds3000_dvbs2_init_tab[i + 1]); | ||
1210 | ds3000_writereg(state, 0xfe, 0x54); | ||
1211 | break; | 1200 | break; |
1212 | default: | ||
1213 | return 1; | ||
1214 | } | 1201 | } |
1202 | } | ||
1215 | 1203 | ||
1216 | /* enable 27MHz clock output */ | 1204 | /* ds3000 out of software reset */ |
1217 | ds3000_writereg(state, 0x29, 0x80); | 1205 | ds3000_writereg(state, 0x00, 0x00); |
1218 | /* enable ac coupling */ | 1206 | /* start ds3000 build-in uC */ |
1219 | ds3000_writereg(state, 0x25, 0x8a); | 1207 | ds3000_writereg(state, 0xb2, 0x00); |
1220 | |||
1221 | /* enhance symbol rate performance */ | ||
1222 | if ((state->dcur.symbol_rate / 1000) <= 5000) { | ||
1223 | value = 29777 / (state->dcur.symbol_rate / 1000) + 1; | ||
1224 | if (value % 2 != 0) | ||
1225 | value++; | ||
1226 | ds3000_writereg(state, 0xc3, 0x0d); | ||
1227 | ds3000_writereg(state, 0xc8, value); | ||
1228 | ds3000_writereg(state, 0xc4, 0x10); | ||
1229 | ds3000_writereg(state, 0xc7, 0x0e); | ||
1230 | } else if ((state->dcur.symbol_rate / 1000) <= 10000) { | ||
1231 | value = 92166 / (state->dcur.symbol_rate / 1000) + 1; | ||
1232 | if (value % 2 != 0) | ||
1233 | value++; | ||
1234 | ds3000_writereg(state, 0xc3, 0x07); | ||
1235 | ds3000_writereg(state, 0xc8, value); | ||
1236 | ds3000_writereg(state, 0xc4, 0x09); | ||
1237 | ds3000_writereg(state, 0xc7, 0x12); | ||
1238 | } else if ((state->dcur.symbol_rate / 1000) <= 20000) { | ||
1239 | value = 64516 / (state->dcur.symbol_rate / 1000) + 1; | ||
1240 | ds3000_writereg(state, 0xc3, value); | ||
1241 | ds3000_writereg(state, 0xc8, 0x0e); | ||
1242 | ds3000_writereg(state, 0xc4, 0x07); | ||
1243 | ds3000_writereg(state, 0xc7, 0x18); | ||
1244 | } else { | ||
1245 | value = 129032 / (state->dcur.symbol_rate / 1000) + 1; | ||
1246 | ds3000_writereg(state, 0xc3, value); | ||
1247 | ds3000_writereg(state, 0xc8, 0x0a); | ||
1248 | ds3000_writereg(state, 0xc4, 0x05); | ||
1249 | ds3000_writereg(state, 0xc7, 0x24); | ||
1250 | } | ||
1251 | 1208 | ||
1252 | /* normalized symbol rate rounded to the closest integer */ | 1209 | ds3000_set_carrier_offset(fe, offset_khz); |
1253 | value = (((state->dcur.symbol_rate / 1000) << 16) + | ||
1254 | (DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE; | ||
1255 | ds3000_writereg(state, 0x61, value & 0x00ff); | ||
1256 | ds3000_writereg(state, 0x62, (value & 0xff00) >> 8); | ||
1257 | |||
1258 | /* co-channel interference cancellation disabled */ | ||
1259 | ds3000_writereg(state, 0x56, 0x00); | ||
1260 | |||
1261 | /* equalizer disabled */ | ||
1262 | ds3000_writereg(state, 0x76, 0x00); | ||
1263 | |||
1264 | /*ds3000_writereg(state, 0x08, 0x03); | ||
1265 | ds3000_writereg(state, 0xfd, 0x22); | ||
1266 | ds3000_writereg(state, 0x08, 0x07); | ||
1267 | ds3000_writereg(state, 0xfd, 0x42); | ||
1268 | ds3000_writereg(state, 0x08, 0x07);*/ | ||
1269 | |||
1270 | /* ds3000 out of software reset */ | ||
1271 | ds3000_writereg(state, 0x00, 0x00); | ||
1272 | /* start ds3000 build-in uC */ | ||
1273 | ds3000_writereg(state, 0xb2, 0x00); | ||
1274 | |||
1275 | /* TODO: calculate and set carrier offset */ | ||
1276 | |||
1277 | /* wait before retrying */ | ||
1278 | for (i = 0; i < 30 ; i++) { | ||
1279 | if (ds3000_is_tuned(fe)) { | ||
1280 | dprintk("%s: Tuned\n", __func__); | ||
1281 | ds3000_dump_registers(fe); | ||
1282 | goto tuned; | ||
1283 | } | ||
1284 | msleep(1); | ||
1285 | } | ||
1286 | 1210 | ||
1287 | dprintk("%s: Not tuned\n", __func__); | 1211 | for (i = 0; i < 30 ; i++) { |
1288 | ds3000_dump_registers(fe); | 1212 | ds3000_read_status(fe, &status); |
1213 | if (status && FE_HAS_LOCK) | ||
1214 | break; | ||
1289 | 1215 | ||
1290 | } while (--retune); | 1216 | msleep(10); |
1217 | } | ||
1291 | 1218 | ||
1292 | tuned: | 1219 | return 0; |
1293 | return ret; | 1220 | } |
1221 | |||
1222 | static int ds3000_tune(struct dvb_frontend *fe, | ||
1223 | struct dvb_frontend_parameters *p, | ||
1224 | unsigned int mode_flags, | ||
1225 | unsigned int *delay, | ||
1226 | fe_status_t *status) | ||
1227 | { | ||
1228 | if (p) { | ||
1229 | int ret = ds3000_set_frontend(fe, p); | ||
1230 | if (ret) | ||
1231 | return ret; | ||
1232 | } | ||
1233 | |||
1234 | *delay = HZ / 5; | ||
1235 | |||
1236 | return ds3000_read_status(fe, status); | ||
1294 | } | 1237 | } |
1295 | 1238 | ||
1296 | static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) | 1239 | static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) |
1297 | { | 1240 | { |
1298 | dprintk("%s()\n", __func__); | 1241 | dprintk("%s()\n", __func__); |
1299 | return DVBFE_ALGO_SW; | 1242 | return DVBFE_ALGO_HW; |
1300 | } | 1243 | } |
1301 | 1244 | ||
1302 | /* | 1245 | /* |
@@ -1306,7 +1249,25 @@ static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) | |||
1306 | */ | 1249 | */ |
1307 | static int ds3000_initfe(struct dvb_frontend *fe) | 1250 | static int ds3000_initfe(struct dvb_frontend *fe) |
1308 | { | 1251 | { |
1252 | struct ds3000_state *state = fe->demodulator_priv; | ||
1253 | int ret; | ||
1254 | |||
1309 | dprintk("%s()\n", __func__); | 1255 | dprintk("%s()\n", __func__); |
1256 | /* hard reset */ | ||
1257 | ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08)); | ||
1258 | msleep(1); | ||
1259 | |||
1260 | /* TS2020 init */ | ||
1261 | ds3000_tuner_writereg(state, 0x42, 0x73); | ||
1262 | ds3000_tuner_writereg(state, 0x05, 0x01); | ||
1263 | ds3000_tuner_writereg(state, 0x62, 0xf5); | ||
1264 | /* Load the firmware if required */ | ||
1265 | ret = ds3000_firmware_ondemand(fe); | ||
1266 | if (ret != 0) { | ||
1267 | printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); | ||
1268 | return ret; | ||
1269 | } | ||
1270 | |||
1310 | return 0; | 1271 | return 0; |
1311 | } | 1272 | } |
1312 | 1273 | ||
@@ -1345,6 +1306,7 @@ static struct dvb_frontend_ops ds3000_ops = { | |||
1345 | .read_signal_strength = ds3000_read_signal_strength, | 1306 | .read_signal_strength = ds3000_read_signal_strength, |
1346 | .read_snr = ds3000_read_snr, | 1307 | .read_snr = ds3000_read_snr, |
1347 | .read_ucblocks = ds3000_read_ucblocks, | 1308 | .read_ucblocks = ds3000_read_ucblocks, |
1309 | .set_voltage = ds3000_set_voltage, | ||
1348 | .set_tone = ds3000_set_tone, | 1310 | .set_tone = ds3000_set_tone, |
1349 | .diseqc_send_master_cmd = ds3000_send_diseqc_msg, | 1311 | .diseqc_send_master_cmd = ds3000_send_diseqc_msg, |
1350 | .diseqc_send_burst = ds3000_diseqc_send_burst, | 1312 | .diseqc_send_burst = ds3000_diseqc_send_burst, |
@@ -1352,7 +1314,8 @@ static struct dvb_frontend_ops ds3000_ops = { | |||
1352 | 1314 | ||
1353 | .set_property = ds3000_set_property, | 1315 | .set_property = ds3000_set_property, |
1354 | .get_property = ds3000_get_property, | 1316 | .get_property = ds3000_get_property, |
1355 | .set_frontend = ds3000_tune, | 1317 | .set_frontend = ds3000_set_frontend, |
1318 | .tune = ds3000_tune, | ||
1356 | }; | 1319 | }; |
1357 | 1320 | ||
1358 | module_param(debug, int, 0644); | 1321 | module_param(debug, int, 0644); |