static int ltr501_probe()

in light/ltr501.c [1443:1601]


static int ltr501_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct ltr501_data *data;
	struct iio_dev *indio_dev;
	struct regmap *regmap;
	int ret, partid, chip_idx = 0;
	const char *name = NULL;

	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
	if (!indio_dev)
		return -ENOMEM;

	regmap = devm_regmap_init_i2c(client, &ltr501_regmap_config);
	if (IS_ERR(regmap)) {
		dev_err(&client->dev, "Regmap initialization failed.\n");
		return PTR_ERR(regmap);
	}

	data = iio_priv(indio_dev);
	i2c_set_clientdata(client, indio_dev);
	data->client = client;
	data->regmap = regmap;
	mutex_init(&data->lock_als);
	mutex_init(&data->lock_ps);

	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,
				       ltr501_disable_regulators, data);
	if (ret)
		return ret;

	data->reg_it = devm_regmap_field_alloc(&client->dev, regmap,
					       reg_field_it);
	if (IS_ERR(data->reg_it)) {
		dev_err(&client->dev, "Integ time reg field init failed.\n");
		return PTR_ERR(data->reg_it);
	}

	data->reg_als_intr = devm_regmap_field_alloc(&client->dev, regmap,
						     reg_field_als_intr);
	if (IS_ERR(data->reg_als_intr)) {
		dev_err(&client->dev, "ALS intr mode reg field init failed\n");
		return PTR_ERR(data->reg_als_intr);
	}

	data->reg_ps_intr = devm_regmap_field_alloc(&client->dev, regmap,
						    reg_field_ps_intr);
	if (IS_ERR(data->reg_ps_intr)) {
		dev_err(&client->dev, "PS intr mode reg field init failed.\n");
		return PTR_ERR(data->reg_ps_intr);
	}

	data->reg_als_rate = devm_regmap_field_alloc(&client->dev, regmap,
						     reg_field_als_rate);
	if (IS_ERR(data->reg_als_rate)) {
		dev_err(&client->dev, "ALS samp rate field init failed.\n");
		return PTR_ERR(data->reg_als_rate);
	}

	data->reg_ps_rate = devm_regmap_field_alloc(&client->dev, regmap,
						    reg_field_ps_rate);
	if (IS_ERR(data->reg_ps_rate)) {
		dev_err(&client->dev, "PS samp rate field init failed.\n");
		return PTR_ERR(data->reg_ps_rate);
	}

	data->reg_als_prst = devm_regmap_field_alloc(&client->dev, regmap,
						     reg_field_als_prst);
	if (IS_ERR(data->reg_als_prst)) {
		dev_err(&client->dev, "ALS prst reg field init failed\n");
		return PTR_ERR(data->reg_als_prst);
	}

	data->reg_ps_prst = devm_regmap_field_alloc(&client->dev, regmap,
						    reg_field_ps_prst);
	if (IS_ERR(data->reg_ps_prst)) {
		dev_err(&client->dev, "PS prst reg field init failed.\n");
		return PTR_ERR(data->reg_ps_prst);
	}

	ret = regmap_read(data->regmap, LTR501_PART_ID, &partid);
	if (ret < 0)
		return ret;

	if (id) {
		name = id->name;
		chip_idx = id->driver_data;
	} else  if (ACPI_HANDLE(&client->dev)) {
		name = ltr501_match_acpi_device(&client->dev, &chip_idx);
	} else {
		return -ENODEV;
	}

	data->chip_info = &ltr501_chip_info_tbl[chip_idx];

	if ((partid >> 4) != data->chip_info->partid)
		return -ENODEV;

	if (device_property_read_u32(&client->dev, "proximity-near-level",
				     &data->near_level))
		data->near_level = 0;

	indio_dev->info = data->chip_info->info;
	indio_dev->channels = data->chip_info->channels;
	indio_dev->num_channels = data->chip_info->no_channels;
	indio_dev->name = name;
	indio_dev->modes = INDIO_DIRECT_MODE;

	ret = ltr501_init(data);
	if (ret < 0)
		return ret;

	if (client->irq > 0) {
		ret = devm_request_threaded_irq(&client->dev, client->irq,
						NULL, ltr501_interrupt_handler,
						IRQF_TRIGGER_FALLING |
						IRQF_ONESHOT,
						"ltr501_thresh_event",
						indio_dev);
		if (ret) {
			dev_err(&client->dev, "request irq (%d) failed\n",
				client->irq);
			return ret;
		}
	} else {
		indio_dev->info = data->chip_info->info_no_irq;
	}

	ret = iio_triggered_buffer_setup(indio_dev, NULL,
					 ltr501_trigger_handler, NULL);
	if (ret)
		goto powerdown_on_error;

	ret = iio_device_register(indio_dev);
	if (ret)
		goto error_unreg_buffer;

	return 0;

error_unreg_buffer:
	iio_triggered_buffer_cleanup(indio_dev);
powerdown_on_error:
	ltr501_powerdown(data);
	return ret;
}