diff options
author | Michael Hunold <devnull@localhost> | 2004-06-22 13:53:59 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2004-06-22 13:53:59 +0000 |
commit | 2ab054a9059005e514cd10e7c546dda722191c05 (patch) | |
tree | b872226485da1d207cf506f2d48d87f6dd6c80f1 /linux/drivers/media/dvb/frontends/at76c651.c | |
parent | a2203e12db48c483f6c71fb1cc6b66711854873e (diff) | |
download | mediapointer-dvb-s2-2ab054a9059005e514cd10e7c546dda722191c05.tar.gz mediapointer-dvb-s2-2ab054a9059005e514cd10e7c546dda722191c05.tar.bz2 |
- convert to kernel i2c, thanks to Kenneth Aafløy <lists@kenneth.aafloy.net>
Note: this will probably break some of the drivers out there, which don't
register properly to the kernel i2c subsystem yet.
Diffstat (limited to 'linux/drivers/media/dvb/frontends/at76c651.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/at76c651.c | 254 |
1 files changed, 157 insertions, 97 deletions
diff --git a/linux/drivers/media/dvb/frontends/at76c651.c b/linux/drivers/media/dvb/frontends/at76c651.c index dd4cd35a8..51c9654e9 100644 --- a/linux/drivers/media/dvb/frontends/at76c651.c +++ b/linux/drivers/media/dvb/frontends/at76c651.c @@ -38,11 +38,12 @@ #include "dvb_functions.h" static int debug = 0; -static u8 at76c651_qam; -static u8 at76c651_revision; #define dprintk if (debug) printk +//FIXME: Move to i2c-id.h +#define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP0 + /* * DAT7021 * ------- @@ -74,6 +75,13 @@ static struct dvb_frontend_info at76c651_info = { FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER }; +struct at76c651_state { + u8 revision; + u8 qam; + struct i2c_adapter *i2c; + struct dvb_adapter *dvb; +}; + #if ! defined(__powerpc__) static __inline__ int __ilog2(unsigned long x) { @@ -89,14 +97,13 @@ static __inline__ int __ilog2(unsigned long x) } #endif -static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int at76c651_writereg(struct i2c_adapter *i2c, u8 reg, u8 data) { - int ret; u8 buf[] = { reg, data }; struct i2c_msg msg = { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c->xfer(i2c, &msg, 1); + ret = i2c_transfer(i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error " @@ -106,43 +113,37 @@ static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data) dvb_delay(10); return (ret != 1) ? -EREMOTEIO : 0; - } -static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg) +static u8 at76c651_readreg(struct i2c_adapter *i2c, u8 reg) { - int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = { {.addr = 0x1a >> 1, .flags = 0, .buf = b0, .len = 1}, {.addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1} }; - ret = i2c->xfer(i2c, msg, 2); + ret = i2c_transfer(i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); return b1[0]; - } -static int at76c651_reset(struct dvb_i2c_bus *i2c) +static int at76c651_reset(struct i2c_adapter *i2c) { - return at76c651_writereg(i2c, 0x07, 0x01); - } -static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) +static int at76c651_disable_interrupts(struct i2c_adapter *i2c) { - return at76c651_writereg(i2c, 0x0b, 0x00); - } -static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) +static int at76c651_set_auto_config(struct at76c651_state *state) { + struct i2c_adapter *i2c = state->i2c; /* * Autoconfig @@ -155,19 +156,19 @@ static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) */ at76c651_writereg(i2c, 0x10, 0x06); - at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10); + at76c651_writereg(i2c, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); at76c651_writereg(i2c, 0x15, 0x28); at76c651_writereg(i2c, 0x20, 0x09); - at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90); + at76c651_writereg(i2c, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); at76c651_writereg(i2c, 0x30, 0x90); - if (at76c651_qam == 5) + if (state->qam == 5) at76c651_writereg(i2c, 0x35, 0x2A); /* * Initialize A/D-converter */ - if (at76c651_revision == 0x11) { + if (state->revision == 0x11) { at76c651_writereg(i2c, 0x2E, 0x38); at76c651_writereg(i2c, 0x2F, 0x13); } @@ -181,32 +182,25 @@ static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) at76c651_reset(i2c); return 0; - } -static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) +static int at76c651_set_bbfreq(struct i2c_adapter *i2c) { - at76c651_writereg(i2c, 0x04, 0x3f); at76c651_writereg(i2c, 0x05, 0xee); - return 0; - } -static int at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable) +static int at76c651_switch_tuner_i2c(struct i2c_adapter *i2c, u8 enable) { - if (enable) return at76c651_writereg(i2c, 0x0c, 0xc2 | 0x01); else return at76c651_writereg(i2c, 0x0c, 0xc2); - } -static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) +static int dat7021_write(struct i2c_adapter *i2c, u32 tw) { - int ret; struct i2c_msg msg = { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) }; @@ -217,7 +211,7 @@ static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) at76c651_switch_tuner_i2c(i2c, 1); - ret = i2c->xfer(i2c, &msg, 1); + ret = i2c_transfer(i2c, &msg, 1); at76c651_switch_tuner_i2c(i2c, 0); @@ -227,12 +221,10 @@ static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) at76c651_reset(i2c); return 0; - } -static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq) +static int dat7021_set_tv_freq(struct i2c_adapter *i2c, u32 freq) { - u32 dw; freq /= 1000; @@ -255,12 +247,10 @@ static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq) dw += 0x4E28E06; return dat7021_write(i2c, dw); - } -static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate) +static int at76c651_set_symbolrate(struct i2c_adapter *i2c, u32 symbolrate) { - u8 exponent; u32 mantissa; @@ -281,37 +271,35 @@ static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate) at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent); return 0; - } -static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) +static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam) { - switch (qam) { case QPSK: - at76c651_qam = 0x02; + state->qam = 0x02; break; case QAM_16: - at76c651_qam = 0x04; + state->qam = 0x04; break; case QAM_32: - at76c651_qam = 0x05; + state->qam = 0x05; break; case QAM_64: - at76c651_qam = 0x06; + state->qam = 0x06; break; case QAM_128: - at76c651_qam = 0x07; + state->qam = 0x07; break; case QAM_256: - at76c651_qam = 0x08; + state->qam = 0x08; break; #if 0 case QAM_512: - at76c651_qam = 0x09; + state->qam = 0x09; break; case QAM_1024: - at76c651_qam = 0x0A; + state->qam = 0x0A; break; #endif default: @@ -319,14 +307,12 @@ static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) } - return at76c651_writereg(i2c, 0x03, at76c651_qam); - + return at76c651_writereg(state->i2c, 0x03, state->qam); } -static int at76c651_set_inversion(struct dvb_i2c_bus *i2c, - fe_spectral_inversion_t inversion) +static int at76c651_set_inversion(struct i2c_adapter *i2c, + fe_spectral_inversion_t inversion) { - u8 feciqinv = at76c651_readreg(i2c, 0x60); switch (inversion) { @@ -348,36 +334,38 @@ static int at76c651_set_inversion(struct dvb_i2c_bus *i2c, } return at76c651_writereg(i2c, 0x60, feciqinv); - } -static int at76c651_set_parameters(struct dvb_i2c_bus *i2c, - struct dvb_frontend_parameters *p) +static int at76c651_set_parameters(struct at76c651_state *state, + struct dvb_frontend_parameters *p) { + struct i2c_adapter *i2c = state->i2c; + dat7021_set_tv_freq(i2c, p->frequency); at76c651_set_symbolrate(i2c, p->u.qam.symbol_rate); at76c651_set_inversion(i2c, p->inversion); - at76c651_set_auto_config(i2c); + at76c651_set_auto_config(state); at76c651_reset(i2c); return 0; - } -static int at76c651_set_defaults(struct dvb_i2c_bus *i2c) +static int at76c651_set_defaults(struct at76c651_state *state) { + struct i2c_adapter *i2c = state->i2c; at76c651_set_symbolrate(i2c, 6900000); - at76c651_set_qam(i2c, QAM_64); + at76c651_set_qam(state, QAM_64); at76c651_set_bbfreq(i2c); - at76c651_set_auto_config(i2c); + at76c651_set_auto_config(state); return 0; - } static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { + struct at76c651_state *state = fe->data; + struct i2c_adapter *i2c = state->i2c; switch (cmd) { case FE_GET_INFO: @@ -393,7 +381,7 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) /* * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) */ - sync = at76c651_readreg(fe->i2c, 0x80); + sync = at76c651_readreg(i2c, 0x80); *status = 0; @@ -420,9 +408,9 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { u32 *ber = (u32 *) arg; - *ber = (at76c651_readreg(fe->i2c, 0x81) & 0x0F) << 16; - *ber |= at76c651_readreg(fe->i2c, 0x82) << 8; - *ber |= at76c651_readreg(fe->i2c, 0x83); + *ber = (at76c651_readreg(i2c, 0x81) & 0x0F) << 16; + *ber |= at76c651_readreg(i2c, 0x82) << 8; + *ber |= at76c651_readreg(i2c, 0x83); *ber *= 10; break; @@ -430,7 +418,7 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) case FE_READ_SIGNAL_STRENGTH: { - u8 gain = ~at76c651_readreg(fe->i2c, 0x91); + u8 gain = ~at76c651_readreg(i2c, 0x91); *(u16 *) arg = (gain << 8) | gain; break; @@ -439,16 +427,16 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) case FE_READ_SNR: *(u16 *) arg = 0xFFFF - - ((at76c651_readreg(fe->i2c, 0x8F) << 8) | - at76c651_readreg(fe->i2c, 0x90)); + ((at76c651_readreg(i2c, 0x8F) << 8) | + at76c651_readreg(i2c, 0x90)); break; case FE_READ_UNCORRECTED_BLOCKS: - *(u32 *) arg = at76c651_readreg(fe->i2c, 0x82); + *(u32 *) arg = at76c651_readreg(i2c, 0x82); break; case FE_SET_FRONTEND: - return at76c651_set_parameters(fe->i2c, arg); + return at76c651_set_parameters(state, arg); case FE_GET_FRONTEND: break; @@ -457,11 +445,13 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) break; case FE_INIT: - return at76c651_set_defaults(fe->i2c); + return at76c651_set_defaults(state); case FE_GET_TUNE_SETTINGS: { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; + struct dvb_frontend_tune_settings* fesettings = + (struct dvb_frontend_tune_settings*) arg; + fesettings->min_delay_ms = 50; fesettings->step_size = 0; fesettings->max_drift = 0; @@ -473,55 +463,125 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) } return 0; - } -static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data) +static struct i2c_client client_template; + +static int attach_adapter(struct i2c_adapter *adapter) { - if ( (at76c651_readreg(i2c, 0x0E) != 0x65) || - ( ( (at76c651_revision = at76c651_readreg(i2c, 0x0F)) & 0xFE) != 0x10) ) - { + struct at76c651_state *state; + struct i2c_client *client; + int ret; + + if (NULL == (state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL))) + return -ENOMEM; + + state->i2c = adapter; + state->revision = at76c651_readreg(adapter, 0x0F) & 0xFE; + + if (state->revision == 0x10) { + dprintk("AT76C651A found\n"); + strcpy(at76c651_info.name, "Atmel AT76C651A with DAT7021"); + } else { + dprintk("AT76C651B found\n"); + strcpy(at76c651_info.name, "Atmel AT76C651B with DAT7021"); + } + + if (at76c651_readreg(adapter, 0x0E) != 0x65 || + state->revision != 0x10) { dprintk("no AT76C651(B) found\n"); + kfree(state); return -ENODEV; } - if (at76c651_revision == 0x10) - { - dprintk("AT76C651A found\n"); - strcpy(at76c651_info.name,"Atmel AT76C651A with DAT7021"); + if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + kfree(state); + return -ENOMEM; } - else - { - strcpy(at76c651_info.name,"Atmel AT76C651B with DAT7021"); - dprintk("AT76C651B found\n"); + + memcpy(client, &client_template, sizeof(struct i2c_client)); + client->adapter = adapter; + client->addr = 0x1a >> 1; + i2c_set_clientdata(client, state); + + ret = i2c_attach_client(client); + if (ret) { + kfree(state); + kfree(client); + return ret; } - at76c651_set_defaults(i2c); + BUG_ON(!state->dvb); - return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info); + ret = dvb_register_frontend_new(at76c651_ioctl, state->dvb, state, &at76c651_info); + if (ret) { + i2c_detach_client(client); + kfree(client); + kfree(state); + return ret; + } + return 0; } -static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data) +static int detach_client(struct i2c_client *client) { + struct at76c651_state *state = (struct at76c651_state*)i2c_get_clientdata(client); - dvb_unregister_frontend(at76c651_ioctl, i2c); + dprintk ("%s\n", __FUNCTION__); + dvb_unregister_frontend_new(at76c651_ioctl, state->dvb); + i2c_detach_client(client); + BUG_ON(state->dvb); + kfree(client); + kfree(state); + return 0; } -static int __init at76c651_init(void) +static int command (struct i2c_client *client, unsigned int cmd, void *arg) { + struct at76c651_state *state = (struct at76c651_state*)i2c_get_clientdata(client); - return dvb_register_i2c_device(THIS_MODULE, at76c651_attach, - at76c651_detach); + dprintk ("%s\n", __FUNCTION__); + 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 void __exit at76c651_exit(void) -{ +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = "at76c651", + .id = I2C_DRIVERID_DVBFE_AT76C651, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach_adapter, + .detach_client = detach_client, + .command = command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("at76c651"), + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; - dvb_unregister_i2c_device(at76c651_attach); +static int __init at76c651_init(void) +{ + return i2c_add_driver(&driver); +} +static void __exit at76c651_exit(void) +{ + if (i2c_del_driver(&driver)) + printk(KERN_ERR "at76c651: driver deregistration failed.\n"); } module_init(at76c651_init); |