From 30970c2a967560590b306f6965aea609d7fd3a54 Mon Sep 17 00:00:00 2001 From: Michael Hunold Date: Mon, 3 May 2004 11:15:31 +0000 Subject: Overhaul frontend i2c subsystem because of the recent discussion about the usage of the syscall interface to load binary firmware used by some frontend drivers. - add dvb_register_frontend_new() and dvb_unregister_frontend_new() which register a frontend driver using the kernel i2c interface instead of the dvb i2c interface. - register kernel i2c interface in av7110/budget driver properly - port stv0299 and ves1x93 to kernel i2c api Other DVB drivers and frontend drivers still can use the old DVB i2c interface. --- linux/drivers/media/dvb/frontends/ves1x93.c | 136 +++++++++++++++++++++------- 1 file changed, 104 insertions(+), 32 deletions(-) (limited to 'linux/drivers/media/dvb/frontends/ves1x93.c') diff --git a/linux/drivers/media/dvb/frontends/ves1x93.c b/linux/drivers/media/dvb/frontends/ves1x93.c index 170416d5f..93925939d 100644 --- a/linux/drivers/media/dvb/frontends/ves1x93.c +++ b/linux/drivers/media/dvb/frontends/ves1x93.c @@ -31,7 +31,9 @@ #include "dvb_frontend.h" #include "dvb_functions.h" - + +/* fixme: add this to i2c-id.h */ +#define I2C_DRIVERID_VES1X93 I2C_DRIVERID_EXP1 static int debug = 0; #define dprintk if (debug) printk @@ -112,17 +114,18 @@ static u8 init_1993_wtab[] = struct ves1x93_state { fe_spectral_inversion_t inversion; + struct i2c_adapter *i2c; }; -static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int ves1x93_writereg (struct i2c_adapter *i2c, u8 reg, u8 data) { u8 buf [] = { 0x00, reg, data }; struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; int err; - if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer (i2c, &msg, 1)) != 1) { dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); return -EREMOTEIO; } @@ -131,7 +134,7 @@ static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) } -static u8 ves1x93_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 ves1x93_readreg (struct i2c_adapter *i2c, u8 reg) { int ret; u8 b0 [] = { 0x00, reg }; @@ -139,7 +142,7 @@ static u8 ves1x93_readreg (struct dvb_i2c_bus *i2c, u8 reg) struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, { .addr = 0x08, .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); @@ -148,13 +151,13 @@ static u8 ves1x93_readreg (struct dvb_i2c_bus *i2c, u8 reg) } -static int tuner_write (struct dvb_i2c_bus *i2c, u8 *data, u8 len) +static int tuner_write (struct i2c_adapter *i2c, u8 *data, u8 len) { int ret; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = len }; ves1x93_writereg(i2c, 0x00, 0x11); - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer (i2c, &msg, 1); ves1x93_writereg(i2c, 0x00, 0x01); if (ret != 1) @@ -169,7 +172,7 @@ static int tuner_write (struct dvb_i2c_bus *i2c, u8 *data, u8 len) * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +static int sp5659_set_tv_freq (struct i2c_adapter *i2c, u32 freq, u8 pwr) { u32 div = (freq + 479500) / 125; u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x95, (pwr << 5) | 0x30 }; @@ -178,7 +181,7 @@ static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) } -static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int tsa5059_set_tv_freq (struct i2c_adapter *i2c, u32 freq) { int ret; u8 buf [2]; @@ -194,7 +197,7 @@ static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) } -static int tuner_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +static int tuner_set_tv_freq (struct i2c_adapter *i2c, u32 freq, u8 pwr) { if ((demod_type == DEMOD_VES1893) && (board_type == BOARD_SIEMENS_PCI)) return sp5659_set_tv_freq (i2c, freq, pwr); @@ -205,7 +208,7 @@ static int tuner_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) } -static int ves1x93_init (struct dvb_i2c_bus *i2c) +static int ves1x93_init (struct i2c_adapter *i2c) { int i; int size; @@ -249,7 +252,7 @@ static int ves1x93_init (struct dvb_i2c_bus *i2c) } -static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c) +static int ves1x93_clr_bit (struct i2c_adapter *i2c) { ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe); ves1x93_writereg (i2c, 0, init_1x93_tab[0]); @@ -257,7 +260,7 @@ static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c) return 0; } -static int ves1x93_init_aquire (struct dvb_i2c_bus *i2c) +static int ves1x93_init_aquire (struct i2c_adapter *i2c) { ves1x93_writereg (i2c, 3, 0x00); ves1x93_writereg (i2c, 3, init_1x93_tab[3]); @@ -266,7 +269,7 @@ static int ves1x93_init_aquire (struct dvb_i2c_bus *i2c) } -static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +static int ves1x93_set_inversion (struct i2c_adapter *i2c, fe_spectral_inversion_t inversion) { u8 val; @@ -293,7 +296,7 @@ static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion } -static int ves1x93_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +static int ves1x93_set_fec (struct i2c_adapter *i2c, fe_code_rate_t fec) { if (fec == FEC_AUTO) return ves1x93_writereg (i2c, 0x0d, 0x08); @@ -304,13 +307,13 @@ static int ves1x93_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) } -static fe_code_rate_t ves1x93_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t ves1x93_get_fec (struct i2c_adapter *i2c) { return FEC_1_2 + ((ves1x93_readreg (i2c, 0x0d) >> 4) & 0x7); } -static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int ves1x93_set_symbolrate (struct i2c_adapter *i2c, u32 srate) { u32 BDR; u32 ratio; @@ -414,7 +417,7 @@ static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) } -static int ves1x93_afc (struct dvb_i2c_bus *i2c, u32 freq, u32 srate) +static int ves1x93_afc (struct i2c_adapter *i2c, u32 freq, u32 srate) { int afc; @@ -433,7 +436,7 @@ static int ves1x93_afc (struct dvb_i2c_bus *i2c, u32 freq, u32 srate) return 0; } -static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int ves1x93_set_voltage (struct i2c_adapter *i2c, fe_sec_voltage_t voltage) { switch (voltage) { case SEC_VOLTAGE_13: @@ -450,8 +453,8 @@ static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { - struct dvb_i2c_bus *i2c = fe->i2c; - struct ves1x93_state *state = (struct ves1x93_state*) fe->data; + struct ves1x93_state *state = (struct ves1x93_state *) fe->data; + struct i2c_adapter *i2c = state->i2c; switch (cmd) { case FE_GET_INFO: @@ -578,11 +581,13 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) return 0; } +static struct i2c_client client_template; -static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) +static int attach_adapter(struct i2c_adapter *adapter) { - u8 identity = ves1x93_readreg(i2c, 0x1e); + struct i2c_client *client; struct ves1x93_state* state; + u8 identity = ves1x93_readreg(adapter, 0x1e); switch (identity) { case 0xdc: /* VES1893A rev1 */ @@ -608,19 +613,86 @@ static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) if ((state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL)) == NULL) { return -ENOMEM; } - state->inversion = INVERSION_OFF; - *data = state; - return dvb_register_frontend (ves1x93_ioctl, i2c, (void*) state, &ves1x93_info); + if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + kfree(state); + return -ENOMEM; + } + + state->inversion = INVERSION_OFF; + state->i2c = adapter; + + memcpy(client, &client_template, sizeof(struct i2c_client)); + client->adapter = adapter; + client->addr = (0x08>>1); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + client->data = state; +#else + i2c_set_clientdata(client, (void*)state); +#endif + + if (0 != i2c_attach_client(client)) { + kfree(client); + kfree(state); + return -EFAULT; + } + return 0; } +static int detach_client(struct i2c_client *client) +{ + i2c_detach_client(client); + kfree(client); + return 0; +} -static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data) +static int command (struct i2c_client *client, unsigned int cmd, void *arg) { - kfree(data); - dvb_unregister_frontend (ves1x93_ioctl, i2c); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + struct stv0299_data *data = (struct stv0299_data*)client->data; +#else + struct stv0299_data *data = (struct stv0299_data*)i2c_get_clientdata(client); +#endif + + dprintk ("%s\n", __FUNCTION__); + + switch (cmd) { + case FE_REGISTER: { + struct dvb_adapter *dvb_adapter = (struct dvb_adapter*)arg; + return dvb_register_frontend_new (ves1x93_ioctl, dvb_adapter, (void*) data, &ves1x93_info); + } + case FE_UNREGISTER: { + struct dvb_adapter *dvb_adapter = (struct dvb_adapter*)arg; + dvb_unregister_frontend_new (ves1x93_ioctl, dvb_adapter); + break; + } + default: + return -EOPNOTSUPP; + } + return 0; } +static struct i2c_driver driver = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + .owner = THIS_MODULE, +#endif + .name = "ves1x93", + .id = I2C_DRIVERID_VES1X93, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach_adapter, + .detach_client = detach_client, + .command = command, +}; + +static struct i2c_client client_template = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + I2C_DEVNAME("stv0299"), +#else + .name = "ves1x93", +#endif + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; static int __init init_ves1x93 (void) { @@ -638,16 +710,16 @@ static int __init init_ves1x93 (void) return -EIO; } - return dvb_register_i2c_device (THIS_MODULE, ves1x93_attach, ves1x93_detach); + return i2c_add_driver(&driver); } static void __exit exit_ves1x93 (void) { - dvb_unregister_i2c_device (ves1x93_attach); + if (i2c_del_driver(&driver)) + printk("vex1x93: driver deregistration failed\n"); } - module_init(init_ves1x93); module_exit(exit_ves1x93); -- cgit v1.2.3