mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
media: stv090x: Implement probe/remove for stv090x
Move common code into a new function. This provides the needed functionality to use dvb_module_probe() instead of dvb_attach()! [mchehab+samsung@kernel.org: fix an out of order error return code] Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
3c8f4cd271
commit
eb5005df88
@ -4889,6 +4889,67 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
|
||||
return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
|
||||
}
|
||||
|
||||
static int stv090x_setup_compound(struct stv090x_state *state)
|
||||
{
|
||||
struct stv090x_dev *temp_int;
|
||||
|
||||
temp_int = find_dev(state->i2c,
|
||||
state->config->address);
|
||||
|
||||
if (temp_int && state->demod_mode == STV090x_DUAL) {
|
||||
state->internal = temp_int->internal;
|
||||
state->internal->num_used++;
|
||||
dprintk(FE_INFO, 1, "Found Internal Structure!");
|
||||
} else {
|
||||
state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL);
|
||||
if (!state->internal)
|
||||
goto error;
|
||||
temp_int = append_internal(state->internal);
|
||||
if (!temp_int) {
|
||||
kfree(state->internal);
|
||||
goto error;
|
||||
}
|
||||
state->internal->num_used = 1;
|
||||
state->internal->mclk = 0;
|
||||
state->internal->dev_ver = 0;
|
||||
state->internal->i2c_adap = state->i2c;
|
||||
state->internal->i2c_addr = state->config->address;
|
||||
dprintk(FE_INFO, 1, "Create New Internal Structure!");
|
||||
|
||||
mutex_init(&state->internal->demod_lock);
|
||||
mutex_init(&state->internal->tuner_lock);
|
||||
|
||||
if (stv090x_setup(&state->frontend) < 0) {
|
||||
dprintk(FE_ERROR, 1, "Error setting up device");
|
||||
goto err_remove;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->internal->dev_ver >= 0x30)
|
||||
state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
|
||||
|
||||
/* workaround for stuck DiSEqC output */
|
||||
if (state->config->diseqc_envelope_mode)
|
||||
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
|
||||
|
||||
state->config->set_gpio = stv090x_set_gpio;
|
||||
|
||||
dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x",
|
||||
state->device == STV0900 ? "STV0900" : "STV0903",
|
||||
state->config->demod,
|
||||
state->internal->dev_ver);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return -ENOMEM;
|
||||
err_remove:
|
||||
remove_dev(state->internal);
|
||||
kfree(state->internal);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static const struct dvb_frontend_ops stv090x_ops = {
|
||||
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
|
||||
.info = {
|
||||
@ -4921,16 +4982,74 @@ static const struct dvb_frontend_ops stv090x_ops = {
|
||||
.read_snr = stv090x_read_cnr,
|
||||
};
|
||||
|
||||
static struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client)
|
||||
{
|
||||
struct stv090x_state *state = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
return &state->frontend;
|
||||
}
|
||||
|
||||
static int stv090x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct stv090x_config *config = client->dev.platform_data;
|
||||
|
||||
struct stv090x_state *state = NULL;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
state->verbose = &verbose;
|
||||
state->config = config;
|
||||
state->i2c = client->adapter;
|
||||
state->frontend.ops = stv090x_ops;
|
||||
state->frontend.demodulator_priv = state;
|
||||
state->demod = config->demod;
|
||||
/* Single or Dual mode */
|
||||
state->demod_mode = config->demod_mode;
|
||||
state->device = config->device;
|
||||
/* default */
|
||||
state->rolloff = STV090x_RO_35;
|
||||
|
||||
ret = stv090x_setup_compound(state);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
i2c_set_clientdata(client, state);
|
||||
|
||||
/* setup callbacks */
|
||||
config->get_dvb_frontend = stv090x_get_dvb_frontend;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stv090x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct stv090x_state *state = i2c_get_clientdata(client);
|
||||
|
||||
stv090x_release(&state->frontend);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
|
||||
struct i2c_adapter *i2c,
|
||||
enum stv090x_demodulator demod)
|
||||
{
|
||||
int ret = 0;
|
||||
struct stv090x_state *state = NULL;
|
||||
struct stv090x_dev *temp_int;
|
||||
|
||||
state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
goto error;
|
||||
|
||||
state->verbose = &verbose;
|
||||
@ -4939,67 +5058,42 @@ struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
|
||||
state->frontend.ops = stv090x_ops;
|
||||
state->frontend.demodulator_priv = state;
|
||||
state->demod = demod;
|
||||
state->demod_mode = config->demod_mode; /* Single or Dual mode */
|
||||
/* Single or Dual mode */
|
||||
state->demod_mode = config->demod_mode;
|
||||
state->device = config->device;
|
||||
state->rolloff = STV090x_RO_35; /* default */
|
||||
/* default */
|
||||
state->rolloff = STV090x_RO_35;
|
||||
|
||||
temp_int = find_dev(state->i2c,
|
||||
state->config->address);
|
||||
|
||||
if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
|
||||
state->internal = temp_int->internal;
|
||||
state->internal->num_used++;
|
||||
dprintk(FE_INFO, 1, "Found Internal Structure!");
|
||||
} else {
|
||||
state->internal = kmalloc(sizeof(struct stv090x_internal),
|
||||
GFP_KERNEL);
|
||||
if (!state->internal)
|
||||
goto error;
|
||||
temp_int = append_internal(state->internal);
|
||||
if (!temp_int) {
|
||||
kfree(state->internal);
|
||||
goto error;
|
||||
}
|
||||
state->internal->num_used = 1;
|
||||
state->internal->mclk = 0;
|
||||
state->internal->dev_ver = 0;
|
||||
state->internal->i2c_adap = state->i2c;
|
||||
state->internal->i2c_addr = state->config->address;
|
||||
dprintk(FE_INFO, 1, "Create New Internal Structure!");
|
||||
|
||||
mutex_init(&state->internal->demod_lock);
|
||||
mutex_init(&state->internal->tuner_lock);
|
||||
|
||||
if (stv090x_setup(&state->frontend) < 0) {
|
||||
dprintk(FE_ERROR, 1, "Error setting up device");
|
||||
goto err_remove;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->internal->dev_ver >= 0x30)
|
||||
state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
|
||||
|
||||
/* workaround for stuck DiSEqC output */
|
||||
if (config->diseqc_envelope_mode)
|
||||
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
|
||||
|
||||
config->set_gpio = stv090x_set_gpio;
|
||||
|
||||
dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
|
||||
state->device == STV0900 ? "STV0900" : "STV0903",
|
||||
demod,
|
||||
state->internal->dev_ver);
|
||||
ret = stv090x_setup_compound(state);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
err_remove:
|
||||
remove_dev(state->internal);
|
||||
kfree(state->internal);
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(stv090x_attach);
|
||||
|
||||
static const struct i2c_device_id stv090x_id_table[] = {
|
||||
{"stv090x", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, stv090x_id_table);
|
||||
|
||||
static struct i2c_driver stv090x_driver = {
|
||||
.driver = {
|
||||
.name = "stv090x",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = stv090x_probe,
|
||||
.remove = stv090x_remove,
|
||||
.id_table = stv090x_id_table,
|
||||
};
|
||||
|
||||
module_i2c_driver(stv090x_driver);
|
||||
|
||||
MODULE_PARM_DESC(verbose, "Set Verbosity level");
|
||||
MODULE_AUTHOR("Manu Abraham");
|
||||
MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
|
||||
|
@ -57,6 +57,7 @@ struct stv090x_config {
|
||||
enum stv090x_device device;
|
||||
enum stv090x_mode demod_mode;
|
||||
enum stv090x_clkmode clk_mode;
|
||||
enum stv090x_demodulator demod;
|
||||
|
||||
u32 xtal; /* default: 8000000 */
|
||||
u8 address; /* default: 0x68 */
|
||||
@ -93,6 +94,8 @@ struct stv090x_config {
|
||||
/* dir = 0 -> output, dir = 1 -> input/open-drain */
|
||||
int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
|
||||
u8 xor_value);
|
||||
|
||||
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *i2c);
|
||||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_DVB_STV090x)
|
||||
|
@ -237,7 +237,7 @@ struct stv090x_state {
|
||||
struct stv090x_internal *internal;
|
||||
|
||||
struct i2c_adapter *i2c;
|
||||
const struct stv090x_config *config;
|
||||
struct stv090x_config *config;
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
u32 *verbose; /* Cached module verbosity */
|
||||
|
Loading…
Reference in New Issue
Block a user