static int pca9685_pwm_probe()

in pwm-pca9685.c [516:599]


static int pca9685_pwm_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	struct pca9685 *pca;
	unsigned int reg;
	int ret;

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

	pca->regmap = devm_regmap_init_i2c(client, &pca9685_regmap_i2c_config);
	if (IS_ERR(pca->regmap)) {
		ret = PTR_ERR(pca->regmap);
		dev_err(&client->dev, "Failed to initialize register map: %d\n",
			ret);
		return ret;
	}

	i2c_set_clientdata(client, pca);

	mutex_init(&pca->lock);

	ret = pca9685_read_reg(pca, PCA9685_MODE2, &reg);
	if (ret)
		return ret;

	if (device_property_read_bool(&client->dev, "invert"))
		reg |= MODE2_INVRT;
	else
		reg &= ~MODE2_INVRT;

	if (device_property_read_bool(&client->dev, "open-drain"))
		reg &= ~MODE2_OUTDRV;
	else
		reg |= MODE2_OUTDRV;

	ret = pca9685_write_reg(pca, PCA9685_MODE2, reg);
	if (ret)
		return ret;

	/* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */
	pca9685_read_reg(pca, PCA9685_MODE1, &reg);
	reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3);
	pca9685_write_reg(pca, PCA9685_MODE1, reg);

	/* Reset OFF/ON registers to POR default */
	pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, LED_FULL);
	pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_H, LED_FULL);
	pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0);
	pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, 0);

	pca->chip.ops = &pca9685_pwm_ops;
	/* Add an extra channel for ALL_LED */
	pca->chip.npwm = PCA9685_MAXCHAN + 1;

	pca->chip.dev = &client->dev;

	ret = pwmchip_add(&pca->chip);
	if (ret < 0)
		return ret;

	ret = pca9685_pwm_gpio_probe(pca);
	if (ret < 0) {
		pwmchip_remove(&pca->chip);
		return ret;
	}

	pm_runtime_enable(&client->dev);

	if (pm_runtime_enabled(&client->dev)) {
		/*
		 * Although the chip comes out of power-up in the sleep state,
		 * we force it to sleep in case it was woken up before
		 */
		pca9685_set_sleep_mode(pca, true);
		pm_runtime_set_suspended(&client->dev);
	} else {
		/* Wake the chip up if runtime PM is disabled */
		pca9685_set_sleep_mode(pca, false);
	}

	return 0;
}