diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index fa3ecbed1e586278254a19555407c62a2c11eaeb..b04346687c689ab4d5fa0440c44d60ab918dc707 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -31,6 +31,10 @@ static int debug; +/* Despite the name "hybrid_tuner", the framework works just as well for + hybrid demodulators as well... */ +static LIST_HEAD(hybrid_tuner_instance_list); + #define dprintk(arg...) do { \ if (debug) \ printk(arg); \ @@ -786,23 +790,50 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe, return 0; } +static struct dvb_frontend_ops au8522_ops; + +int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, + u8 client_address) +{ + return hybrid_tuner_request_state(struct au8522_state, (*state), + hybrid_tuner_instance_list, + i2c, client_address, "au8522"); +} + +void au8522_release_state(struct au8522_state *state) +{ + if (state != NULL) + hybrid_tuner_release_state(state); +} + + static void au8522_release(struct dvb_frontend *fe) { struct au8522_state *state = fe->demodulator_priv; - kfree(state); + au8522_release_state(state); } -static struct dvb_frontend_ops au8522_ops; - struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct i2c_adapter *i2c) { struct au8522_state *state = NULL; + int instance; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); - if (state == NULL) - goto error; + instance = au8522_get_state(&state, i2c, config->demod_address); + switch (instance) { + case 0: + dprintk("%s state allocation failed\n", __func__); + break; + case 1: + /* new demod instance */ + dprintk("%s using new instance\n", __func__); + break; + default: + /* existing demod instance */ + dprintk("%s using existing instance\n", __func__); + break; + } /* setup the state */ state->config = config; @@ -824,7 +855,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, return &state->frontend; error: - kfree(state); + au8522_release_state(state); return NULL; } EXPORT_SYMBOL(au8522_attach); diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h index 569675d295d50ed93b082ee05d8b4f5603777b73..98b09caa212387928678c10d6c6edcd2d530dd89 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb/frontends/au8522_priv.h @@ -37,6 +37,10 @@ struct au8522_state { struct i2c_adapter *i2c; + /* Used for sharing of the state between analog and digital mode */ + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; + /* configuration settings */ const struct au8522_config *config; @@ -55,3 +59,7 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data); u8 au8522_readreg(struct au8522_state *state, u16 reg); int au8522_init(struct dvb_frontend *fe); int au8522_sleep(struct dvb_frontend *fe); + +int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, + u8 client_address); +void au8522_release_state(struct au8522_state *state);