in accel/kxcjk-1013.c [1435:1609]
static int kxcjk1013_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct kxcjk1013_data *data;
struct iio_dev *indio_dev;
struct kxcjk_1013_platform_data *pdata;
const char *name;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
pdata = dev_get_platdata(&client->dev);
if (pdata) {
data->active_high_intr = pdata->active_high_intr;
data->orientation = pdata->orientation;
} else {
data->active_high_intr = true; /* default polarity */
ret = iio_read_mount_matrix(&client->dev, &data->orientation);
if (ret)
return ret;
}
data->regulators[0].supply = "vdd";
data->regulators[1].supply = "vddio";
ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return ret;
ret = devm_add_action_or_reset(&client->dev, kxcjk1013_disable_regulators, data);
if (ret)
return ret;
/*
* A typical delay of 10ms is required for powering up
* according to the data sheets of supported chips.
* Hence double that to play safe.
*/
msleep(20);
if (id) {
data->chipset = (enum kx_chipset)(id->driver_data);
name = id->name;
} else if (ACPI_HANDLE(&client->dev)) {
name = kxcjk1013_match_acpi_device(&client->dev,
&data->chipset,
&data->acpi_type,
&indio_dev->label);
} else
return -ENODEV;
switch (data->chipset) {
case KXCJK1013:
case KXCJ91008:
case KXTJ21009:
data->regs = &kxcjk1013_regs;
break;
case KXTF9:
data->regs = &kxtf9_regs;
break;
case KX0231025:
data->regs = &kx0231025_regs;
break;
default:
return -EINVAL;
}
ret = kxcjk1013_chip_init(data);
if (ret < 0)
return ret;
mutex_init(&data->mutex);
indio_dev->channels = kxcjk1013_channels;
indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &kxcjk1013_info;
if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
IRQF_TRIGGER_RISING,
KXCJK1013_IRQ_NAME,
indio_dev);
if (ret)
goto err_poweroff;
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d",
indio_dev->name,
iio_device_id(indio_dev));
if (!data->dready_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->motion_trig = devm_iio_trigger_alloc(&client->dev,
"%s-any-motion-dev%d",
indio_dev->name,
iio_device_id(indio_dev));
if (!data->motion_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->dready_trig->ops = &kxcjk1013_trigger_ops;
iio_trigger_set_drvdata(data->dready_trig, indio_dev);
indio_dev->trig = data->dready_trig;
iio_trigger_get(indio_dev->trig);
ret = iio_trigger_register(data->dready_trig);
if (ret)
goto err_poweroff;
data->motion_trig->ops = &kxcjk1013_trigger_ops;
iio_trigger_set_drvdata(data->motion_trig, indio_dev);
ret = iio_trigger_register(data->motion_trig);
if (ret) {
data->motion_trig = NULL;
goto err_trigger_unregister;
}
}
ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time,
kxcjk1013_trigger_handler,
&kxcjk1013_buffer_setup_ops);
if (ret < 0) {
dev_err(&client->dev, "iio triggered buffer setup failed\n");
goto err_trigger_unregister;
}
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto err_buffer_cleanup;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
KXCJK1013_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
if (data->motion_trig)
iio_trigger_unregister(data->motion_trig);
err_poweroff:
kxcjk1013_set_mode(data, STANDBY);
return ret;
}