static int is31fl319x_probe()

in leds-is31fl319x.c [335:415]


static int is31fl319x_probe(struct i2c_client *client,
			    const struct i2c_device_id *id)
{
	struct is31fl319x_chip *is31;
	struct device *dev = &client->dev;
	int err;
	int i = 0;
	u32 aggregated_led_microamp = IS31FL319X_CURRENT_MAX;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
		return -EIO;

	is31 = devm_kzalloc(&client->dev, sizeof(*is31), GFP_KERNEL);
	if (!is31)
		return -ENOMEM;

	mutex_init(&is31->lock);

	err = is31fl319x_parse_dt(&client->dev, is31);
	if (err)
		goto free_mutex;

	if (is31->shutdown_gpio) {
		gpiod_direction_output(is31->shutdown_gpio, 0);
		mdelay(5);
		gpiod_direction_output(is31->shutdown_gpio, 1);
	}

	is31->client = client;
	is31->regmap = devm_regmap_init_i2c(client, &regmap_config);
	if (IS_ERR(is31->regmap)) {
		dev_err(&client->dev, "failed to allocate register map\n");
		err = PTR_ERR(is31->regmap);
		goto free_mutex;
	}

	i2c_set_clientdata(client, is31);

	/* check for write-reply from chip (we can't read any registers) */
	err = regmap_write(is31->regmap, IS31FL319X_RESET, 0x00);
	if (err < 0) {
		dev_err(&client->dev, "no response from chip write: err = %d\n",
			err);
		err = -EIO; /* does not answer */
		goto free_mutex;
	}

	/*
	 * Kernel conventions require per-LED led-max-microamp property.
	 * But the chip does not allow to limit individual LEDs.
	 * So we take minimum from all subnodes for safety of hardware.
	 */
	for (i = 0; i < is31->cdef->num_leds; i++)
		if (is31->leds[i].configured &&
		    is31->leds[i].max_microamp < aggregated_led_microamp)
			aggregated_led_microamp = is31->leds[i].max_microamp;

	regmap_write(is31->regmap, IS31FL319X_CONFIG2,
		     is31fl319x_microamp_to_cs(dev, aggregated_led_microamp) |
		     is31fl319x_db_to_gain(is31->audio_gain_db));

	for (i = 0; i < is31->cdef->num_leds; i++) {
		struct is31fl319x_led *led = &is31->leds[i];

		if (!led->configured)
			continue;

		led->chip = is31;
		led->cdev.brightness_set_blocking = is31fl319x_brightness_set;

		err = devm_led_classdev_register(&client->dev, &led->cdev);
		if (err < 0)
			goto free_mutex;
	}

	return 0;

free_mutex:
	mutex_destroy(&is31->lock);
	return err;
}