diff options
author | Michael Hunold <devnull@localhost> | 2004-08-09 11:11:59 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2004-08-09 11:11:59 +0000 |
commit | aa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0 (patch) | |
tree | f69a3066d76ac2afa40a6d85fec0887d683abbd0 /linux/drivers/media/dvb/frontends/ves1820.c | |
parent | f0e186adfa45c6d6fc266051e392c11510afe154 (diff) | |
download | mediapointer-dvb-s2-aa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0.tar.gz mediapointer-dvb-s2-aa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0.tar.bz2 |
- convert to kernel i2c
- whitespace and coding style cleanup
- temporarily removed the possibility to set the initial pwm value via module parameters
Diffstat (limited to 'linux/drivers/media/dvb/frontends/ves1820.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/ves1820.c | 660 |
1 files changed, 341 insertions, 319 deletions
diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 3008d985d..7bf168e85 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -32,60 +32,30 @@ #include "dvb_functions.h" #include "dvb_i2c.h" -#if 0 -#define dprintk(x...) printk(x) -#else -#define dprintk(x...) -#endif +/* I2C_DRIVERID_VES1820 is already defined in i2c-id.h */ +static int debug = 0; +#define dprintk if (debug) printk -#define MAX_UNITS 4 -static int pwm[MAX_UNITS] = { -1, -1, -1, -1 }; static int verbose; -/** - * since we need only a few bits to store internal state we don't allocate - * extra memory but use frontend->data as bitfield - */ +struct ves1820_state { + int pwm; + u8 reg0; + int tuner; + u8 demod_addr; + struct i2c_adapter *i2c; + struct dvb_adapter *dvb; +}; -#define SET_PWM(data,pwm) do { \ - long d = (long)data; \ - d &= ~0xff; \ - d |= pwm; \ - data = (void *)d; \ -} while (0) - -#define SET_REG0(data,reg0) do { \ - long d = (long)data; \ - d &= ~(0xff << 8); \ - d |= reg0 << 8; \ - data = (void *)d; \ -} while (0) - -#define SET_TUNER(data,type) do { \ - long d = (long)data; \ - d &= ~(0xff << 16); \ - d |= type << 16; \ - data = (void *)d; \ -} while (0) - -#define SET_DEMOD_ADDR(data,type) do { \ - long d = (long)data; \ - d &= ~(0xff << 24); \ - d |= type << 24; \ - data = (void *)d; \ -} while (0) - -#define GET_PWM(data) ((u8) ((long) data & 0xff)) -#define GET_REG0(data) ((u8) (((long) data >> 8) & 0xff)) -#define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff)) -#define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff)) +/* possible ves1820 adresses */ +static u8 addr[] = { 0x61, 0x62 }; #if defined(CONFIG_DBOX2) #define XIN 69600000UL #define DISABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) #define ENABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) #define HAS_INVERSION(reg0) (reg0 & 0x20) -#else /* PCI cards */ +#else /* PCI cards */ #define XIN 57840000UL #define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) #define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) @@ -94,30 +64,29 @@ static int verbose; #define FIN (XIN >> 4) - - static struct dvb_frontend_info ves1820_info = { .name = "VES1820 based DVB-C frontend", .type = FE_QAM, .frequency_stepsize = 62500, .frequency_min = 51000000, .frequency_max = 858000000, - .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ + .symbol_rate_min = (XIN / 2) / 64, /* SACLK/64 == (XIN/2)/64 */ + .symbol_rate_max = (XIN / 2) / 4, /* SACLK/4 */ #if 0 - .frequency_tolerance = ???, - .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ + .frequency_tolerance = ? ? ?, + .symbol_rate_tolerance = ? ? ?, /* ppm *//* == 8% (spec p. 5) */ .notifier_delay = ?, #endif - .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO, + .caps = FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO | + FE_CAN_INVERSION_AUTO, }; - - -static u8 ves1820_inittab [] = -{ +static u8 ves1820_inittab[] = { 0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -127,79 +96,70 @@ static u8 ves1820_inittab [] = 0x00, 0x00, 0x00, 0x00, 0x40 }; - -static int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data) +static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data) { - u8 addr = GET_DEMOD_ADDR(fe->data); - u8 buf[] = { 0x00, reg, data }; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; - struct dvb_i2c_bus *i2c = fe->i2c; - int ret; + u8 buf[] = { 0x00, reg, data }; + struct i2c_msg msg = {.addr = state->demod_addr,.flags = 0,.buf = buf,.len = 3 }; + int ret; - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) - printk("DVB: VES1820(%d): %s, writereg error " - "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - fe->i2c->adapter->num, __FUNCTION__, reg, data, ret); + printk("ves1820: %s(): writereg error (reg == 0x%02x," + "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); dvb_delay(10); return (ret != 1) ? -EREMOTEIO : 0; } - -static u8 ves1820_readreg (struct dvb_frontend *fe, u8 reg) +static u8 ves1820_readreg(struct ves1820_state *state, u8 reg) { - u8 b0 [] = { 0x00, reg }; - u8 b1 [] = { 0 }; - u8 addr = GET_DEMOD_ADDR(fe->data); - struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 }, - { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - struct dvb_i2c_bus *i2c = fe->i2c; + u8 b0[] = { 0x00, reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + {.addr = state->demod_addr,.flags = 0,.buf = b0,.len = 2}, + {.addr = state->demod_addr,.flags = I2C_M_RD,.buf = b1,.len = 1} + }; int ret; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk("DVB: VES1820(%d): %s: readreg error (ret == %i)\n", - fe->i2c->adapter->num, __FUNCTION__, ret); + printk("ves1820: %s(): readreg error (reg == 0x%02x," + "ret == %i)\n", __FUNCTION__, reg, ret); return b1[0]; } - -static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4]) +static int tuner_write(struct ves1820_state *state, u8 addr, u8 data[4]) { - int ret; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; + int ret; + struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = data,.len = 4 }; - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); - if (ret != 1) - printk("DVB: VES1820(%d): %s: i/o error (ret == %i)\n", - i2c->adapter->num, __FUNCTION__, ret); + if (ret != 1) + printk("ves1820: %s(): i/o error (ret == %i)\n", __FUNCTION__, ret); - return (ret != 1) ? -EREMOTEIO : 0; + return (ret != 1) ? -EREMOTEIO : 0; } - /** * set up the downconverter frequency divisor for a * reference clock comparision frequency of 62.5 kHz. */ -static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq) +static int tuner_set_tv_freq(struct ves1820_state *state, u32 freq) { - u32 div, ifreq; - static u8 addr [] = { 0x61, 0x62 }; - static u8 byte3 [] = { 0x8e, 0x85 }; - int tuner_type = GET_TUNER(fe->data); - u8 buf [4]; + u32 div, ifreq; + static u8 byte3[] = { 0x8e, 0x85 }; + int tuner_type = state->tuner; + u8 buf[4]; - if (tuner_type == 0xff) /* PLL not reachable over i2c ... */ + if (tuner_type == 0xff) /* PLL not reachable over i2c ... */ return 0; - if (strstr (fe->i2c->adapter->name, "Technotrend") || - strstr (fe->i2c->adapter->name, "TT-Budget")) + if (strstr(state->i2c->name, "Technotrend") + || strstr(state->i2c->name, "TT-Budget")) ifreq = 35937500; else ifreq = 36125000; @@ -212,147 +172,147 @@ static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq) if (tuner_type == 1) { buf[2] |= (div >> 10) & 0x60; - buf[3] = (freq < 174000000 ? 0x88 : - freq < 470000000 ? 0x84 : 0x81); + buf[3] = (freq < 174000000 ? 0x88 : freq < 470000000 ? 0x84 : 0x81); } else { - buf[3] = (freq < 174000000 ? 0xa1 : - freq < 454000000 ? 0x92 : 0x34); + buf[3] = (freq < 174000000 ? 0xa1 : freq < 454000000 ? 0x92 : 0x34); } - return tuner_write (fe->i2c, addr[tuner_type], buf); + return tuner_write(state, addr[tuner_type], buf); } - -static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0, - fe_spectral_inversion_t inversion) +static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion) { - reg0 |= GET_REG0(fe->data) & 0x62; + reg0 |= state->reg0 & 0x62; if (INVERSION_ON == inversion) ENABLE_INVERSION(reg0); else if (INVERSION_OFF == inversion) DISABLE_INVERSION(reg0); - ves1820_writereg (fe, 0x00, reg0 & 0xfe); - ves1820_writereg (fe, 0x00, reg0 | 0x01); + ves1820_writereg(state, 0x00, reg0 & 0xfe); + ves1820_writereg(state, 0x00, reg0 | 0x01); /** * check lock and toggle inversion bit if required... */ - if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) { + if (INVERSION_AUTO == inversion && !(ves1820_readreg(state, 0x11) & 0x08)) { mdelay(50); - if (!(ves1820_readreg (fe, 0x11) & 0x08)) { + if (!(ves1820_readreg(state, 0x11) & 0x08)) { reg0 ^= 0x20; - ves1820_writereg (fe, 0x00, reg0 & 0xfe); - ves1820_writereg (fe, 0x00, reg0 | 0x01); + ves1820_writereg(state, 0x00, reg0 & 0xfe); + ves1820_writereg(state, 0x00, reg0 | 0x01); } } - SET_REG0(fe->data, reg0); + state->reg0 = reg0; return 0; } - -static int ves1820_init (struct dvb_frontend *fe) +static int ves1820_init(struct ves1820_state *state) { int i; - dprintk("DVB: VES1820(%d): init chip\n", fe->i2c->adapter->num); - - ves1820_writereg (fe, 0, 0); + ves1820_writereg(state, 0, 0); #if defined(CONFIG_DBOX2) ves1820_inittab[2] &= ~0x08; #endif - for (i=0; i<53; i++) - ves1820_writereg (fe, i, ves1820_inittab[i]); + for (i = 0; i < 53; i++) + ves1820_writereg(state, i, ves1820_inittab[i]); - ves1820_writereg (fe, 0x34, GET_PWM(fe->data)); + ves1820_writereg(state, 0x34, state->pwm); return 0; } - -static int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate) +static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) { - s32 BDR; - s32 BDRI; - s16 SFIL=0; - u16 NDEC = 0; - u32 tmp, ratio; + s32 BDR; + s32 BDRI; + s16 SFIL = 0; + u16 NDEC = 0; + u32 tmp, ratio; - if (symbolrate > XIN/2) - symbolrate = XIN/2; + if (symbolrate > XIN / 2) + symbolrate = XIN / 2; if (symbolrate < 500000) - symbolrate = 500000; - - if (symbolrate < XIN/16) NDEC = 1; - if (symbolrate < XIN/32) NDEC = 2; - if (symbolrate < XIN/64) NDEC = 3; + symbolrate = 500000; + + if (symbolrate < XIN / 16) + NDEC = 1; + if (symbolrate < XIN / 32) + NDEC = 2; + if (symbolrate < XIN / 64) + NDEC = 3; + + if (symbolrate < (u32) (XIN / 12.3)) + SFIL = 1; + if (symbolrate < (u32) (XIN / 16)) + SFIL = 0; + if (symbolrate < (u32) (XIN / 24.6)) + SFIL = 1; + if (symbolrate < (u32) (XIN / 32)) + SFIL = 0; + if (symbolrate < (u32) (XIN / 49.2)) + SFIL = 1; + if (symbolrate < (u32) (XIN / 64)) + SFIL = 0; + if (symbolrate < (u32) (XIN / 98.4)) + SFIL = 1; + + symbolrate <<= NDEC; + ratio = (symbolrate << 4) / FIN; + tmp = ((symbolrate << 4) % FIN) << 8; + ratio = (ratio << 8) + tmp / FIN; + tmp = (tmp % FIN) << 8; + ratio = (ratio << 8) + (tmp + FIN / 2) / FIN; + + BDR = ratio; + BDRI = (((XIN << 5) / symbolrate) + 1) / 2; + + if (BDRI > 0xFF) + BDRI = 0xFF; + + SFIL = (SFIL << 4) | ves1820_inittab[0x0E]; + + NDEC = (NDEC << 6) | ves1820_inittab[0x03]; + + ves1820_writereg(state, 0x03, NDEC); + ves1820_writereg(state, 0x0a, BDR & 0xff); + ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff); + ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f); + + ves1820_writereg(state, 0x0d, BDRI); + ves1820_writereg(state, 0x0e, SFIL); - if (symbolrate < (u32)(XIN/12.3)) SFIL = 1; - if (symbolrate < (u32)(XIN/16)) SFIL = 0; - if (symbolrate < (u32)(XIN/24.6)) SFIL = 1; - if (symbolrate < (u32)(XIN/32)) SFIL = 0; - if (symbolrate < (u32)(XIN/49.2)) SFIL = 1; - if (symbolrate < (u32)(XIN/64)) SFIL = 0; - if (symbolrate < (u32)(XIN/98.4)) SFIL = 1; - - symbolrate <<= NDEC; - ratio = (symbolrate << 4) / FIN; - tmp = ((symbolrate << 4) % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; - - BDR = ratio; - BDRI = (((XIN << 5) / symbolrate) + 1) / 2; - - if (BDRI > 0xFF) - BDRI = 0xFF; - - SFIL = (SFIL << 4) | ves1820_inittab[0x0E]; - - NDEC = (NDEC << 6) | ves1820_inittab[0x03]; - - ves1820_writereg (fe, 0x03, NDEC); - ves1820_writereg (fe, 0x0a, BDR&0xff); - ves1820_writereg (fe, 0x0b, (BDR>> 8)&0xff); - ves1820_writereg (fe, 0x0c, (BDR>>16)&0x3f); - - ves1820_writereg (fe, 0x0d, BDRI); - ves1820_writereg (fe, 0x0e, SFIL); - - return 0; + return 0; } - -static int ves1820_set_parameters (struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int ves1820_set_parameters(struct ves1820_state *state, struct dvb_frontend_parameters *p) { - static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 }; - static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 }; - static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 }; - static const u8 reg0x08 [] = { 162, 116, 67, 52, 35 }; - static const u8 reg0x09 [] = { 145, 150, 106, 126, 107 }; + static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 }; + static const u8 reg0x01[] = { 140, 140, 106, 100, 92 }; + static const u8 reg0x05[] = { 135, 100, 70, 54, 38 }; + static const u8 reg0x08[] = { 162, 116, 67, 52, 35 }; + static const u8 reg0x09[] = { 145, 150, 106, 126, 107 }; int real_qam = p->u.qam.modulation - QAM_16; if (real_qam < 0 || real_qam > 4) return -EINVAL; - tuner_set_tv_freq (fe, p->frequency); - ves1820_set_symbolrate (fe, p->u.qam.symbol_rate); - ves1820_writereg (fe, 0x34, GET_PWM(fe->data)); + tuner_set_tv_freq(state, p->frequency); + ves1820_set_symbolrate(state, p->u.qam.symbol_rate); + ves1820_writereg(state, 0x34, state->pwm); - ves1820_writereg (fe, 0x01, reg0x01[real_qam]); - ves1820_writereg (fe, 0x05, reg0x05[real_qam]); - ves1820_writereg (fe, 0x08, reg0x08[real_qam]); - ves1820_writereg (fe, 0x09, reg0x09[real_qam]); + ves1820_writereg(state, 0x01, reg0x01[real_qam]); + ves1820_writereg(state, 0x05, reg0x05[real_qam]); + ves1820_writereg(state, 0x08, reg0x08[real_qam]); + ves1820_writereg(state, 0x09, reg0x09[real_qam]); - ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion); + ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion); /* yes, this speeds things up: userspace reports lock in about 8 ms instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */ @@ -361,133 +321,127 @@ static int ves1820_set_parameters (struct dvb_frontend *fe, return 0; } - - -static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1820_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { - switch (cmd) { + struct ves1820_state *state = (struct ves1820_state *) fe->data; + + switch (cmd) { case FE_GET_INFO: - memcpy (arg, &ves1820_info, sizeof(struct dvb_frontend_info)); + memcpy(arg, &ves1820_info, sizeof(struct dvb_frontend_info)); break; - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; - int sync; + case FE_READ_STATUS: + { + fe_status_t *status = (fe_status_t *) arg; + int sync; - *status = 0; + *status = 0; - sync = ves1820_readreg (fe, 0x11); + sync = ves1820_readreg(state, 0x11); - if (sync & 1) - *status |= FE_HAS_SIGNAL; + if (sync & 1) + *status |= FE_HAS_SIGNAL; - if (sync & 2) - *status |= FE_HAS_CARRIER; + if (sync & 2) + *status |= FE_HAS_CARRIER; - if (sync & 2) /* XXX FIXME! */ - *status |= FE_HAS_VITERBI; + if (sync & 2) /* XXX FIXME! */ + *status |= FE_HAS_VITERBI; - if (sync & 4) - *status |= FE_HAS_SYNC; + if (sync & 4) + *status |= FE_HAS_SYNC; - if (sync & 8) - *status |= FE_HAS_LOCK; + if (sync & 8) + *status |= FE_HAS_LOCK; - break; - } + break; + } case FE_READ_BER: - { - u32 ber = ves1820_readreg(fe, 0x14) | - (ves1820_readreg(fe, 0x15) << 8) | - ((ves1820_readreg(fe, 0x16) & 0x0f) << 16); - *((u32*) arg) = 10 * ber; - break; - } + { + u32 ber = ves1820_readreg(state, 0x14) | + (ves1820_readreg(state, 0x15) << 8) | + ((ves1820_readreg(state, 0x16) & 0x0f) << 16); + *((u32 *) arg) = 10 * ber; + break; + } case FE_READ_SIGNAL_STRENGTH: - { - u8 gain = ves1820_readreg(fe, 0x17); - *((u16*) arg) = (gain << 8) | gain; - break; - } + { + u8 gain = ves1820_readreg(state, 0x17); + *((u16 *) arg) = (gain << 8) | gain; + break; + } case FE_READ_SNR: - { - u8 quality = ~ves1820_readreg(fe, 0x18); - *((u16*) arg) = (quality << 8) | quality; - break; - } + { + u8 quality = ~ves1820_readreg(state, 0x18); + *((u16 *) arg) = (quality << 8) | quality; + break; + } case FE_READ_UNCORRECTED_BLOCKS: - *((u32*) arg) = ves1820_readreg (fe, 0x13) & 0x7f; - if (*((u32*) arg) == 0x7f) - *((u32*) arg) = 0xffffffff; + *((u32 *) arg) = ves1820_readreg(state, 0x13) & 0x7f; + if (*((u32 *) arg) == 0x7f) + *((u32 *) arg) = 0xffffffff; /* reset uncorrected block counter */ - ves1820_writereg (fe, 0x10, ves1820_inittab[0x10] & 0xdf); - ves1820_writereg (fe, 0x10, ves1820_inittab[0x10]); + ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf); + ves1820_writereg(state, 0x10, ves1820_inittab[0x10]); break; - case FE_SET_FRONTEND: - return ves1820_set_parameters (fe, arg); + case FE_SET_FRONTEND: + return ves1820_set_parameters(state, arg); case FE_GET_FRONTEND: - { - struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *)arg; - u8 reg0 = GET_REG0(fe->data); - int sync; - s8 afc = 0; - - sync = ves1820_readreg(fe, 0x11); - afc = ves1820_readreg(fe, 0x19); - if (verbose) { - /* AFC only valid when carrier has been recovered */ - printk(sync & 2 ? "DVB: VES1820(%d): AFC (%d) %dHz\n" : - "DVB: VES1820(%d): [AFC (%d) %dHz]\n", - fe->i2c->adapter->num, afc, - -((s32)p->u.qam.symbol_rate * afc) >> 10); + { + struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *) arg; + int sync; + s8 afc = 0; + + sync = ves1820_readreg(state, 0x11); + afc = ves1820_readreg(state, 0x19); + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" : + "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10); + } + + p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF; + p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; + + p->u.qam.fec_inner = FEC_NONE; + + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + if (sync & 2) + p->frequency -= ((s32) p->u.qam.symbol_rate * afc) >> 10; + break; } - - p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF; - p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16; - - p->u.qam.fec_inner = FEC_NONE; - - p->frequency = ((p->frequency + 31250) / 62500) * 62500; - if (sync & 2) - p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; - break; - } case FE_SLEEP: - ves1820_writereg (fe, 0x1b, 0x02); /* pdown ADC */ - ves1820_writereg (fe, 0x00, 0x80); /* standby */ + ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */ + ves1820_writereg(state, 0x00, 0x80); /* standby */ break; - case FE_INIT: - return ves1820_init (fe); + case FE_INIT: + return ves1820_init(state); - default: - return -EINVAL; - } + default: + return -EINVAL; + } - return 0; + return 0; } - -static long probe_tuner (struct dvb_i2c_bus *i2c) +static long probe_tuner(struct i2c_adapter *i2c) { - static const struct i2c_msg msg1 = - { .addr = 0x61, .flags = 0, .buf = NULL, .len = 0 }; - static const struct i2c_msg msg2 = - { .addr = 0x62, .flags = 0, .buf = NULL, .len = 0 }; + struct i2c_msg msg1 = {.addr = 0x61,.flags = 0,.buf = NULL,.len = 0 }; + struct i2c_msg msg2 = {.addr = 0x62,.flags = 0,.buf = NULL,.len = 0 }; int type; - if (i2c->xfer(i2c, &msg1, 1) == 1) { + if (i2c_transfer(i2c, &msg1, 1) == 1) { type = 0; - printk ("DVB: VES1820(%d): setup for tuner spXXXX\n", i2c->adapter->num); - } else if (i2c->xfer(i2c, &msg2, 1) == 1) { + printk("ves1820: setup for tuner spXXXX\n"); + } else if (i2c_transfer(i2c, &msg2, 1) == 1) { type = 1; - printk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num); + printk("ves1820: setup for tuner sp5659c\n"); } else { type = -1; } @@ -495,96 +449,164 @@ static long probe_tuner (struct dvb_i2c_bus *i2c) return type; } - -static u8 read_pwm (struct dvb_i2c_bus *i2c) +static u8 read_pwm(struct i2c_adapter *i2c) { u8 b = 0xff; u8 pwm; - struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 }, - { .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } }; + struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + }; - if ((i2c->xfer(i2c, msg, 2) != 2) || (pwm == 0xff)) + if ((i2c_transfer(i2c, msg, 2) != 2) || (pwm == 0xff)) pwm = 0x48; - printk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm); + printk("ves1820: pwm=0x%02x\n", pwm); return pwm; } - -static long probe_demod_addr (struct dvb_i2c_bus *i2c) +static long probe_demod_addr(struct i2c_adapter *i2c) { - u8 b [] = { 0x00, 0x1a }; + u8 b[] = { 0x00, 0x1a }; u8 id; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b, .len = 2 }, - { .addr = 0x08, .flags = I2C_M_RD, .buf = &id, .len = 1 } }; + struct i2c_msg msg[] = { {.addr = 0x08,.flags = 0,.buf = b,.len = 2}, + {.addr = 0x08,.flags = I2C_M_RD,.buf = &id,.len = 1} + }; - if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) + if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) return msg[0].addr; msg[0].addr = msg[1].addr = 0x09; - if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) + if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) return msg[0].addr; return -1; } +static struct i2c_client client_template; -static int ves1820_attach (struct dvb_i2c_bus *i2c, void **data) +static int attach_adapter(struct i2c_adapter *adapter) { - void *priv = NULL; + struct i2c_client *client; + struct ves1820_state *state; long demod_addr; - long tuner_type; + int tuner_type; + int ret; - if ((demod_addr = probe_demod_addr(i2c)) < 0) + demod_addr = probe_demod_addr(adapter); + if (demod_addr < 0) return -ENODEV; - tuner_type = probe_tuner(i2c); + tuner_type = probe_tuner(adapter); + if (tuner_type < 0) { + printk("ves1820: demod found, but unknown tuner type.\n"); + return -ENODEV; + } - if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) { - printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n", - i2c->adapter->num, pwm[i2c->adapter->num]); - SET_PWM(priv, pwm[i2c->adapter->num]); + if ((state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL)) == NULL) { + return -ENOMEM; } - else - SET_PWM(priv, read_pwm(i2c)); - SET_REG0(priv, ves1820_inittab[0]); - SET_TUNER(priv, tuner_type); - SET_DEMOD_ADDR(priv, demod_addr); - return dvb_register_frontend (ves1820_ioctl, i2c, priv, &ves1820_info); -} + if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + kfree(state); + return -ENOMEM; + } + state->i2c = adapter; + state->tuner = tuner_type; + state->pwm = read_pwm(adapter); + state->reg0 = ves1820_inittab[0]; + state->demod_addr = demod_addr; -static void ves1820_detach (struct dvb_i2c_bus *i2c, void *data) -{ - dvb_unregister_frontend (ves1820_ioctl, i2c); + /* todo: honour user pwm setting somehow */ + + memcpy(client, &client_template, sizeof(struct i2c_client)); + client->adapter = adapter; + client->addr = addr[tuner_type]; + + i2c_set_clientdata(client, (void *) state); + + ret = i2c_attach_client(client); + if (ret) { + kfree(client); + kfree(state); + return -EFAULT; + } + + BUG_ON(!state->dvb); + + ret = dvb_register_frontend_new(ves1820_ioctl, state->dvb, state, &ves1820_info, THIS_MODULE); + if (ret) { + i2c_detach_client(client); + kfree(client); + kfree(state); + return -EFAULT; + } + + return 0; } +static int detach_client(struct i2c_client *client) +{ + struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); + dvb_unregister_frontend_new(ves1820_ioctl, state->dvb); + i2c_detach_client(client); + BUG_ON(state->dvb); + kfree(client); + kfree(state); + return 0; +} -static int __init init_ves1820 (void) +static int command(struct i2c_client *client, unsigned int cmd, void *arg) { - int i; - for (i = 0; i < MAX_UNITS; i++) - if (pwm[i] < -1 || pwm[i] > 255) - return -EINVAL; - return dvb_register_i2c_device (THIS_MODULE, - ves1820_attach, ves1820_detach); + struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client); + + switch (cmd) { + case FE_REGISTER:{ + state->dvb = (struct dvb_adapter *) arg; + break; + } + case FE_UNREGISTER:{ + state->dvb = NULL; + break; + } + default: + return -EOPNOTSUPP; + } + return 0; } +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = "ves1820", + .id = I2C_DRIVERID_VES1820, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach_adapter, + .detach_client = detach_client, + .command = command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("ves1820"), + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; -static void __exit exit_ves1820 (void) +static int __init init_ves1820(void) { - dvb_unregister_i2c_device (ves1820_attach); + return i2c_add_driver(&driver); } +static void __exit exit_ves1820(void) +{ + if (i2c_del_driver(&driver)) + printk("ves1820: driver deregistration failed\n"); +} module_init(init_ves1820); module_exit(exit_ves1820); -MODULE_PARM(pwm, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM_DESC(pwm, "override PWM value stored in EEPROM (tuner calibration)"); MODULE_PARM(verbose, "i"); MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting"); |