diff options
author | Kenneth Aafloy <devnull@localhost> | 2004-07-16 19:08:40 +0000 |
---|---|---|
committer | Kenneth Aafloy <devnull@localhost> | 2004-07-16 19:08:40 +0000 |
commit | 2848c66d0366df1880b673ecadbaefcbf1448a86 (patch) | |
tree | 389dbf67338e53c86aced193a7d2685de411dffb /linux/drivers/media | |
parent | 2ae9e8fdd009dc568f8447b64c6e93bd95c26981 (diff) | |
download | mediapointer-dvb-s2-2848c66d0366df1880b673ecadbaefcbf1448a86.tar.gz mediapointer-dvb-s2-2848c66d0366df1880b673ecadbaefcbf1448a86.tar.bz2 |
- Conversion to Kernel I2C layer.
- MODULE_PARM* -> module_param*
- Common name for I2C device and prefix for debug messages.
NOTE: This needs testing by someone who has one of these frontends.
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/dvb/frontends/grundig_29504-401.c | 230 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/grundig_29504-491.c | 174 |
2 files changed, 289 insertions, 115 deletions
diff --git a/linux/drivers/media/dvb/frontends/grundig_29504-401.c b/linux/drivers/media/dvb/frontends/grundig_29504-401.c index 4fec2c6a0..ed42a6e76 100644 --- a/linux/drivers/media/dvb/frontends/grundig_29504-401.c +++ b/linux/drivers/media/dvb/frontends/grundig_29504-401.c @@ -31,16 +31,29 @@ #include "dvb_frontend.h" #include "dvb_functions.h" -static int debug = 0; +#define FRONTEND_NAME "dvbfe_l64781" -#define dprintk if (debug) printk +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ + } while (0) -struct grundig_state { +static int debug; +static int old_set_tv_freq; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +module_param(old_set_tv_freq, int, 0644); +MODULE_PARM_DESC(old_set_tv_freq, "Use old tsa5060_set_tv_freq calculations."); + +struct l64781_state { int first:1; + struct i2c_adapter *i2c; + struct dvb_adapter *dvb; }; -struct dvb_frontend_info grundig_29504_401_info = { - .name = "Grundig 29504-401", +struct dvb_frontend_info l64781_info = { + .name = "Grundig 29504-401 (LSI L64781 Based)", .type = FE_OFDM, /* .frequency_min = ???,*/ /* .frequency_max = ???,*/ @@ -55,13 +68,13 @@ struct dvb_frontend_info grundig_29504_401_info = { }; -static int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int l64781_writereg (struct i2c_adapter *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 }; - if ((ret = i2c->xfer (i2c, &msg, 1)) != 1) + if ((ret = i2c_transfer(i2c, &msg, 1)) != 1) dprintk ("%s: write_reg error (reg == %02x) = %02x!\n", __FUNCTION__, reg, ret); @@ -69,7 +82,7 @@ static int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) } -static u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 l64781_readreg (struct i2c_adapter *i2c, u8 reg) { int ret; u8 b0 [] = { reg }; @@ -77,7 +90,7 @@ static u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg) struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, { .addr = 0x55, .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); @@ -86,12 +99,12 @@ static u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg) } -static int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int tsa5060_write (struct i2c_adapter *i2c, u8 data [4]) { int ret; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; - if ((ret = i2c->xfer (i2c, &msg, 1)) != 1) + if ((ret = i2c_transfer(i2c, &msg, 1)) != 1) dprintk ("%s: write_reg error == %02x!\n", __FUNCTION__, ret); return (ret != 1) ? -1 : 0; @@ -103,14 +116,17 @@ static int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4]) * reference clock comparision frequency of 166666 Hz. * frequency offset is 36125000 Hz. */ -static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int tsa5060_set_tv_freq (struct i2c_adapter *i2c, u32 freq) { -#if 1 u32 div; u8 buf [4]; u8 cfg, cpump, band_select; - div = (36125000 + freq) / 166666; + if (old_set_tv_freq) + div = (36000000 + freq) / 166666; + else + div = (36125000 + freq) / 166666; + cfg = 0x88; cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 : @@ -121,28 +137,18 @@ static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) buf [0] = (div >> 8) & 0x7f; buf [1] = div & 0xff; buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = (cpump << 6) | band_select; -#else - /* old code which seems to work better for at least one person */ - u32 div; - u8 buf [4]; - u8 cfg; - - div = (36000000 + freq) / 166666; - cfg = 0x88; - - buf [0] = (div >> 8) & 0x7f; - buf [1] = div & 0xff; - buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = 0xc0; -#endif + + if (old_set_tv_freq) + buf [3] = 0xc0; + else + buf [3] = (cpump << 6) | band_select; return tsa5060_write(i2c, buf); } -static void apply_tps (struct dvb_i2c_bus *i2c) +static void apply_tps (struct i2c_adapter *i2c) { l64781_writereg (i2c, 0x2a, 0x00); l64781_writereg (i2c, 0x2a, 0x01); @@ -156,7 +162,7 @@ static void apply_tps (struct dvb_i2c_bus *i2c) } -static void reset_afc (struct dvb_i2c_bus *i2c) +static void reset_afc (struct i2c_adapter *i2c) { /* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for timing offset */ @@ -174,7 +180,7 @@ static void reset_afc (struct dvb_i2c_bus *i2c) } -static int apply_frontend_param (struct dvb_i2c_bus *i2c, +static int apply_frontend_param (struct i2c_adapter *i2c, struct dvb_frontend_parameters *param) { /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */ @@ -286,16 +292,16 @@ static int apply_frontend_param (struct dvb_i2c_bus *i2c, } -static int reset_and_configure (struct dvb_i2c_bus *i2c) +static int reset_and_configure (struct i2c_adapter *i2c) { u8 buf [] = { 0x06 }; struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 }; - return (i2c->xfer (i2c, &msg, 1) == 1) ? 0 : -ENODEV; + return (i2c_transfer(i2c, &msg, 1) == 1) ? 0 : -ENODEV; } -static int get_frontend(struct dvb_i2c_bus* i2c, struct dvb_frontend_parameters* param) +static int get_frontend(struct i2c_adapter* i2c, struct dvb_frontend_parameters* param) { int tmp; @@ -413,7 +419,7 @@ static int get_frontend(struct dvb_i2c_bus* i2c, struct dvb_frontend_parameters* } -static int init (struct dvb_i2c_bus *i2c) +static int init (struct i2c_adapter *i2c) { reset_and_configure (i2c); @@ -450,16 +456,16 @@ static int init (struct dvb_i2c_bus *i2c) static -int grundig_29504_401_ioctl (struct dvb_frontend *fe, +int l64781_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { - struct dvb_i2c_bus *i2c = fe->i2c; + struct l64781_state* state = fe->data; + struct i2c_adapter *i2c = state->i2c; int res; - struct grundig_state* state = (struct grundig_state*) fe->data; switch (cmd) { case FE_GET_INFO: - memcpy (arg, &grundig_29504_401_info, + memcpy (arg, &l64781_info, sizeof(struct dvb_frontend_info)); break; @@ -568,28 +574,26 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe, return 0; } - -static int l64781_attach (struct dvb_i2c_bus *i2c, void **data) +static int l64781_probe(struct i2c_adapter *i2c) { u8 reg0x3e; u8 b0 [] = { 0x1a }; u8 b1 [] = { 0x00 }; struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - struct grundig_state* state; /** * the L64781 won't show up before we send the reset_and_configure() * broadcast. If nothing responds there is no L64781 on the bus... */ if (reset_and_configure(i2c) < 0) { - dprintk("no response on reset_and_configure() broadcast, bailing out...\n"); + dprintk("No response to reset and configure broadcast...\n"); return -ENODEV; } /* The chip always responds to reads */ - if (i2c->xfer(i2c, msg, 2) != 2) { - dprintk("no response to read on I2C bus\n"); + if (i2c_transfer(i2c, msg, 2) != 2) { + dprintk("No response to read on I2C bus\n"); return -ENODEV; } @@ -608,58 +612,138 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data) /* Responds to all reads with 0 */ if (l64781_readreg(i2c, 0x1a) != 0) { dprintk("Read 1 returned unexpcted value\n"); - goto bailout; - } + goto out; + } /* Turn the chip on */ l64781_writereg (i2c, 0x3e, 0xa5); - + /* Responds with register default value */ if (l64781_readreg(i2c, 0x1a) != 0xa1) { dprintk("Read 2 returned unexpcted value\n"); - goto bailout; + goto out; } - - state = kmalloc(sizeof(struct grundig_state), GFP_KERNEL); - if (state == NULL) goto bailout; - *data = state; - state->first = 1; - - return dvb_register_frontend (grundig_29504_401_ioctl, i2c, state, - &grundig_29504_401_info); - bailout: + return 0; +out: l64781_writereg (i2c, 0x3e, reg0x3e); /* restore reg 0x3e */ return -ENODEV; } +static struct i2c_client client_template; - -static void l64781_detach (struct dvb_i2c_bus *i2c, void *data) +static int l64781_attach_adapter(struct i2c_adapter *adapter) { - kfree(data); - dvb_unregister_frontend (grundig_29504_401_ioctl, i2c); + struct l64781_state *state; + struct i2c_client *client; + int ret; + + dprintk("Trying to attach to adapter 0x%x:%s.\n", + adapter->id, adapter->name); + + if ((ret = l64781_probe(adapter))) + return ret; + + if ( !(state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL)) ) + return -ENOMEM; + + memset(state, 0, sizeof(struct l64781_state)); + state->i2c = adapter; + state->first = 1; + + if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { + kfree(state); + return -ENOMEM; + } + + memcpy(client, &client_template, sizeof(struct i2c_client)); + client->adapter = adapter; + client->addr = 0; //XXX + i2c_set_clientdata(client, state); + + if ((ret = i2c_attach_client(client))) { + kfree(state); + kfree(client); + return ret; + } + + BUG_ON(!state->dvb); + + if ((ret = dvb_register_frontend_new(l64781_ioctl, state->dvb, state, + &l64781_info, THIS_MODULE))) { + i2c_detach_client(client); + kfree(state); + kfree(client); + return ret; + } + + return 0; } +static int l64781_detach_client(struct i2c_client *client) +{ + struct l64781_state *state = i2c_get_clientdata(client); + + dvb_unregister_frontend_new(l64781_ioctl, state->dvb); + i2c_detach_client(client); + BUG_ON(state->dvb); + kfree(client); + kfree(state); + return 0; +} -static int __init init_grundig_29504_401 (void) +static int l64781_command(struct i2c_client *client, + unsigned int cmd, void *arg) { - return dvb_register_i2c_device (THIS_MODULE, - l64781_attach, l64781_detach); + struct l64781_state *data = i2c_get_clientdata(client); + dprintk ("%s\n", __FUNCTION__); + + switch (cmd) { + case FE_REGISTER: { + data->dvb = arg; + break; + } + case FE_UNREGISTER: { + data->dvb = NULL; + break; + } + default: + return -EOPNOTSUPP; + } + return 0; } +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = FRONTEND_NAME, + .id = I2C_DRIVERID_DVBFE_L64781, + .flags = I2C_DF_NOTIFY, + .attach_adapter = l64781_attach_adapter, + .detach_client = l64781_detach_client, + .command = l64781_command, +}; + +static struct i2c_client client_template = { + .name = FRONTEND_NAME, + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; + +static int __init init_l64781 (void) +{ + return i2c_add_driver(&driver); +} -static void __exit exit_grundig_29504_401 (void) +static void __exit exit_l64781 (void) { - dvb_unregister_i2c_device (l64781_attach); + if (i2c_del_driver(&driver)) + printk(KERN_ERR "l64781: driver deregistration failed\n"); } -module_init(init_grundig_29504_401); -module_exit(exit_grundig_29504_401); +module_init(init_l64781); +module_exit(exit_l64781); -MODULE_PARM(debug,"i"); -MODULE_PARM_DESC(debug, "enable verbose debug messages"); -MODULE_DESCRIPTION("Grundig 29504-401 DVB-T Frontend"); +MODULE_DESCRIPTION("Grundig 29504-401 DVB-T Frontend (LSI L64781 Based)"); MODULE_AUTHOR("Holger Waechtler, Marko Kohtala"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/grundig_29504-491.c b/linux/drivers/media/dvb/frontends/grundig_29504-491.c index 68408c7b4..3f82cef6b 100644 --- a/linux/drivers/media/dvb/frontends/grundig_29504-491.c +++ b/linux/drivers/media/dvb/frontends/grundig_29504-491.c @@ -33,11 +33,25 @@ #include "dvb_frontend.h" #include "dvb_functions.h" -static int debug = 0; -#define dprintk if (debug) printk +#define FRONTEND_NAME "dvbfe_tda8083" +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG FRONTEND_NAME ": " args); \ + } while (0) -static struct dvb_frontend_info grundig_29504_491_info = { +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + + +struct tda8083_state { + struct i2c_adapter *i2c; + struct dvb_adapter *dvb; +}; + +static struct dvb_frontend_info tda8083_info = { .name = "Grundig 29504-491, (TDA8083 based)", .type = FE_QPSK, .frequency_min = 950000, /* FIXME: guessed! */ @@ -55,8 +69,6 @@ static struct dvb_frontend_info grundig_29504_491_info = { FE_CAN_QPSK | FE_CAN_MUTE_TS }; - - static u8 tda8083_init_tab [] = { 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea, 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10, @@ -67,14 +79,13 @@ static u8 tda8083_init_tab [] = { }; - -static int tda8083_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int tda8083_writereg (struct i2c_adapter *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; struct i2c_msg msg = { .addr = 0x68, .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 (reg %02x, ret == %i)\n", @@ -84,13 +95,13 @@ static int tda8083_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) } -static int tda8083_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) +static int tda8083_readregs (struct i2c_adapter *i2c, u8 reg1, u8 *b, u8 len) { int ret; struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = ®1, .len = 1 }, { .addr = 0x68, .flags = I2C_M_RD, .buf = b, .len = len } }; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer(i2c, msg, 2); if (ret != 2) dprintk ("%s: readreg error (reg %02x, ret == %i)\n", @@ -100,7 +111,7 @@ static int tda8083_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) } -static inline u8 tda8083_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static inline u8 tda8083_readreg (struct i2c_adapter *i2c, u8 reg) { u8 val; @@ -110,12 +121,12 @@ static inline u8 tda8083_readreg (struct dvb_i2c_bus *i2c, u8 reg) } -static int tsa5522_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int tsa5522_write (struct i2c_adapter *i2c, u8 data [4]) { int ret; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer(i2c, &msg, 1); if (ret != 1) dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); @@ -128,7 +139,7 @@ static int tsa5522_write (struct dvb_i2c_bus *i2c, u8 data [4]) * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static int tsa5522_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int tsa5522_set_tv_freq (struct i2c_adapter *i2c, u32 freq) { u32 div = freq / 125; u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x8e, 0x00 }; @@ -137,7 +148,7 @@ static int tsa5522_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) } -static int tda8083_init (struct dvb_i2c_bus *i2c) +static int tda8083_init (struct i2c_adapter *i2c) { int i; @@ -150,7 +161,7 @@ static int tda8083_init (struct dvb_i2c_bus *i2c) } -static int tda8083_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +static int tda8083_set_inversion (struct i2c_adapter *i2c, fe_spectral_inversion_t inversion) { /* XXX FIXME: implement other modes than FEC_AUTO */ if (inversion == INVERSION_AUTO) @@ -160,7 +171,7 @@ static int tda8083_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion } -static int tda8083_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +static int tda8083_set_fec (struct i2c_adapter *i2c, fe_code_rate_t fec) { if (fec == FEC_AUTO) return tda8083_writereg (i2c, 0x07, 0xff); @@ -172,7 +183,7 @@ static int tda8083_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) } -static fe_code_rate_t tda8083_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t tda8083_get_fec (struct i2c_adapter *i2c) { u8 index; static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, @@ -184,7 +195,7 @@ static fe_code_rate_t tda8083_get_fec (struct dvb_i2c_bus *i2c) } -static int tda8083_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int tda8083_set_symbolrate (struct i2c_adapter *i2c, u32 srate) { u32 ratio; u32 tmp; @@ -224,7 +235,7 @@ static int tda8083_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) } -static void tda8083_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout) +static void tda8083_wait_diseqc_fifo (struct i2c_adapter *i2c, int timeout) { unsigned long start = jiffies; @@ -236,7 +247,7 @@ static void tda8083_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout) } -static int tda8083_send_diseqc_msg (struct dvb_i2c_bus *i2c, +static int tda8083_send_diseqc_msg (struct i2c_adapter *i2c, struct dvb_diseqc_master_cmd *m) { int i; @@ -254,7 +265,7 @@ static int tda8083_send_diseqc_msg (struct dvb_i2c_bus *i2c, } -static int tda8083_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) +static int tda8083_send_diseqc_burst (struct i2c_adapter *i2c, fe_sec_mini_cmd_t burst) { switch (burst) { case SEC_MINI_A: @@ -273,7 +284,7 @@ static int tda8083_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t } -static int tda8083_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) +static int tda8083_set_tone (struct i2c_adapter *i2c, fe_sec_tone_mode_t tone) { tda8083_writereg (i2c, 0x26, 0xf1); @@ -288,7 +299,7 @@ static int tda8083_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) } -static int tda8083_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int tda8083_set_voltage (struct i2c_adapter *i2c, fe_sec_voltage_t voltage) { switch (voltage) { case SEC_VOLTAGE_13: @@ -301,15 +312,15 @@ static int tda8083_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag } -static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd, - void *arg) +static int tda8083_ioctl(struct dvb_frontend *fe, unsigned int cmd, + void *arg) { - struct dvb_i2c_bus *i2c = fe->i2c; + struct tda8083_state *state = fe->data; + struct i2c_adapter *i2c = state->i2c; switch (cmd) { case FE_GET_INFO: - memcpy (arg, &grundig_29504_491_info, - sizeof(struct dvb_frontend_info)); + memcpy (arg, &tda8083_info, sizeof(struct dvb_frontend_info)); break; case FE_READ_STATUS: @@ -426,40 +437,119 @@ static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd, return 0; } +static struct i2c_client client_template; -static int tda8083_attach (struct dvb_i2c_bus *i2c, void **data) +static int tda8083_attach_adapter(struct i2c_adapter *adapter) { - if ((tda8083_readreg (i2c, 0x00)) != 0x05) + struct tda8083_state *state; + struct i2c_client *client; + int ret; + + dprintk("Trying to attach to adapter 0x%x:%s.\n", + adapter->id, adapter->name); + + if ((tda8083_readreg (adapter, 0x00)) != 0x05) return -ENODEV; - return dvb_register_frontend (grundig_29504_491_ioctl, i2c, NULL, - &grundig_29504_491_info); + if ( !(state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL)) ) + return -ENOMEM; + + if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) { + kfree(state); + return -ENOMEM; + } + + memset(state, 0, sizeof(struct tda8083_state)); + state->i2c = adapter; + + memcpy(client, &client_template, sizeof(struct i2c_client)); + client->adapter = adapter; + client->addr = 0; //XXX + i2c_set_clientdata(client, state); + + if ((ret = i2c_attach_client(client))) { + kfree(state); + kfree(client); + return ret; + } + + BUG_ON(!state->dvb); + + if ((ret = dvb_register_frontend_new(tda8083_ioctl, state->dvb, state, + &tda8083_info, THIS_MODULE))) { + i2c_detach_client(client); + kfree(state); + kfree(client); + return ret; + } + + return 0; } +static int tda8083_detach_client(struct i2c_client *client) +{ + struct tda8083_state *state = i2c_get_clientdata(client); + + dvb_unregister_frontend_new (tda8083_ioctl, state->dvb); + i2c_detach_client(client); + BUG_ON(state->dvb); + kfree(client); + kfree(state); + return 0; +} -static void tda8083_detach (struct dvb_i2c_bus *i2c, void *data) +static int tda8083_command (struct i2c_client *client, unsigned int cmd, void *arg) { - dvb_unregister_frontend (grundig_29504_491_ioctl, i2c); + struct tda8083_state *data = i2c_get_clientdata(client); + dprintk ("%s\n", __FUNCTION__); + + switch (cmd) { + case FE_REGISTER: { + data->dvb = arg; + break; + } + case FE_UNREGISTER: { + data->dvb = NULL; + break; + } + default: + return -EOPNOTSUPP; + } + + return 0; } +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = FRONTEND_NAME, + .id = I2C_DRIVERID_DVBFE_TDA8083, + .flags = I2C_DF_NOTIFY, + .attach_adapter = tda8083_attach_adapter, + .detach_client = tda8083_detach_client, + .command = tda8083_command, +}; + +static struct i2c_client client_template = { + .name = FRONTEND_NAME, + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; static int __init init_tda8083 (void) { - return dvb_register_i2c_device (THIS_MODULE, - tda8083_attach, tda8083_detach); + return i2c_add_driver(&driver); } - -static void __exit exit_tda8083 (void) +static void __exit exit_tda8083(void) { - dvb_unregister_i2c_device (tda8083_attach); + if (i2c_del_driver(&driver)) + printk("grundig_29504_401: driver deregistration failed\n"); } module_init(init_tda8083); module_exit(exit_tda8083); -MODULE_PARM(debug,"i"); -MODULE_DESCRIPTION("Grundig 29504-491 DVB frontend driver"); +MODULE_DESCRIPTION("Grundig 29504-491 DVB frontend driver (TDA8083 Based)"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); |