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, ®map_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;
}