in si476x-i2c.c [686:836]
static int si476x_core_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rval;
struct si476x_core *core;
struct si476x_platform_data *pdata;
struct mfd_cell *cell;
int cell_num;
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
if (!core)
return -ENOMEM;
core->client = client;
core->regmap = devm_regmap_init_si476x(core);
if (IS_ERR(core->regmap)) {
rval = PTR_ERR(core->regmap);
dev_err(&client->dev,
"Failed to allocate register map: %d\n",
rval);
return rval;
}
i2c_set_clientdata(client, core);
atomic_set(&core->is_alive, 0);
core->power_state = SI476X_POWER_DOWN;
pdata = dev_get_platdata(&client->dev);
if (pdata) {
memcpy(&core->power_up_parameters,
&pdata->power_up_parameters,
sizeof(core->power_up_parameters));
core->gpio_reset = -1;
if (gpio_is_valid(pdata->gpio_reset)) {
rval = gpio_request(pdata->gpio_reset, "si476x reset");
if (rval) {
dev_err(&client->dev,
"Failed to request gpio: %d\n", rval);
return rval;
}
core->gpio_reset = pdata->gpio_reset;
gpio_direction_output(core->gpio_reset, 0);
}
core->diversity_mode = pdata->diversity_mode;
memcpy(&core->pinmux, &pdata->pinmux,
sizeof(struct si476x_pinmux));
} else {
dev_err(&client->dev, "No platform data provided\n");
return -EINVAL;
}
core->supplies[0].supply = "vd";
core->supplies[1].supply = "va";
core->supplies[2].supply = "vio1";
core->supplies[3].supply = "vio2";
rval = devm_regulator_bulk_get(&client->dev,
ARRAY_SIZE(core->supplies),
core->supplies);
if (rval) {
dev_err(&client->dev, "Failed to get all of the regulators\n");
goto free_gpio;
}
mutex_init(&core->cmd_lock);
init_waitqueue_head(&core->command);
init_waitqueue_head(&core->tuning);
rval = kfifo_alloc(&core->rds_fifo,
SI476X_DRIVER_RDS_FIFO_DEPTH *
sizeof(struct v4l2_rds_data),
GFP_KERNEL);
if (rval) {
dev_err(&client->dev, "Could not allocate the FIFO\n");
goto free_gpio;
}
mutex_init(&core->rds_drainer_status_lock);
init_waitqueue_head(&core->rds_read_queue);
INIT_WORK(&core->rds_fifo_drainer, si476x_core_drain_rds_fifo);
if (client->irq) {
rval = devm_request_threaded_irq(&client->dev,
client->irq, NULL,
si476x_core_interrupt,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
client->name, core);
if (rval < 0) {
dev_err(&client->dev, "Could not request IRQ %d\n",
client->irq);
goto free_kfifo;
}
disable_irq(client->irq);
dev_dbg(&client->dev, "IRQ requested.\n");
core->rds_fifo_depth = 20;
} else {
INIT_DELAYED_WORK(&core->status_monitor,
si476x_core_poll_loop);
dev_info(&client->dev,
"No IRQ number specified, will use polling\n");
core->rds_fifo_depth = 5;
}
core->chip_id = id->driver_data;
rval = si476x_core_get_revision_info(core);
if (rval < 0) {
rval = -ENODEV;
goto free_kfifo;
}
cell_num = 0;
cell = &core->cells[SI476X_RADIO_CELL];
cell->name = "si476x-radio";
cell_num++;
#ifdef CONFIG_SND_SOC_SI476X
if ((core->chip_id == SI476X_CHIP_SI4761 ||
core->chip_id == SI476X_CHIP_SI4764) &&
core->pinmux.dclk == SI476X_DCLK_DAUDIO &&
core->pinmux.dfs == SI476X_DFS_DAUDIO &&
core->pinmux.dout == SI476X_DOUT_I2S_OUTPUT &&
core->pinmux.xout == SI476X_XOUT_TRISTATE) {
cell = &core->cells[SI476X_CODEC_CELL];
cell->name = "si476x-codec";
cell_num++;
}
#endif
rval = mfd_add_devices(&client->dev,
(client->adapter->nr << 8) + client->addr,
core->cells, cell_num,
NULL, 0, NULL);
if (!rval)
return 0;
free_kfifo:
kfifo_free(&core->rds_fifo);
free_gpio:
if (gpio_is_valid(core->gpio_reset))
gpio_free(core->gpio_reset);
return rval;
}