Lines Matching +full:period +full:- +full:scale
1 // SPDX-License-Identifier: GPL-2.0-only
6 * Author: Peter Meerwald <p.meerwald@bct-electronic.com>
9 * Based on leds-pca955x.c
11 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
12 * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.)
22 * or by adding the 'nxp,hw-blink' property to the DTS.
43 #define PCA963X_MODE2_OUTDRV 0x04 /* Open-drain or totem pole */
86 /* Total blink period in milliseconds */
121 struct i2c_client *client = led->chip->client; in pca963x_brightness()
122 struct pca963x_chipdef *chipdef = led->chip->chipdef; in pca963x_brightness()
127 ledout_addr = chipdef->ledout_base + (led->led_num / 4); in pca963x_brightness()
128 shift = 2 * (led->led_num % 4); in pca963x_brightness()
134 if (led->blinking) { in pca963x_brightness()
138 led->led_num, in pca963x_brightness()
148 led->blinking = false; in pca963x_brightness()
153 led->led_num, in pca963x_brightness()
158 if (led->blinking) in pca963x_brightness()
172 struct i2c_client *client = led->chip->client; in pca963x_blink()
173 struct pca963x_chipdef *chipdef = led->chip->chipdef; in pca963x_blink()
177 ledout_addr = chipdef->ledout_base + (led->led_num / 4); in pca963x_blink()
178 shift = 2 * (led->led_num % 4); in pca963x_blink()
182 i2c_smbus_write_byte_data(client, chipdef->grppwm, led->gdc); in pca963x_blink()
184 i2c_smbus_write_byte_data(client, chipdef->grpfreq, led->gfrq); in pca963x_blink()
190 mutex_lock(&led->chip->mutex); in pca963x_blink()
198 mutex_unlock(&led->chip->mutex); in pca963x_blink()
199 led->blinking = true; in pca963x_blink()
204 struct i2c_client *client = led->chip->client; in pca963x_power_state()
205 unsigned long *leds_on = &led->chip->leds_on; in pca963x_power_state()
208 if (led->led_cdev.brightness) in pca963x_power_state()
209 set_bit(led->led_num, leds_on); in pca963x_power_state()
211 clear_bit(led->led_num, leds_on); in pca963x_power_state()
228 mutex_lock(&led->chip->mutex); in pca963x_led_set()
236 mutex_unlock(&led->chip->mutex); in pca963x_led_set()
243 unsigned int scaling = led->chip->chipdef->scaling; in pca963x_period_scale()
251 unsigned long time_on, time_off, period; in pca963x_blink_set() local
266 period = pca963x_period_scale(led, time_on + time_off); in pca963x_blink_set()
268 /* If period not supported by hardware, default to someting sane. */ in pca963x_blink_set()
269 if ((period < PCA963X_BLINK_PERIOD_MIN) || in pca963x_blink_set()
270 (period > PCA963X_BLINK_PERIOD_MAX)) { in pca963x_blink_set()
273 period = pca963x_period_scale(led, 1000); in pca963x_blink_set()
277 * From manual: duty cycle = (GDC / 256) -> in pca963x_blink_set()
278 * (time_on / period) = (GDC / 256) -> in pca963x_blink_set()
279 * GDC = ((time_on * 256) / period) in pca963x_blink_set()
281 gdc = (pca963x_period_scale(led, time_on) * 256) / period; in pca963x_blink_set()
284 * From manual: period = ((GFRQ + 1) / 24) in seconds. in pca963x_blink_set()
285 * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> in pca963x_blink_set()
286 * GFRQ = ((period * 24 / 1000) - 1) in pca963x_blink_set()
288 gfrq = (period * 24 / 1000) - 1; in pca963x_blink_set()
290 led->gdc = gdc; in pca963x_blink_set()
291 led->gfrq = gfrq; in pca963x_blink_set()
294 led->led_cdev.brightness = LED_FULL; in pca963x_blink_set()
306 struct pca963x_chipdef *chipdef = chip->chipdef; in pca963x_register_leds()
307 struct pca963x_led *led = chip->leds; in pca963x_register_leds()
308 struct device *dev = &client->dev; in pca963x_register_leds()
314 if (device_property_read_u32(dev, "nxp,period-scale", in pca963x_register_leds()
315 &chipdef->scaling)) in pca963x_register_leds()
316 chipdef->scaling = 1000; in pca963x_register_leds()
318 hw_blink = device_property_read_bool(dev, "nxp,hw-blink"); in pca963x_register_leds()
324 /* default to open-drain unless totem pole (push-pull) is specified */ in pca963x_register_leds()
325 if (device_property_read_bool(dev, "nxp,totem-pole")) in pca963x_register_leds()
330 /* default to non-inverted output, unless inverted is specified */ in pca963x_register_leds()
331 if (device_property_read_bool(dev, "nxp,inverted-out")) in pca963x_register_leds()
345 if (ret || reg >= chipdef->n_leds) { in pca963x_register_leds()
348 return -EINVAL; in pca963x_register_leds()
351 led->led_num = reg; in pca963x_register_leds()
352 led->chip = chip; in pca963x_register_leds()
353 led->led_cdev.brightness_set_blocking = pca963x_led_set; in pca963x_register_leds()
355 led->led_cdev.blink_set = pca963x_blink_set; in pca963x_register_leds()
356 led->blinking = false; in pca963x_register_leds()
362 client->adapter->nr, client->addr, reg); in pca963x_register_leds()
365 ret = devm_led_classdev_register_ext(dev, &led->led_cdev, in pca963x_register_leds()
384 reg = i2c_smbus_read_byte_data(chip->client, PCA963X_MODE1); in pca963x_suspend()
386 i2c_smbus_write_byte_data(chip->client, PCA963X_MODE1, reg); in pca963x_suspend()
396 reg = i2c_smbus_read_byte_data(chip->client, PCA963X_MODE1); in pca963x_resume()
398 i2c_smbus_write_byte_data(chip->client, PCA963X_MODE1, reg); in pca963x_resume()
417 struct device *dev = &client->dev; in pca963x_probe()
422 chipdef = &pca963x_chipdefs[id->driver_data]; in pca963x_probe()
425 if (!count || count > chipdef->n_leds) { in pca963x_probe()
427 dev_fwnode(dev), chipdef->n_leds); in pca963x_probe()
428 return -EINVAL; in pca963x_probe()
433 return -ENOMEM; in pca963x_probe()
437 mutex_init(&chip->mutex); in pca963x_probe()
438 chip->chipdef = chipdef; in pca963x_probe()
439 chip->client = client; in pca963x_probe()
442 for (i = 0; i < chipdef->n_leds / 4; i++) in pca963x_probe()
443 i2c_smbus_write_byte_data(client, chipdef->ledout_base + i, 0x00); in pca963x_probe()
445 /* Disable LED all-call address, and power down initially */ in pca963x_probe()
453 .name = "leds-pca963x",
463 MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>");