diff options
Diffstat (limited to 'drivers/media/dvb/bt8xx')
-rw-r--r-- | drivers/media/dvb/bt8xx/bt878.c | 11 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/dst.c | 606 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/dst_ca.c | 116 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/dst_common.h | 33 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/dvb-bt8xx.c | 118 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/dvb-bt8xx.h | 2 |
6 files changed, 678 insertions, 208 deletions
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 5500f8a0ffe..761fa6e7d76 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off)."); int bt878_num; struct bt878 bt878[BT878_MAX]; -EXPORT_SYMBOL(bt878_debug); -EXPORT_SYMBOL(bt878_verbose); EXPORT_SYMBOL(bt878_num); EXPORT_SYMBOL(bt878); @@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = { { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, - { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" }, + { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }, + { 0, -1, NULL } }; @@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev, printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); + if (bt878_num >= BT878_MAX) { + printk(KERN_ERR "bt878: Too many devices inserted\n"); + result = -ENOMEM; + goto fail0; + } if (pci_enable_device(dev)) return -EIO; diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 1cfa5e5035d..d687a14ec0a 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -38,6 +38,10 @@ static unsigned int dst_addons; module_param(dst_addons, int, 0644); MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)"); +static unsigned int dst_algo; +module_param(dst_algo, int, 0644); +MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)"); + #define HAS_LOCK 1 #define ATTEMPT_TUNE 2 #define HAS_POWER 4 @@ -47,20 +51,24 @@ MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)"); #define DST_INFO 2 #define DST_DEBUG 3 -#define dprintk(x, y, z, format, arg...) do { \ - if (z) { \ - if ((x > DST_ERROR) && (x > y)) \ - printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_NOTICE) && (x > y)) \ - printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_INFO) && (x > y)) \ - printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_DEBUG) && (x > y)) \ - printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \ - } else { \ - if (x > y) \ - printk(format, ##arg); \ - } \ +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > DST_ERROR) && (x > y)) \ + printk(KERN_ERR "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_INFO) && (x > y)) \ + printk(KERN_INFO "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + } else { \ + if (x > y) \ + printk(format, ##arg); \ + } \ } while(0) @@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state, u8 *result) *result = 0; if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { - dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err); + dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err); return -EREMOTEIO; } *result = (u8) rd_packet.rd.value; @@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state *state, u32 freq) state->tx_tuna[2] = (freq >> 16) & 0xff; state->tx_tuna[3] = (freq >> 8) & 0xff; state->tx_tuna[4] = (u8) freq; + } else if (state->dst_type == DST_TYPE_IS_ATSC) { + freq = freq / 1000; + if (freq < 51000 || freq > 858000) + return -EINVAL; + state->tx_tuna[2] = (freq >> 16) & 0xff; + state->tx_tuna[3] = (freq >> 8) & 0xff; + state->tx_tuna[4] = (u8) freq; + state->tx_tuna[5] = 0x00; /* ATSC */ + state->tx_tuna[6] = 0x00; + if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG) + state->tx_tuna[7] = 0x00; /* Digital */ } else return -EINVAL; @@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate) } dprintk(verbose, DST_INFO, 1, "set symrate %u", srate); srate /= 1000; - if (state->type_flags & DST_TYPE_HAS_SYMDIV) { - sval = srate; - sval <<= 20; - do_div(sval, 88000); - symcalc = (u32) sval; - dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc); - state->tx_tuna[5] = (u8) (symcalc >> 12); - state->tx_tuna[6] = (u8) (symcalc >> 4); - state->tx_tuna[7] = (u8) (symcalc << 4); - } else { - state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; - state->tx_tuna[6] = (u8) (srate >> 8); - state->tx_tuna[7] = (u8) srate; - } - state->tx_tuna[8] &= ~0x20; - if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { - if (srate > 8000) - state->tx_tuna[8] |= 0x20; + if (state->dst_type == DST_TYPE_IS_SAT) { + if (state->type_flags & DST_TYPE_HAS_SYMDIV) { + sval = srate; + sval <<= 20; + do_div(sval, 88000); + symcalc = (u32) sval; + dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc); + state->tx_tuna[5] = (u8) (symcalc >> 12); + state->tx_tuna[6] = (u8) (symcalc >> 4); + state->tx_tuna[7] = (u8) (symcalc << 4); + } else { + state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; + state->tx_tuna[6] = (u8) (srate >> 8); + state->tx_tuna[7] = (u8) srate; + } + state->tx_tuna[8] &= ~0x20; + if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { + if (srate > 8000) + state->tx_tuna[8] |= 0x20; + } + } else if (state->dst_type == DST_TYPE_IS_CABLE) { + dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name); + if (!strncmp(state->fw_name, "DCTNEW", 6)) { + state->tx_tuna[5] = (u8) (srate >> 8); + state->tx_tuna[6] = (u8) srate; + state->tx_tuna[7] = 0x00; + } else if (!strncmp(state->fw_name, "DCT-CI", 6)) { + state->tx_tuna[5] = 0x00; + state->tx_tuna[6] = (u8) (srate >> 8); + state->tx_tuna[7] = (u8) srate; + } } return 0; } - static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation) { if (state->dst_type != DST_TYPE_IS_CABLE) @@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio state->tx_tuna[8] = 0x80; break; case QAM_256: - state->tx_tuna[8] = 0x00; + if (!strncmp(state->fw_name, "DCTNEW", 6)) + state->tx_tuna[8] = 0xff; + else if (!strncmp(state->fw_name, "DCT-CI", 6)) + state->tx_tuna[8] = 0x00; break; case QPSK: case QAM_AUTO: @@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len) } EXPORT_SYMBOL(dst_check_sum); -static void dst_type_flags_print(u32 type_flags) +static void dst_type_flags_print(struct dst_state *state) { + u32 type_flags = state->type_flags; + dprintk(verbose, DST_ERROR, 0, "DST type flags :"); - if (type_flags & DST_TYPE_HAS_NEWTUNE) - dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE); + if (type_flags & DST_TYPE_HAS_TS188) + dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188); + if (type_flags & DST_TYPE_HAS_NEWTUNE_2) + dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2); if (type_flags & DST_TYPE_HAS_TS204) dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204); + if (type_flags & DST_TYPE_HAS_VLF) + dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF); if (type_flags & DST_TYPE_HAS_SYMDIV) dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV); if (type_flags & DST_TYPE_HAS_FW_1) @@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 type_flags) } -static int dst_type_print(u8 type) +static int dst_type_print(struct dst_state *state, u8 type) { char *otype; switch (type) { @@ -558,6 +598,10 @@ static int dst_type_print(u8 type) otype = "cable"; break; + case DST_TYPE_IS_ATSC: + otype = "atsc"; + break; + default: dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type); return -EINVAL; @@ -567,6 +611,127 @@ static int dst_type_print(u8 type) return 0; } +struct tuner_types tuner_list[] = { + { + .tuner_type = TUNER_TYPE_L64724, + .tuner_name = "L 64724", + .board_name = "UNKNOWN", + .fw_name = "UNKNOWN" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1020", + .fw_name = "DST-MOT" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1020", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_MB86A15, + .tuner_name = "MB 86A15", + .board_name = "VP1022", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_MB86A15, + .tuner_name = "MB 86A15", + .board_name = "VP1025", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1030", + .fw_name = "DST-CI" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1030", + .fw_name = "DSTMCI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2021", + .fw_name = "DCTNEW" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2030", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2031", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2040", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3020", + .fw_name = "DTTFTA" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3021", + .fw_name = "DTTFTA" + }, + + { + .tuner_type = TUNER_TYPE_TDA10046, + .tuner_name = "TDA10046", + .board_name = "VP3040", + .fw_name = "DTT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3051", + .fw_name = "DTTNXT" + }, + + { + .tuner_type = TUNER_TYPE_NXT200x, + .tuner_name = "NXT200x", + .board_name = "VP3220", + .fw_name = "ATSCDI" + }, + + { + .tuner_type = TUNER_TYPE_NXT200x, + .tuner_name = "NXT200x", + .board_name = "VP3250", + .fw_name = "ATSCAD" + }, +}; + /* Known cards list Satellite @@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { @@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { .device_id = "DST-030", .offset = 0, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { @@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = { .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2, .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5 - | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO + | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO, + .tuner_type = TUNER_TYPE_MULTI }, { @@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { .device_id = "DST-CI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, /* An OEM board */ { .device_id = "DSTMCI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT, + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF, .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 - | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC + | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC, + .tuner_type = TUNER_TYPE_MULTI }, { .device_id = "DSTFCI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, + .dst_feature = 0, + .tuner_type = 0 }, /* unknown to vendor */ { .device_id = "DCT-CI", .offset = 1, .dst_type = DST_TYPE_IS_CABLE, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1 - | DST_TYPE_HAS_FW_2, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, { .device_id = "DCTNEW", .offset = 1, .dst_type = DST_TYPE_IS_CABLE, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE, + .dst_feature = 0, + .tuner_type = 0 }, { .device_id = "DTT-CI", .offset = 1, .dst_type = DST_TYPE_IS_TERR, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, { @@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_TERR, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, { @@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_TERR, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = DST_TYPE_HAS_ANALOG + .dst_feature = DST_TYPE_HAS_ANALOG, + .tuner_type = 0 }, { @@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_ATSC, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, { .device_id = "ATSCAD", .offset = 1, .dst_type = DST_TYPE_IS_ATSC, - .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD, + .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG, + .tuner_type = 0 }, { } @@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state *state) static int dst_card_type(struct dst_state *state) { + int j; + struct tuner_types *p_tuner_list = NULL; + u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; get_type[7] = dst_check_sum(get_type, 7); if (dst_command(state, get_type, 8) < 0) { @@ -775,9 +957,17 @@ static int dst_card_type(struct dst_state *state) return -1; } memset(&state->card_info, '\0', 8); - memcpy(&state->card_info, &state->rxbuffer, 8); + memcpy(&state->card_info, &state->rxbuffer, 7); dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]); + for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { + if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) { + state->tuner_type = p_tuner_list->tuner_type; + dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]", + p_tuner_list->tuner_name, p_tuner_list->tuner_type); + } + } + return 0; } @@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_state *state) return -1; } memset(&state->vendor, '\0', 8); - memcpy(&state->vendor, &state->rxbuffer, 8); + memcpy(&state->vendor, &state->rxbuffer, 7); dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]); return 0; } +static void debug_dst_buffer(struct dst_state *state) +{ + int i; + + if (verbose > 2) { + printk("%s: [", __func__); + for (i = 0; i < 8; i++) + printk(" %02x", state->rxbuffer[i]); + printk("]\n"); + } +} + +static int dst_check_stv0299(struct dst_state *state) +{ + u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_stv0299[7] = dst_check_sum(check_stv0299, 7); + if (dst_command(state, check_stv0299, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed"); + return -1; + } + debug_dst_buffer(state); + + if (memcmp(&check_stv0299, &state->rxbuffer, 8)) { + dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM"); + state->tuner_type = TUNER_TYPE_STV0299; + return 0; + } + + return -1; +} + +static int dst_check_mb86a15(struct dst_state *state) +{ + u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_mb86a15[7] = dst_check_sum(check_mb86a15, 7); + if (dst_command(state, check_mb86a15, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed"); + return -1; + } + debug_dst_buffer(state); + + if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM"); + state->tuner_type = TUNER_TYPE_MB86A15; + return 0; + } + + return -1; +} + static int dst_get_tuner_info(struct dst_state *state) { u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst_state *state) get_tuner_1[7] = dst_check_sum(get_tuner_1, 7); get_tuner_2[7] = dst_check_sum(get_tuner_2, 7); + dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE"); if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { - if (dst_command(state, get_tuner_2, 8) < 0) { - dprintk(verbose, DST_INFO, 1, "Unsupported Command"); - return -1; + if (dst_command(state, get_tuner_1, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported"); + goto force; } } else { - if (dst_command(state, get_tuner_1, 8) < 0) { - dprintk(verbose, DST_INFO, 1, "Unsupported Command"); - return -1; + if (dst_command(state, get_tuner_2, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported"); + goto force; } } memset(&state->board_info, '\0', 8); memcpy(&state->board_info, &state->rxbuffer, 8); if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { - if (state->board_info[1] == 0x0b) { - if (state->type_flags & DST_TYPE_HAS_TS204) - state->type_flags &= ~DST_TYPE_HAS_TS204; - state->type_flags |= DST_TYPE_HAS_NEWTUNE; - dprintk(verbose, DST_INFO, 1, "DST type has TS=188"); - } else { - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; - state->type_flags |= DST_TYPE_HAS_TS204; - dprintk(verbose, DST_INFO, 1, "DST type has TS=204"); - } - } else { - if (state->board_info[0] == 0xbc) { - if (state->type_flags & DST_TYPE_HAS_TS204) - state->type_flags &= ~DST_TYPE_HAS_TS204; - state->type_flags |= DST_TYPE_HAS_NEWTUNE; - dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]); - - } else if (state->board_info[0] == 0xcc) { - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; - state->type_flags |= DST_TYPE_HAS_TS204; - dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]); + dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); + } + if (state->board_info[0] == 0xbc) { + if (state->type_flags != DST_TYPE_IS_ATSC) + state->type_flags |= DST_TYPE_HAS_TS188; + else + state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; + + if (state->board_info[1] == 0x01) { + state->dst_hw_cap |= DST_TYPE_HAS_DBOARD; + dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard"); } } return 0; +force: + if (!strncmp(state->fw_name, "DCT-CI", 6)) { + state->type_flags |= DST_TYPE_HAS_TS204; + dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name); + } + + return -1; } static int dst_get_device_id(struct dst_state *state) { u8 reply; - int i; - struct dst_types *p_dst_type; + int i, j; + struct dst_types *p_dst_type = NULL; + struct tuner_types *p_tuner_list = NULL; + u8 use_dst_type = 0; u32 use_type_flags = 0; static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; + state->tuner_type = 0; device_type[7] = dst_check_sum(device_type, 7); if (write_dst(state, device_type, FIXED_COMM)) @@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_state *state) /* Card capabilities */ state->dst_hw_cap = p_dst_type->dst_feature; - dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id); - + dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id); + strncpy(&state->fw_name[0], p_dst_type->device_id, 6); + /* Multiple tuners */ + if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { + switch (use_dst_type) { + case DST_TYPE_IS_SAT: + /* STV0299 check */ + if (dst_check_stv0299(state) < 0) { + dprintk(verbose, DST_ERROR, 1, "Unsupported"); + state->tuner_type = TUNER_TYPE_MB86A15; + } + break; + default: + break; + } + if (dst_check_mb86a15(state) < 0) + dprintk(verbose, DST_ERROR, 1, "Unsupported"); + /* Single tuner */ + } else { + state->tuner_type = p_dst_type->tuner_type; + } + for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { + if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) && + p_tuner_list->tuner_type == state->tuner_type) { + dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]", + p_dst_type->device_id, p_tuner_list->tuner_name); + } + } break; } } @@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_state *state) use_dst_type = DST_TYPE_IS_SAT; use_type_flags = DST_TYPE_HAS_SYMDIV; } - dst_type_print(use_dst_type); + dst_type_print(state, use_dst_type); state->type_flags = use_type_flags; state->dst_type = use_dst_type; - dst_type_flags_print(state->type_flags); + dst_type_flags_print(state); return 0; } @@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_state *state) static int dst_probe(struct dst_state *state) { mutex_init(&state->dst_mutex); - if ((rdc_8820_reset(state)) < 0) { - dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); - return -1; - } - if (dst_addons & DST_TYPE_HAS_CA) + if (dst_addons & DST_TYPE_HAS_CA) { + if ((rdc_8820_reset(state)) < 0) { + dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); + return -1; + } msleep(4000); - else + } else { msleep(100); - + } if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed."); return -1; @@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *state) } if (dst_get_mac(state) < 0) { dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command"); - return 0; } if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) { if (dst_get_tuner_info(state) < 0) @@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_state *state) state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; state->decode_strength = state->rxbuffer[4] << 8; state->decode_snr = state->rxbuffer[3] << 8; + } else if (state->dst_type == DST_TYPE_IS_ATSC) { + state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0; + state->decode_strength = state->rxbuffer[4] << 8; + state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; } state->cur_jiff = jiffies; } @@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state *state) state->diseq_flags &= ~(HAS_LOCK); if (!dst_wait_dst_ready(state, NO_DELAY)) return -EIO; - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - /* how to get variable length reply ???? */ + if ((state->type_flags & DST_TYPE_HAS_VLF) && + !(state->dst_type == DST_TYPE_IS_ATSC)) + retval = read_dst(state, state->rx_tuna, 10); else retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM); @@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state *state) dprintk(verbose, DST_DEBUG, 1, "read not successful"); return retval; } - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + if ((state->type_flags & DST_TYPE_HAS_VLF) && + !(state->dst_type == DST_TYPE_IS_CABLE) && + !(state->dst_type == DST_TYPE_IS_ATSC)) { + if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk(verbose, DST_INFO, 1, "checksum failure ? "); return -EIO; @@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_frontend *fe) dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed."); goto error; } - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { +// if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + if ((state->type_flags & DST_TYPE_HAS_VLF) && + (!(state->dst_type == DST_TYPE_IS_ATSC))) { + state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); retval = write_dst(state, &state->tx_tuna[0], 10); } else { @@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd if (state->dst_type != DST_TYPE_IS_SAT) return 0; - if (cmd->msg_len == 0 || cmd->msg_len > 4) + if (cmd->msg_len > 0 && cmd->msg_len < 5) + memcpy(&paket[3], cmd->msg, cmd->msg_len); + else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5) + memcpy(&paket[2], cmd->msg, cmd->msg_len); + else return -EINVAL; - memcpy(&paket[3], cmd->msg, cmd->msg_len); paket[7] = dst_check_sum(&paket[0], 7); dst_command(state, paket, 8); return 0; @@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend *fe) static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 }; static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; - static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; + static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; + static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; state->inversion = INVERSION_OFF; state->voltage = SEC_VOLTAGE_13; @@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend *fe) state->bandwidth = BANDWIDTH_7_MHZ; state->cur_jiff = jiffies; if (state->dst_type == DST_TYPE_IS_SAT) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); else if (state->dst_type == DST_TYPE_IS_TERR) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); else if (state->dst_type == DST_TYPE_IS_CABLE) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); + else if (state->dst_type == DST_TYPE_IS_ATSC) + memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner)); return 0; } @@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; } -static int dst_set_frontend(struct dvb_frontend* fe, +static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct dst_state *state = fe->demodulator_priv; + + if (p != NULL) { + dst_set_freq(state, p->frequency); + dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); + + if (state->dst_type == DST_TYPE_IS_SAT) { + if (state->type_flags & DST_TYPE_HAS_OBS_REGS) + dst_set_inversion(state, p->inversion); + dst_set_fec(state, p->u.qpsk.fec_inner); + dst_set_symbolrate(state, p->u.qpsk.symbol_rate); + dst_set_polarization(state); + dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); + + } else if (state->dst_type == DST_TYPE_IS_TERR) + dst_set_bandwidth(state, p->u.ofdm.bandwidth); + else if (state->dst_type == DST_TYPE_IS_CABLE) { + dst_set_fec(state, p->u.qam.fec_inner); + dst_set_symbolrate(state, p->u.qam.symbol_rate); + dst_set_modulation(state, p->u.qam.modulation); + } + dst_write_tuna(fe); + } + + return 0; +} + +static int dst_tune_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* p, unsigned int mode_flags, int *delay, @@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_frontend* fe, return 0; } +static int dst_get_tuning_algo(struct dvb_frontend *fe) +{ + return dst_algo; +} + static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { struct dst_state *state = fe->demodulator_priv; @@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_frontend *fe) static struct dvb_frontend_ops dst_dvbt_ops; static struct dvb_frontend_ops dst_dvbs_ops; static struct dvb_frontend_ops dst_dvbc_ops; +static struct dvb_frontend_ops dst_atsc_ops; struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter) { @@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad return NULL; } /* determine settings based on type */ + /* create dvb_frontend */ switch (state->dst_type) { case DST_TYPE_IS_TERR: - memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_CABLE: - memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_SAT: - memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); + break; + case DST_TYPE_IS_ATSC: + memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops)); break; default: dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist."); kfree(state); return NULL; } - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; return state; /* Manu (DST is a card not a frontend) */ @@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ops = { .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, @@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ops = { .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, @@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ops = { .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, + .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, + .read_status = dst_read_status, + .read_signal_strength = dst_read_signal_strength, + .read_snr = dst_read_snr, +}; + +static struct dvb_frontend_ops dst_atsc_ops = { + .info = { + .name = "DST ATSC", + .type = FE_ATSC, + .frequency_stepsize = 62500, + .frequency_min = 510000000, + .frequency_max = 858000000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + + .release = dst_release, + .init = dst_init, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, }; -MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver"); +MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver"); MODULE_AUTHOR("Jamie Honan, Manu Abraham"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index f6b49a801eb..fa923b9b346 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -68,6 +68,13 @@ static int ca_set_pid(void) return -EOPNOTSUPP; } +static void put_command_and_length(u8 *data, int command, int length) +{ + data[0] = (command >> 16) & 0xff; + data[1] = (command >> 8) & 0xff; + data[2] = command & 0xff; + data[3] = length; +} static void put_checksum(u8 *check_string, int length) { @@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, u8 dst_ca_comm_err = 0; while (dst_ca_comm_err < RETRIES) { - dst_comm_init(state); dprintk(verbose, DST_CA_NOTICE, 1, " Put Command"); if (dst_ci_command(state, data, ca_string, len, read)) { // If error dst_error_recovery(state); dst_ca_comm_err++; // work required here. + } else { + break; } - break; } + if(dst_ca_comm_err == RETRIES) + return -1; + return 0; } @@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, static int ca_get_app_info(struct dst_state *state) { + int length, str_length; static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff}; put_checksum(&command[0], command[0]); @@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state) (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); + // Transform dst message to correct application_info message + length = state->messages[5]; + str_length = length - 6; + if (str_length < 0) { + str_length = 0; + dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering."); + } + + // First, the command and length fields + put_command_and_length(&state->messages[0], CA_APP_INFO, length); + + // Copy application_type, application_manufacturer and manufacturer_code + memcpy(&state->messages[4], &state->messages[7], 5); + + // Set string length and copy string + state->messages[9] = str_length; + memcpy(&state->messages[10], &state->messages[12], str_length); + + return 0; +} + +static int ca_get_ca_info(struct dst_state *state) +{ + int srcPtr, dstPtr, i, num_ids; + static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff}; + const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7; + + put_checksum(&slot_command[0], slot_command[0]); + if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) { + dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); + return -1; + } + dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !"); + + // Print raw data + dprintk(verbose, DST_CA_INFO, 0, " DST data = ["); + for (i = 0; i < state->messages[0] + 1; i++) { + dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]); + } + dprintk(verbose, DST_CA_INFO, 0, "]\n"); + + // Set the command and length of the output + num_ids = state->messages[in_num_ids_pos]; + if (num_ids >= 100) { + num_ids = 100; + dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering."); + } + put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2); + + dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = ["); + srcPtr = in_system_id_pos; + dstPtr = out_system_id_pos; + for(i = 0; i < num_ids; i++) { + dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]); + // Append to output + state->messages[dstPtr + 0] = state->messages[srcPtr + 0]; + state->messages[dstPtr + 1] = state->messages[srcPtr + 1]; + srcPtr += 2; + dstPtr += 2; + } + dprintk(verbose, DST_CA_INFO, 0, "]\n"); + return 0; } @@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]); dprintk(verbose, DST_CA_INFO, 0, "===================================\n"); - for (i = 0; i < 8; i++) + for (i = 0; i < slot_cap[0] + 1; i++) dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]); dprintk(verbose, DST_CA_INFO, 0, "\n"); @@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) return -EFAULT; break; + case CA_INFO: + memcpy(p_ca_message->msg, state->messages, 128); + if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) + return -EFAULT; + break; } } @@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l rdc_reset_state(state); return -1; } - dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes."); + dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success."); return 0; } @@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset) return 0; } + static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query) { u32 length = 0; @@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, } dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); break; + case CA_INFO_ENQUIRY: + dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information"); + + if ((ca_get_ca_info(state)) < 0) { + dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !"); + result = -1; + goto free_mem_and_exit; + } + dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !"); + break; } } free_mem_and_exit: @@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd void __user *arg = (void __user *)ioctl_arg; int result = 0; - if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { - dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; - } - if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) { + p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); + p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); + p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); + if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; - } - if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) { - dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; + result = -ENOMEM; + goto free_mem_and_exit; } + /* We have now only the standard ioctl's, the driver is upposed to handle internals. */ switch (cmd) { case CA_SEND_MSG: @@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file) static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) { - int bytes_read = 0; + ssize_t bytes_read = 0; dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 51d4e043716..0677b047b3a 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -42,7 +42,7 @@ #define DST_TYPE_IS_CABLE 2 #define DST_TYPE_IS_ATSC 3 -#define DST_TYPE_HAS_NEWTUNE 1 +#define DST_TYPE_HAS_TS188 1 #define DST_TYPE_HAS_TS204 2 #define DST_TYPE_HAS_SYMDIV 4 #define DST_TYPE_HAS_FW_1 8 @@ -52,6 +52,9 @@ #define DST_TYPE_HAS_OBS_REGS 128 #define DST_TYPE_HAS_INC_COUNT 256 #define DST_TYPE_HAS_MULTI_FE 512 +#define DST_TYPE_HAS_NEWTUNE_2 1024 +#define DST_TYPE_HAS_DBOARD 2048 +#define DST_TYPE_HAS_VLF 4096 /* Card capability list */ @@ -64,6 +67,20 @@ #define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */ #define DST_TYPE_HAS_SESSION 128 +#define TUNER_TYPE_MULTI 1 +#define TUNER_TYPE_UNKNOWN 2 +/* DVB-S */ +#define TUNER_TYPE_L64724 4 +#define TUNER_TYPE_STV0299 8 +#define TUNER_TYPE_MB86A15 16 + +/* DVB-T */ +#define TUNER_TYPE_TDA10046 32 + +/* ATSC */ +#define TUNER_TYPE_NXT200x 64 + + #define RDC_8820_PIO_0_DISABLE 0 #define RDC_8820_PIO_0_ENABLE 1 #define RDC_8820_INT 2 @@ -84,8 +101,6 @@ struct dst_state { struct bt878* bt; - struct dvb_frontend_ops ops; - /* configuration settings */ const struct dst_config* config; @@ -121,8 +136,17 @@ struct dst_state { u8 card_info[8]; u8 vendor[8]; u8 board_info[8]; - + u32 tuner_type; + char *tuner_name; struct mutex dst_mutex; + u8 fw_name[8]; +}; + +struct tuner_types { + u32 tuner_type; + char *tuner_name; + char *board_name; + char *fw_name; }; struct dst_types { @@ -131,6 +155,7 @@ struct dst_types { u8 dst_type; u32 type_flags; u32 dst_feature; + u32 tuner_type; }; struct dst_config diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index ccc7b2eb4a2..b715b972d2f 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe) return 0; } -static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; unsigned char cp = 0; + if (buf_len < 5) + return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; if (params->frequency < 542000000) @@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_ else bs = 0x08; - pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address + pllbuf[0] = 0x60; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = cp; pllbuf[4] = bs; - return 0; + return 5; } static struct mt352_config thomson_dtt7579_config = { .demod_address = 0x0f, .demod_init = thomson_dtt7579_demod_init, - .pll_set = thomson_dtt7579_pll_set, }; -static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static struct zl10353_config thomson_dtt7579_zl10353_config = { + .demod_address = 0x0f, +}; + +static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { u32 freq = params->frequency; @@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete return 0; } -static int pinnsat_pll_init(struct dvb_frontend* fe) +static int pinnsat_tuner_init(struct dvb_frontend* fe) { struct dvb_bt8xx_card *card = fe->dvb->priv; @@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe) return 0; } -static int pinnsat_pll_sleep(struct dvb_frontend* fe) +static int pinnsat_tuner_sleep(struct dvb_frontend* fe) { struct dvb_bt8xx_card *card = fe->dvb->priv; @@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe) static struct cx24110_config pctvsat_config = { .demod_address = 0x55, - .pll_init = pinnsat_pll_init, - .pll_set = cx24108_pll_set, - .pll_sleep = pinnsat_pll_sleep, }; -static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; u8 cfg, cpump, band_select; @@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(card->i2c_adapter, &msg, 1); return (div * 166666 - 36000000); } @@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s static struct sp887x_config microtune_mt7202dtf_config = { .demod_address = 0x70, - .pll_set = microtune_mt7202dtf_pll_set, .request_firmware = microtune_mt7202dtf_request_firmware, }; @@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) return 0; } -static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; unsigned char cp = 0; + if (buf_len < 5) return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; if (params->frequency < 150000000) @@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct else bs = 0x08; - pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[0] = 0x61; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = cp; pllbuf[4] = bs; - return 0; + return 5; } static struct mt352_config advbt771_samsung_tdtc9251dh0_config = { .demod_address = 0x0f, .demod_init = advbt771_samsung_tdtc9251dh0_demod_init, - .pll_set = advbt771_samsung_tdtc9251dh0_pll_set, }; static struct dst_config dst_config = { @@ -455,7 +460,7 @@ static struct or51211_config or51211_config = { .sleep = or51211_sleep, }; -static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; u8 buf[4]; @@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten else return -EINVAL; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(card->i2c_adapter, &msg, 1); return 0; } @@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten static struct nxt6000_config vp3021_alps_tded4_config = { .demod_address = 0x0a, .clock_inversion = 1, - .pll_set = vp3021_alps_tded4_pll_set, }; static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe) @@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe) return 0; } -static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; struct dvb_ofdm_parameters *op = ¶ms->u.ofdm; + if (buf_len < 5) + return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - pllbuf[0] = 0xc2; + pllbuf[0] = 0x61; pllbuf[1] = (div >> 8) & 0x7F; pllbuf[2] = div & 0xFF; pllbuf[3] = 0x85; @@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten if (op->bandwidth == 8) pllbuf[4] |= 0x04; - return 0; + return 5; } static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt) @@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt) static struct mt352_config digitv_alps_tded4_config = { .demod_address = 0x0a, .demod_init = digitv_alps_tded4_demod_init, - .pll_set = digitv_alps_tded4_pll_set, }; -static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; - int err; - - dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0); - dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", - __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); - if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) { - printk(KERN_WARNING "dvb-bt8xx: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - /* Set the Auxiliary Byte. */ - buf[2] &= ~0x20; - buf[2] |= 0x18; - buf[3] = 0x50; - i2c_transfer(card->i2c_adapter, &msg, 1); - - return 0; + return lg_h06xf_pll_set(fe, card->i2c_adapter, params); } static struct lgdt330x_config tdvs_tua6034_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ - .pll_set = tdvs_tua6034_pll_set, }; static void lgdt330x_reset(struct dvb_bt8xx_card *bt) @@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) switch(type) { case BTTV_BOARD_DVICO_DVBT_LITE: card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); + + if (card->fe == NULL) + card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config, + card->i2c_adapter); + if (card->fe != NULL) { - card->fe->ops->info.frequency_min = 174000000; - card->fe->ops->info.frequency_max = 862000000; + card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs; + card->fe->ops.info.frequency_min = 174000000; + card->fe->ops.info.frequency_max = 862000000; } break; case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: lgdt330x_reset(card); card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); - if (card->fe != NULL) + if (card->fe != NULL) { + card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; dprintk ("dvb_bt8xx: lgdt330x detected\n"); + } break; case BTTV_BOARD_NEBULA_DIGITV: @@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) digitv_alps_tded4_reset(card); card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter); if (card->fe != NULL) { + card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params; dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n"); break; } @@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) digitv_alps_tded4_reset(card); card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter); - if (card->fe != NULL) + if (card->fe != NULL) { + card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs; dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n"); + } break; case BTTV_BOARD_AVDVBT_761: card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); + if (card->fe) { + card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params; + } break; case BTTV_BOARD_AVDVBT_771: card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); if (card->fe != NULL) { - card->fe->ops->info.frequency_min = 174000000; - card->fe->ops->info.frequency_max = 862000000; + card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs; + card->fe->ops.info.frequency_min = 174000000; + card->fe->ops.info.frequency_max = 862000000; } break; @@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) case BTTV_BOARD_PINNACLESAT: card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter); + if (card->fe) { + card->fe->ops.tuner_ops.init = pinnsat_tuner_init; + card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep; + card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params; + } break; case BTTV_BOARD_PC_HDTV: @@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) else if (dvb_register_frontend(&card->dvb_adapter, card->fe)) { printk("dvb-bt8xx: Frontend registration failed!\n"); - if (card->fe->ops->release) - card->fe->ops->release(card->fe); + if (card->fe->ops.release) + card->fe->ops.release(card->fe); card->fe = NULL; } } @@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) { int result; - if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) { + if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) { printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result); return result; } diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 00dd9fa54c8..4745a9017a1 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,6 +37,8 @@ #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" +#include "lg_h06xf.h" +#include "zl10353.h" struct dvb_bt8xx_card { struct mutex lock; |