diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/dvb/b2c2/skystar2.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/mt352.c | 522 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/mt352.h | 179 |
3 files changed, 526 insertions, 181 deletions
diff --git a/linux/drivers/media/dvb/b2c2/skystar2.c b/linux/drivers/media/dvb/b2c2/skystar2.c index d2a2bf350..216e697ca 100644 --- a/linux/drivers/media/dvb/b2c2/skystar2.c +++ b/linux/drivers/media/dvb/b2c2/skystar2.c @@ -294,10 +294,10 @@ static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); - /* allow only the mt312 and stv0299 frontends to access the bus */ - if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && (msgs[i].addr != 0x61)) { + /* allow only the mt312, mt352 and stv0299 frontends to access the bus */ + if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && + (msgs[i].addr != 0x61) && (msgs[i].addr != 0x0f)) { up(&tmp->i2c_sem); - return -EREMOTEIO; } } diff --git a/linux/drivers/media/dvb/frontends/mt352.c b/linux/drivers/media/dvb/frontends/mt352.c index 21079b606..ae5027292 100644 --- a/linux/drivers/media/dvb/frontends/mt352.c +++ b/linux/drivers/media/dvb/frontends/mt352.c @@ -7,6 +7,11 @@ * AVerMedia AVerTV DVB-T 771 support by * Wolfram Joost <dbox2@frokaschwei.de> * + * Support for Samsung TDTC9251DH01C(M) tuner + * + * Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it> + * Amauri Celani <acelani@essegi.net> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -29,12 +34,10 @@ #include <linux/delay.h> #include "dvb_frontend.h" +#include "mt352.h" -#define I2C_MT352_ADDR 0x0f -#define I2C_TUNER_ADDR 0xc2 - -#define CARD_UNKNOWN 0x00 -#define CARD_AVDVBT771 0x01 +static int force_card = -1; +static u32 card_type = -1; #define mt352_write(ibuf, ilen) \ do { \ @@ -42,27 +45,75 @@ do { \ .buf = ibuf, .len = ilen }; \ int err = i2c->xfer(i2c, &msg, 1); \ if (err != 1) { \ - printk(KERN_WARNING \ + printk(KERN_WARNING \ "mt352_write() failed (err = %d)!\n", err); \ return err; \ } \ } while (0) +static struct _tuner_info tuner_info [] = { + //TUA6034 tuner + { + .fe_frequency_min = 174000000, + .fe_frequency_max = 862000000, + .fe_frequency_stepsize = 166667, + .coderate_hp_shift = 9, + .coderate_lp_shift = 6, + .constellation_shift = 14, + .tx_mode_shift = 1, + .guard_interval_shift = 3, + .hierarchy_shift = 12, + .read_reg_flag = I2C_M_NOSTART, + .mt352_init = mt352_init_TUA6034, + .mt352_charge_pump = mt352_cp_TUA6034, + .mt352_band_select = mt352_bs_TUA6034 + }, + //AVERMEDIA 771 board + { + .fe_frequency_min = 174000000, + .fe_frequency_max = 862000000, + .fe_frequency_stepsize = 83333, + .coderate_hp_shift = 7, + .coderate_lp_shift = 4, + .constellation_shift = 13, + .tx_mode_shift = 0, + .guard_interval_shift = 2, + .hierarchy_shift = 10, + .read_reg_flag = I2C_M_NOSTART, + .mt352_init = mt352_init_AVERMEDIA771, + .mt352_charge_pump = mt352_cp_AVERMEDIA771, + .mt352_band_select = mt352_bs_AVERMEDIA771 + }, + //TDTC9251DH01C tuner + { + .fe_frequency_min = 474000000, + .fe_frequency_max = 858000000, + .fe_frequency_stepsize = 166667, + .coderate_hp_shift = 9, + .coderate_lp_shift = 6, + .constellation_shift = 4, + .tx_mode_shift = 1, + .guard_interval_shift = 3, + .hierarchy_shift = 12, + .read_reg_flag = 0, + .mt352_init = mt352_init_TDTC9251DH01C, + .mt352_charge_pump = mt352_cp_TDTC9251DH01C, + .mt352_band_select = mt352_bs_TDTC9251DH01C + } +}; -#define msb(x) (((x) >> 8) & 0xff) -#define lsb(x) ((x) & 0xff) static struct dvb_frontend_info mt352_info = { - .name = "DVB-T Zarlink MT352 demodulator driver", - .type = FE_OFDM, - .frequency_min = 174000000, /* NIM of AV771 starts at 50MHz */ - .frequency_max = 862000000, - .frequency_stepsize = 83333, + .name = "DVB-T Zarlink MT352 demodulator driver", + .type = FE_OFDM, /* - .frequency_tolerance = 0, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - .symbol_rate_tolerance = ???, + .frequency_min = 0, + .frequency_max = 0, + .frequency_stepsize = 0, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = ???, */ .notifier_delay = 0, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | @@ -74,8 +125,170 @@ static struct dvb_frontend_info mt352_info = { FE_CAN_MUTE_TS }; -int mt352_detect_avermedia_771(struct dvb_i2c_bus *i2c) +static int mt352_init_TUA6034(struct dvb_i2c_bus *i2c) +{ + static u8 mt352_reset [] = { RESET, 0x80 }; + static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; + static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x19, 0xa0 }; + static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 }; + + mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(mt352_reset, sizeof(mt352_reset)); + mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl)); + + mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); + + return 0; +} + +static int mt352_init_AVERMEDIA771(struct dvb_i2c_bus *i2c) +{ + static u8 mt352_reset [] = { RESET, 0x80 }; + static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; + static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x10, 0x23, 0x00, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x40, 0x40 }; + static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 }; + static u8 mt352_av771_extra[] = { 0xB5, 0x7A }; + + mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(mt352_reset, sizeof(mt352_reset)); + mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl)); + + mt352_write(mt352_agc_cfg,sizeof(mt352_agc_cfg)); + udelay(2000); + mt352_write(mt352_av771_extra,sizeof(mt352_av771_extra)); + + return 0; +} + +static int mt352_init_TDTC9251DH01C(struct dvb_i2c_bus *i2c) +{ + static u8 mt352_reset [] = { RESET, 0x80 }; + static u8 mt352_clock_config [] = { CLOCK_CTL, 0x10, 0x2d }; + static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x28, 0xa1 }; + static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 }; + + mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(mt352_reset, sizeof(mt352_reset)); + mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl)); + + mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); + + return 0; +} + +static unsigned char mt352_cp_TUA6034(u32 freq) +{ + unsigned char cp = 0; + + if (freq < 542) + cp = 0xbe; + else if (freq < 830) + cp = 0xf6; + else + cp = 0xfe; + + return cp; +} + +static unsigned char mt352_cp_AVERMEDIA771(u32 freq) +{ + unsigned char cp = 0; + + if (freq < 150) + cp = 0xB4; + else if (freq < 173) + cp = 0xBC; + else if (freq < 250) + cp = 0xB4; + else if (freq < 400) + cp = 0xBC; + else if (freq < 420) + cp = 0xF4; + else if (freq < 470) + cp = 0xFC; + else if (freq < 600) + cp = 0xBC; + else if (freq < 730) + cp = 0xF4; + else + cp = 0xFC; + + return cp; +} + +static unsigned char mt352_cp_TDTC9251DH01C(u32 freq) +{ + return(0xcc); +} + +static unsigned char mt352_bs_TUA6034(u32 freq) +{ + unsigned char bs = 0; + + if (freq < 250) + bs = 0x01; + else + bs = 0x08; + + return bs; +} + +static unsigned char mt352_bs_AVERMEDIA771(u32 freq) +{ + unsigned char bs = 0; + + if (freq < 150) + bs = 0x01; + else if (freq < 173) + bs = 0x01; + else if (freq < 250) + bs = 0x02; + else if (freq < 400) + bs = 0x02; + else if (freq < 420) + bs = 0x02; + else if (freq < 470) + bs = 0x02; + else if (freq < 600) + bs = 0x08; + else if (freq < 730) + bs = 0x08; + else + bs = 0x08; + + return bs; +} + +static unsigned char mt352_bs_TDTC9251DH01C(u32 freq) +{ + unsigned char bs = 0; + + if ((freq >= 48) && (freq <= 154)) /* low band */ + bs = 0x09; + + if ((freq >= 161) && (freq <= 439)) /* medium band */ + bs = 0x0a; + + if ((freq >= 447) && (freq <= 863)) /* high band */ + bs = 0x08; + + return bs; +} + + +static int mt352_detect_avermedia_771(struct dvb_i2c_bus *i2c) { + int i; u8 reg; u8 id[4]; const u8 pciid[4] = { 0x07, 0x71, 0x14, 0x61 }; @@ -92,8 +305,7 @@ int mt352_detect_avermedia_771(struct dvb_i2c_bus *i2c) .flags = I2C_M_RD, .len = 1 } - }; - int i; + }; for (i = 0; i < 4; i++) { @@ -108,50 +320,49 @@ int mt352_detect_avermedia_771(struct dvb_i2c_bus *i2c) return *((u32 *) id) == *((u32 *) pciid); } -int mt352_init (struct dvb_i2c_bus *i2c, u32 card_type) +static int mt352_detect_tdtc9251dh01c(struct dvb_i2c_bus *i2c) +{ + /* detection code must be written */ + + /* for Airstar2 DVB-T checking the PCI ID */ + /* is not enought because the one reported from */ + /* lspci is the one of Skystar2 */ + + if (force_card == 2) + return(1); + else + return(0); +} + +static int mt352_detect_tua6034(struct dvb_i2c_bus *i2c) +{ + /* detection code must be written */ + if (force_card == 0) + return(1); + else + return(0); +} + +static int mt352_init(struct dvb_i2c_bus *i2c) { /** * all register write sequence have the register address of the * first register in the first byte, thenafter the value to write * into this and the following registers. - */ - static u8 mt352_reset [] = { 0x50, 0x80 }; - static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d }; - static u8 mt352_adc_ctl_1_cfg [] = { 0x8e, 0x40 }; - static u8 mt352_agc_cfg [] = { 0x67, 0x19, 0xa0 }; - static u8 mt352_acq_ctl [] = { 0x53, 0x50 }; - - static u8 mt352_agc_cfg_av771 [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static u8 mt352_av771_extra[] = { 0xB5, 0x7A }; - /** + * + * * We only write non-default settings, all default settings are * restored by the full mt352_reset sequence. - */ - mt352_write(mt352_clock_config, sizeof(mt352_clock_config)); - udelay(2000); - mt352_write(mt352_reset, sizeof(mt352_reset)); - mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl)); - if (card_type == CARD_AVDVBT771) - { - mt352_write(mt352_agc_cfg_av771,sizeof(mt352_agc_cfg_av771)); - udelay(2000); - mt352_write(mt352_av771_extra,sizeof(mt352_av771_extra)); - } - else - { - /** - * The optimal AGC target value and slope might vary from tuner - * type to tuner type, so check whether you need to adjust this one... - */ - mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg)); - } + * + * + * The optimal AGC target value and slope might vary from tuner + * type to tuner type, so check whether you need to adjust this one... + **/ - return 0; + return(MT352_INIT(i2c)); } -int mt352_sleep(struct dvb_i2c_bus *i2c) +static int mt352_sleep(struct dvb_i2c_bus *i2c) { static u8 mt352_softdown[] = { 0x89, 0x20, 0x08 }; @@ -160,27 +371,27 @@ int mt352_sleep(struct dvb_i2c_bus *i2c) return 0; } -int mt352_set_parameters (struct dvb_i2c_bus *i2c, - struct dvb_frontend_parameters *param, u32 card_type) +static int mt352_set_parameters(struct dvb_i2c_bus *i2c, + struct dvb_frontend_parameters *param) { unsigned char buf[14]; unsigned int tps = 0; struct dvb_ofdm_parameters *op = ¶m->u.ofdm; - u32 freq = param->frequency / 1000; + u32 freq = param->frequency / 1000000; uint16_t tmp; switch (op->code_rate_HP) { case FEC_2_3: - tps = (1 << 7); + tps |= (1 << CODERATE_HP_SHIFT); break; case FEC_3_4: - tps = (2 << 7); + tps |= (2 << CODERATE_HP_SHIFT); break; case FEC_5_6: - tps = (3 << 7); + tps |= (3 << CODERATE_HP_SHIFT); break; case FEC_7_8: - tps = (4 << 7); + tps |= (4 << CODERATE_HP_SHIFT); break; case FEC_1_2: case FEC_AUTO: @@ -191,16 +402,16 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, switch (op->code_rate_LP) { case FEC_2_3: - tps |= (1 << 4); + tps |= (1 << CODERATE_LP_SHIFT); break; case FEC_3_4: - tps |= (2 << 4); + tps |= (2 << CODERATE_LP_SHIFT); break; case FEC_5_6: - tps |= (3 << 4); + tps |= (3 << CODERATE_LP_SHIFT); break; case FEC_7_8: - tps |= (4 << 4); + tps |= (4 << CODERATE_LP_SHIFT); break; case FEC_1_2: case FEC_AUTO: @@ -214,10 +425,10 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, break; case QAM_AUTO: case QAM_16: - tps |= (1 << 13); + tps |= (1 << CONSTELLATION_SHIFT); break; case QAM_64: - tps |= (2 << 13); + tps |= (2 << CONSTELLATION_SHIFT); break; default: return -EINVAL; @@ -228,7 +439,7 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, case TRANSMISSION_MODE_AUTO: break; case TRANSMISSION_MODE_8K: - tps |= (1 << 0); + tps |= (1 << TX_MODE_SHIFT); break; default: return -EINVAL; @@ -239,13 +450,13 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, case GUARD_INTERVAL_AUTO: break; case GUARD_INTERVAL_1_16: - tps |= (1 << 2); + tps |= (1 << GUARD_INTERVAL_SHIFT); break; case GUARD_INTERVAL_1_8: - tps |= (2 << 2); + tps |= (2 << GUARD_INTERVAL_SHIFT); break; case GUARD_INTERVAL_1_4: - tps |= (3 << 2); + tps |= (3 << GUARD_INTERVAL_SHIFT); break; default: return -EINVAL; @@ -256,20 +467,20 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, case HIERARCHY_NONE: break; case HIERARCHY_1: - tps |= (1 << 10); + tps |= (1 << HIERARCHY_SHIFT); break; case HIERARCHY_2: - tps |= (2 << 10); + tps |= (2 << HIERARCHY_SHIFT); break; case HIERARCHY_4: - tps |= (3 << 10); + tps |= (3 << HIERARCHY_SHIFT); break; default: return -EINVAL; } - buf[0] = 0x51; /* TPS_GIVEN_1 and following registers */ + buf[0] = TPS_GIVEN_1; /* TPS_GIVEN_1 and following registers */ buf[1] = msb(tps); /* TPS_GIVEN_(1|0) */ buf[2] = lsb(tps); @@ -291,6 +502,9 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, buf[5] = 0xb7; } + buf[6] = 0x31; /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */ + buf[7] = 0x05; /* see MT352 Design Manual page 32 for details */ + buf[8] = I2C_TUNER_ADDR; /** @@ -300,78 +514,13 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, /* here we assume 1/6MHz == 166.66kHz stepsize */ #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ - tmp = (3 * freq) / 500 + IF_FREQUENCYx6; + tmp = 6 * freq + IF_FREQUENCYx6; + buf[9] = msb(tmp); /* CHAN_START_(1|0) */ buf[10] = lsb(tmp); - buf[6] = 0x31; /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */ - buf[7] = 0x05; /* see MT352 Design Manual page 32 for details */ - - if (card_type == CARD_AVDVBT771) - { - if (freq < 150000) - { - buf[11] = 0xB4; - buf[12] = 0x01; - } - else if (freq < 173000) - { - buf[11] = 0xBC; - buf[12] = 0x01; - } - else if (freq < 250000) - { - buf[11] = 0xB4; - buf[12] = 0x02; - } - else if (freq < 400000) - { - buf[11] = 0xBC; - buf[12] = 0x02; - } - else if (freq < 420000) - { - buf[11] = 0xF4; - buf[12] = 0x02; - } - else if (freq < 470000) - { - buf[11] = 0xFC; - buf[12] = 0x02; - } - else if (freq < 600000) - { - buf[11] = 0xBC; - buf[12] = 0x08; - } - else if (freq < 730000) - { - buf[11] = 0xF4; - buf[12] = 0x08; - } - else - { - buf[11] = 0xFC; - buf[12] = 0x08; - } - } - else - { - - printk (KERN_WARNING "buf9,10: %02x %02x\n", buf[9], buf[10]); - - if (freq < 542000) - buf[11] = 0xbe; /* CONT_1, charge pump byte */ - else if (freq < 830000) - buf[11] = 0xf6; - else - buf[11] = 0xfe; - - if (freq < 250000) /* VHF, freq < 250MHz */ - buf[12] = 0x01; /* CONT_0, bandswitch byte */ - else - buf[12] = 0x08; - } + buf[11] = MT352_CHARGE_PUMP(freq); + buf[12] = MT352_BAND_SELECT(freq); buf[13] = 0x01; /* TUNER_GO!! */ @@ -380,13 +529,13 @@ int mt352_set_parameters (struct dvb_i2c_bus *i2c, return 0; } -static u8 mt352_read_register (struct dvb_i2c_bus *i2c, u8 reg) +static u8 mt352_read_register(struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; struct i2c_msg msg [] = { { .addr = I2C_MT352_ADDR, - .flags = I2C_M_NOSTART, + .flags = READ_REG_FLAG, .buf = b0, .len = 1 }, { .addr = I2C_MT352_ADDR, .flags = I2C_M_RD, @@ -402,13 +551,12 @@ static u8 mt352_read_register (struct dvb_i2c_bus *i2c, u8 reg) } -int mt352_get_parameters (struct dvb_i2c_bus *i2c, - struct dvb_frontend_parameters *param, u32 card_type) +static int mt352_get_parameters(struct dvb_i2c_bus *i2c, + struct dvb_frontend_parameters *param) { u16 tps; u16 div; u8 trl; - struct dvb_ofdm_parameters *op = ¶m->u.ofdm; static const u8 tps_fec_to_api[8] = { @@ -430,9 +578,9 @@ int mt352_get_parameters (struct dvb_i2c_bus *i2c, /* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because * the mt352 sometimes works with the wrong parameters */ - tps = (mt352_read_register(i2c,0x1E) << 8) | mt352_read_register(i2c,0x1F); - div = (mt352_read_register(i2c,0x59) << 8) | mt352_read_register(i2c,0x5A); - trl = mt352_read_register(i2c,0x54); + tps = (mt352_read_register(i2c, TPS_RECEIVED_1) << 8) | mt352_read_register(i2c, TPS_RECEIVED_0); + div = (mt352_read_register(i2c, CHAN_START_1) << 8) | mt352_read_register(i2c, CHAN_START_0); + trl = mt352_read_register(i2c, TRL_NOMINAL_RATE_1); op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7]; op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7]; @@ -508,16 +656,19 @@ int mt352_get_parameters (struct dvb_i2c_bus *i2c, op->bandwidth = BANDWIDTH_6_MHZ; } - param->inversion = INVERSION_OFF; + + if (mt352_read_register(i2c, STATUS_2) & 0x02) + param->inversion = INVERSION_OFF; + else + param->inversion = INVERSION_ON; return 0; } -static int mt352_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int mt352_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dvb_i2c_bus *i2c = fe->i2c; - u32 card_type = (u32) fe->data; u8 r,snr; fe_status_t *status; u16 signal; @@ -531,7 +682,7 @@ static int mt352_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) case FE_READ_STATUS: status = arg; *status = 0; - r = mt352_read_register (i2c, 0x00); + r = mt352_read_register (i2c, STATUS_0); if (r & (1 << 4)) *status = FE_HAS_CARRIER; if (r & (1 << 1)) @@ -539,45 +690,45 @@ static int mt352_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if (r & (1 << 5)) *status |= FE_HAS_LOCK; - r = mt352_read_register (i2c, 0x01); + r = mt352_read_register (i2c, STATUS_1); if (r & (1 << 1)) *status |= FE_HAS_SYNC; - r = mt352_read_register (i2c, 0x03); + r = mt352_read_register (i2c, STATUS_3); if (r & (1 << 6)) *status |= FE_HAS_SIGNAL; break; case FE_READ_BER: - *((u32 *) arg) = (mt352_read_register (i2c, 0x0D) << 16) | - (mt352_read_register (i2c, 0x0E) << 8) | - (mt352_read_register (i2c, 0x0F)); + *((u32 *) arg) = (mt352_read_register (i2c, RS_ERR_CNT_2) << 16) | + (mt352_read_register (i2c, RS_ERR_CNT_1) << 8) | + (mt352_read_register (i2c, RS_ERR_CNT_0)); break; case FE_READ_SIGNAL_STRENGTH: - signal = (mt352_read_register (i2c, 0x12) << 8) | - (mt352_read_register (i2c, 0x13)); + signal = (mt352_read_register (i2c, AGC_GAIN_3) << 8) | + (mt352_read_register (i2c, AGC_GAIN_2)); *((u16*) arg) = ~signal; break; case FE_READ_SNR: - snr = mt352_read_register (i2c, 0x09); + snr = mt352_read_register (i2c, SNR); *((u16*) arg) = (snr << 8) | snr; break; case FE_READ_UNCORRECTED_BLOCKS: - *(u32*) arg = (mt352_read_register (i2c, 0x10) << 8) | - (mt352_read_register (i2c, 0x11)); + *(u32*) arg = (mt352_read_register (i2c, RS_UBC_1) << 8) | + (mt352_read_register (i2c, RS_UBC_0)); break; case FE_SET_FRONTEND: return mt352_set_parameters (i2c, - (struct dvb_frontend_parameters *) arg,card_type); + (struct dvb_frontend_parameters *) arg); case FE_GET_FRONTEND: return mt352_get_parameters (i2c, - (struct dvb_frontend_parameters *) arg,card_type); + (struct dvb_frontend_parameters *) arg); case FE_GET_TUNE_SETTINGS: fe_tune_settings = (struct dvb_frontend_tune_settings *) arg; @@ -590,7 +741,7 @@ static int mt352_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) return mt352_sleep(i2c); case FE_INIT: - return mt352_init(i2c,card_type); + return mt352_init(i2c); default: return -EOPNOTSUPP; @@ -600,26 +751,38 @@ static int mt352_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) } -static int mt352_attach (struct dvb_i2c_bus *i2c, void **data) +static int mt352_attach(struct dvb_i2c_bus *i2c, void **data) { - u32 card_type; static u8 mt352_reset_attach [] = { 0x50, 0xC0 }; - if (mt352_read_register(i2c, 0x7f) == 0x13) + /* set the proper MT352 frequency range */ + mt352_info.frequency_min = FE_FREQ_MIN; + mt352_info.frequency_max = FE_FREQ_MAX; + mt352_info.frequency_stepsize = FE_FREQ_STEPSIZE; + + if (mt352_read_register(i2c, CHIP_ID) == ID_MT352) { if (mt352_detect_avermedia_771(i2c)) { card_type = CARD_AVDVBT771; } + else if (mt352_detect_tdtc9251dh01c(i2c)) + { + card_type = CARD_TDTC9251DH01C; + } + else if (mt352_detect_tua6034(i2c)) + { + card_type = CARD_TUA6034; + } else { - card_type = CARD_UNKNOWN; + return -ENODEV; } /* Do a "hard" reset */ mt352_write(mt352_reset_attach,sizeof(mt352_reset_attach)); /* Don't waste power and (maybe) pci bandwidth */ mt352_sleep(i2c); - return dvb_register_frontend(mt352_ioctl, i2c, (void *) card_type, + return dvb_register_frontend(mt352_ioctl, i2c, NULL, &mt352_info); } @@ -627,20 +790,20 @@ static int mt352_attach (struct dvb_i2c_bus *i2c, void **data) } -static void mt352_detach (struct dvb_i2c_bus *i2c, void *data) +static void mt352_detach(struct dvb_i2c_bus *i2c, void *data) { mt352_sleep(i2c); dvb_unregister_frontend(mt352_ioctl, i2c); } -static int __init init_mt352 (void) +static int __init init_mt352(void) { return dvb_register_i2c_device(NULL, mt352_attach, mt352_detach); } -static void __exit exit_mt352 (void) +static void __exit exit_mt352(void) { dvb_unregister_i2c_device(mt352_attach); } @@ -651,5 +814,8 @@ module_exit(exit_mt352); MODULE_DESCRIPTION("DVB-T MT352 Zarlink"); -MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); +MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso"); MODULE_LICENSE("GPL"); + +MODULE_PARM(force_card, "i"); +MODULE_PARM_DESC(force_card, "<0: TUA6034 -- 1:AVDVBT771 -- 2: TDTC9251DH01C>"); diff --git a/linux/drivers/media/dvb/frontends/mt352.h b/linux/drivers/media/dvb/frontends/mt352.h new file mode 100644 index 000000000..4a41ee6e0 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/mt352.h @@ -0,0 +1,179 @@ +/* + * Driver for Zarlink DVB-T MT352 demodulator + * + * Written by Holger Waechtler <holger@qanu.de> + * and Daniel Mack <daniel@qanu.de> + * + * Support for Samsung TDTC9251DH01C(M) tuner + * + * Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it> + * Amauri Celani <acelani@essegi.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef _MT352_ +#define _MT352_ + +#define I2C_MT352_ADDR 0x0f +#define I2C_TUNER_ADDR 0xc2 +#define ID_MT352 0x13 + +#define CARD_TUA6034 0x00 +#define CARD_AVDVBT771 0x01 +#define CARD_TDTC9251DH01C 0x02 + +#define msb(x) (((x) >> 8) & 0xff) +#define lsb(x) ((x) & 0xff) + +enum mt352_reg_addr { + STATUS_0 = 0x00, + STATUS_1 = 0x01, + STATUS_2 = 0x02, + STATUS_3 = 0x03, + STATUS_4 = 0x04, + INTERRUPT_0 = 0x05, + INTERRUPT_1 = 0x06, + INTERRUPT_2 = 0x07, + INTERRUPT_3 = 0x08, + SNR = 0x09, + VIT_ERR_CNT_2 = 0x0A, + VIT_ERR_CNT_1 = 0x0B, + VIT_ERR_CNT_0 = 0x0C, + RS_ERR_CNT_2 = 0x0D, + RS_ERR_CNT_1 = 0x0E, + RS_ERR_CNT_0 = 0x0F, + RS_UBC_1 = 0x10, + RS_UBC_0 = 0x11, + AGC_GAIN_3 = 0x12, + AGC_GAIN_2 = 0x13, + AGC_GAIN_1 = 0x14, + AGC_GAIN_0 = 0x15, + FREQ_OFFSET_2 = 0x17, + FREQ_OFFSET_1 = 0x18, + FREQ_OFFSET_0 = 0x19, + TIMING_OFFSET_1 = 0x1A, + TIMING_OFFSET_0 = 0x1B, + CHAN_FREQ_1 = 0x1C, + CHAN_FREQ_0 = 0x1D, + TPS_RECEIVED_1 = 0x1E, + TPS_RECEIVED_0 = 0x1F, + TPS_CURRENT_1 = 0x20, + TPS_CURRENT_0 = 0x21, + TPS_CELL_ID_1 = 0x22, + TPS_CELL_ID_0 = 0x23, + TPS_MISC_DATA_2 = 0x24, + TPS_MISC_DATA_1 = 0x25, + TPS_MISC_DATA_0 = 0x26, + RESET = 0x50, + TPS_GIVEN_1 = 0x51, + TPS_GIVEN_0 = 0x52, + ACQ_CTL = 0x53, + TRL_NOMINAL_RATE_1 = 0x54, + TRL_NOMINAL_RATE_0 = 0x55, + INPUT_FREQ_1 = 0x56, + INPUT_FREQ_0 = 0x57, + TUNER_ADDR = 0x58, + CHAN_START_1 = 0x59, + CHAN_START_0 = 0x5A, + CONT_1 = 0x5B, + CONT_0 = 0x5C, + TUNER_GO = 0x5D, + STATUS_EN_0 = 0x5F, + STATUS_EN_1 = 0x60, + INTERRUPT_EN_0 = 0x61, + INTERRUPT_EN_1 = 0x62, + INTERRUPT_EN_2 = 0x63, + INTERRUPT_EN_3 = 0x64, + AGC_TARGET = 0x67, + AGC_CTL = 0x68, + CAPT_RANGE = 0x75, + SNR_SELECT_1 = 0x79, + SNR_SELECT_0 = 0x7A, + RS_ERR_PER_1 = 0x7C, + RS_ERR_PER_0 = 0x7D, + CHIP_ID = 0x7F, + CHAN_STOP_1 = 0x80, + CHAN_STOP_0 = 0x81, + CHAN_STEP_1 = 0x82, + CHAN_STEP_0 = 0x83, + FEC_LOCK_TIME = 0x85, + OFDM_LOCK_TIME = 0x86, + ACQ_DELAY = 0x87, + SCAN_CTL = 0x88, + CLOCK_CTL = 0x89, + CONFIG = 0x8A, + MCLK_RATIO = 0x8B, + GPP_CTL = 0x8C, + ADC_CTL_1 = 0x8E, + ADC_CTL_0 = 0x8F +}; + +struct _tuner_info { + __u32 fe_frequency_min; +#define FE_FREQ_MIN tuner_info[card_type].fe_frequency_min + + __u32 fe_frequency_max; +#define FE_FREQ_MAX tuner_info[card_type].fe_frequency_max + + __u32 fe_frequency_stepsize; //verificare se u32 e' corretto +#define FE_FREQ_STEPSIZE tuner_info[card_type].fe_frequency_stepsize + + __u32 coderate_hp_shift; //verificare se u32 giusto +#define CODERATE_HP_SHIFT tuner_info[card_type].coderate_hp_shift + + __u32 coderate_lp_shift; +#define CODERATE_LP_SHIFT tuner_info[card_type].coderate_lp_shift + + int constellation_shift; +#define CONSTELLATION_SHIFT tuner_info[card_type].constellation_shift + + int tx_mode_shift; +#define TX_MODE_SHIFT tuner_info[card_type].tx_mode_shift + + int guard_interval_shift; +#define GUARD_INTERVAL_SHIFT tuner_info[card_type].guard_interval_shift + + int hierarchy_shift; +#define HIERARCHY_SHIFT tuner_info[card_type].hierarchy_shift + + int read_reg_flag; +#define READ_REG_FLAG tuner_info[card_type].read_reg_flag + + int (* mt352_init) (struct dvb_i2c_bus *i2c); +#define MT352_INIT tuner_info[card_type].mt352_init + + unsigned char (* mt352_charge_pump) (u32 freq); +#define MT352_CHARGE_PUMP tuner_info[card_type].mt352_charge_pump + + unsigned char (* mt352_band_select) (u32 freq); +#define MT352_BAND_SELECT tuner_info[card_type].mt352_band_select +}; + +static int mt352_init_TUA6034(struct dvb_i2c_bus *i2c); +static int mt352_init_AVERMEDIA771(struct dvb_i2c_bus *i2c); +static int mt352_init_TDTC9251DH01C(struct dvb_i2c_bus *i2c); +static unsigned char mt352_cp_TUA6034(u32 freq); +static unsigned char mt352_cp_AVERMEDIA771(u32 freq); +static unsigned char mt352_cp_TDTC9251DH01C(u32 freq); +static unsigned char mt352_bs_TUA6034(u32 freq); +static unsigned char mt352_bs_AVERMEDIA771(u32 freq); +static unsigned char mt352_bs_TDTC9251DH01C(u32 freq); +static int mt352_detect_avermedia_771(struct dvb_i2c_bus *i2c); +static int mt352_detect_tdtc9251dh01c(struct dvb_i2c_bus *i2c); +static int mt352_detect_tua6034(struct dvb_i2c_bus *i2c); + +#endif /* _MT352_ */ |