Lines Matching +full:led +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0
22 #define CHT_WC_LED1_CTRL 0x5e1f
23 #define CHT_WC_LED1_FSM 0x5e20
24 #define CHT_WC_LED1_PWM 0x5e21
26 #define CHT_WC_LED2_CTRL 0x4fdf
27 #define CHT_WC_LED2_FSM 0x4fe0
28 #define CHT_WC_LED2_PWM 0x4fe1
30 #define CHT_WC_LED1_SWCTL BIT(0) /* HW or SW control of charging led */
33 #define CHT_WC_LED2_ON BIT(0)
34 #define CHT_WC_LED_I_MA2_5 (2 << 2) /* LED current limit */
35 #define CHT_WC_LED_I_MASK GENMASK(3, 2) /* LED current limit mask */
37 #define CHT_WC_LED_F_1_4_HZ (0 << 4)
43 #define CHT_WC_LED_EFF_OFF (0 << 1)
56 /* Mask + values for turning the LED on/off */
97 .off_val = 0,
109 struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); in cht_wc_leds_brightness_set() local
112 mutex_lock(&led->mutex); in cht_wc_leds_brightness_set()
115 ret = regmap_update_bits(led->regmap, led->regs->ctrl, in cht_wc_leds_brightness_set()
116 led->regs->on_off_mask, led->regs->off_val); in cht_wc_leds_brightness_set()
117 if (ret < 0) { in cht_wc_leds_brightness_set()
118 dev_err(cdev->dev, "Failed to turn off: %d\n", ret); in cht_wc_leds_brightness_set()
123 ret = regmap_update_bits(led->regmap, led->regs->fsm, in cht_wc_leds_brightness_set()
125 if (ret < 0) in cht_wc_leds_brightness_set()
126 dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); in cht_wc_leds_brightness_set()
128 ret = regmap_write(led->regmap, led->regs->pwm, value); in cht_wc_leds_brightness_set()
129 if (ret < 0) { in cht_wc_leds_brightness_set()
130 dev_err(cdev->dev, "Failed to set brightness: %d\n", ret); in cht_wc_leds_brightness_set()
134 ret = regmap_update_bits(led->regmap, led->regs->ctrl, in cht_wc_leds_brightness_set()
135 led->regs->on_off_mask, led->regs->on_val); in cht_wc_leds_brightness_set()
136 if (ret < 0) in cht_wc_leds_brightness_set()
137 dev_err(cdev->dev, "Failed to turn on: %d\n", ret); in cht_wc_leds_brightness_set()
140 mutex_unlock(&led->mutex); in cht_wc_leds_brightness_set()
146 struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); in cht_wc_leds_brightness_get() local
150 mutex_lock(&led->mutex); in cht_wc_leds_brightness_get()
152 ret = regmap_read(led->regmap, led->regs->ctrl, &val); in cht_wc_leds_brightness_get()
153 if (ret < 0) { in cht_wc_leds_brightness_get()
154 dev_err(cdev->dev, "Failed to read LED CTRL reg: %d\n", ret); in cht_wc_leds_brightness_get()
155 ret = 0; in cht_wc_leds_brightness_get()
159 val &= led->regs->on_off_mask; in cht_wc_leds_brightness_get()
160 if (val != led->regs->on_val) { in cht_wc_leds_brightness_get()
161 ret = 0; in cht_wc_leds_brightness_get()
165 ret = regmap_read(led->regmap, led->regs->pwm, &val); in cht_wc_leds_brightness_get()
166 if (ret < 0) { in cht_wc_leds_brightness_get()
167 dev_err(cdev->dev, "Failed to read LED PWM reg: %d\n", ret); in cht_wc_leds_brightness_get()
168 ret = 0; in cht_wc_leds_brightness_get()
174 mutex_unlock(&led->mutex); in cht_wc_leds_brightness_get()
195 return 0; in cht_wc_leds_get_period()
200 * period < 750 ms - select 2 HZ
201 * 750 ms <= period < 1500 ms - select 1 HZ
202 * 1500 ms <= period < 3000 ms - select 1/2 HZ
203 * 3000 ms <= period < 5000 ms - select 1/4 HZ
204 * 5000 ms <= period - return -1
217 return -1; in cht_wc_leds_find_freq()
225 struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); in cht_wc_leds_set_effect() local
228 mutex_lock(&led->mutex); in cht_wc_leds_set_effect()
235 if (ctrl < 0) { in cht_wc_leds_set_effect()
237 ret = regmap_update_bits(led->regmap, led->regs->fsm, in cht_wc_leds_set_effect()
239 if (ret < 0) in cht_wc_leds_set_effect()
240 dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); in cht_wc_leds_set_effect()
243 *delay_on = *delay_off = 0; in cht_wc_leds_set_effect()
244 ret = -EINVAL; in cht_wc_leds_set_effect()
248 ret = regmap_update_bits(led->regmap, led->regs->fsm, in cht_wc_leds_set_effect()
250 if (ret < 0) in cht_wc_leds_set_effect()
251 dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); in cht_wc_leds_set_effect()
253 /* Set the frequency and make sure the LED is on */ in cht_wc_leds_set_effect()
254 ret = regmap_update_bits(led->regmap, led->regs->ctrl, in cht_wc_leds_set_effect()
255 CHT_WC_LED_F_MASK | led->regs->on_off_mask, in cht_wc_leds_set_effect()
256 ctrl | led->regs->on_val); in cht_wc_leds_set_effect()
257 if (ret < 0) in cht_wc_leds_set_effect()
258 dev_err(cdev->dev, "Failed to update LED CTRL reg: %d\n", ret); in cht_wc_leds_set_effect()
263 mutex_unlock(&led->mutex); in cht_wc_leds_set_effect()
275 * The desired default behavior of LED1 / the charge LED is breathing in cht_wc_leds_blink_set()
278 * when the default "charging-blink-full-solid" trigger is used to in cht_wc_leds_blink_set()
281 if (cdev->flags & LED_INIT_DEFAULT_TRIGGER) { in cht_wc_leds_blink_set()
295 if (repeat > 0 || len != 2 || in cht_wc_leds_pattern_set()
296 pattern[0].brightness != 0 || pattern[1].brightness != 1 || in cht_wc_leds_pattern_set()
297 pattern[0].delta_t != pattern[1].delta_t || in cht_wc_leds_pattern_set()
298 (pattern[0].delta_t != 250 && pattern[0].delta_t != 500 && in cht_wc_leds_pattern_set()
299 pattern[0].delta_t != 1000 && pattern[0].delta_t != 2000)) in cht_wc_leds_pattern_set()
300 return -EINVAL; in cht_wc_leds_pattern_set()
302 delay_off = pattern[0].delta_t; in cht_wc_leds_pattern_set()
310 return cht_wc_leds_brightness_set(cdev, 0); in cht_wc_leds_pattern_clear()
313 static int cht_wc_led_save_regs(struct cht_wc_led *led, in cht_wc_led_save_regs() argument
318 ret = regmap_read(led->regmap, led->regs->ctrl, &saved_regs->ctrl); in cht_wc_led_save_regs()
319 if (ret < 0) in cht_wc_led_save_regs()
322 ret = regmap_read(led->regmap, led->regs->fsm, &saved_regs->fsm); in cht_wc_led_save_regs()
323 if (ret < 0) in cht_wc_led_save_regs()
326 return regmap_read(led->regmap, led->regs->pwm, &saved_regs->pwm); in cht_wc_led_save_regs()
329 static void cht_wc_led_restore_regs(struct cht_wc_led *led, in cht_wc_led_restore_regs() argument
332 regmap_write(led->regmap, led->regs->ctrl, saved_regs->ctrl); in cht_wc_led_restore_regs()
333 regmap_write(led->regmap, led->regs->fsm, saved_regs->fsm); in cht_wc_led_restore_regs()
334 regmap_write(led->regmap, led->regs->pwm, saved_regs->pwm); in cht_wc_led_restore_regs()
339 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); in cht_wc_leds_probe()
346 * connected to a haptic feedback motor rather then a LED. in cht_wc_leds_probe()
347 * So do not register a LED classdev there (LED2 is unused). in cht_wc_leds_probe()
349 if (pmic->cht_wc_model == INTEL_CHT_WC_LENOVO_YT3_X90) in cht_wc_leds_probe()
350 return -ENODEV; in cht_wc_leds_probe()
352 leds = devm_kzalloc(&pdev->dev, sizeof(*leds), GFP_KERNEL); in cht_wc_leds_probe()
354 return -ENOMEM; in cht_wc_leds_probe()
357 * LED1 might be in hw-controlled mode when this driver gets loaded; and in cht_wc_leds_probe()
361 leds->leds[0].regs = &cht_wc_led_regs[0]; in cht_wc_leds_probe()
362 leds->leds[0].regmap = pmic->regmap; in cht_wc_leds_probe()
363 ret = cht_wc_led_save_regs(&leds->leds[0], &leds->led1_initial_regs); in cht_wc_leds_probe()
364 if (ret < 0) in cht_wc_leds_probe()
368 switch (pmic->cht_wc_model) { in cht_wc_leds_probe()
370 leds->leds[0].cdev.default_trigger = "max170xx_battery-charging-blink-full-solid"; in cht_wc_leds_probe()
373 leds->leds[0].cdev.default_trigger = "bq27520-0-charging-blink-full-solid"; in cht_wc_leds_probe()
376 leds->leds[0].cdev.default_trigger = "bq27542-0-charging-blink-full-solid"; in cht_wc_leds_probe()
379 dev_warn(&pdev->dev, "Unknown model, no default charging trigger\n"); in cht_wc_leds_probe()
383 for (i = 0; i < CHT_WC_LED_COUNT; i++) { in cht_wc_leds_probe()
384 struct cht_wc_led *led = &leds->leds[i]; in cht_wc_leds_probe() local
386 led->regs = &cht_wc_led_regs[i]; in cht_wc_leds_probe()
387 led->regmap = pmic->regmap; in cht_wc_leds_probe()
388 mutex_init(&led->mutex); in cht_wc_leds_probe()
389 led->cdev.name = cht_wc_leds_names[i]; in cht_wc_leds_probe()
390 led->cdev.brightness_set_blocking = cht_wc_leds_brightness_set; in cht_wc_leds_probe()
391 led->cdev.brightness_get = cht_wc_leds_brightness_get; in cht_wc_leds_probe()
392 led->cdev.blink_set = cht_wc_leds_blink_set; in cht_wc_leds_probe()
393 led->cdev.pattern_set = cht_wc_leds_pattern_set; in cht_wc_leds_probe()
394 led->cdev.pattern_clear = cht_wc_leds_pattern_clear; in cht_wc_leds_probe()
395 led->cdev.max_brightness = 255; in cht_wc_leds_probe()
397 ret = led_classdev_register(&pdev->dev, &led->cdev); in cht_wc_leds_probe()
398 if (ret < 0) in cht_wc_leds_probe()
403 return 0; in cht_wc_leds_probe()
411 for (i = 0; i < CHT_WC_LED_COUNT; i++) in cht_wc_leds_remove()
412 led_classdev_unregister(&leds->leds[i].cdev); in cht_wc_leds_remove()
414 /* Restore LED1 regs if hw-control was active else leave LED1 off */ in cht_wc_leds_remove()
415 if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL)) in cht_wc_leds_remove()
416 cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs); in cht_wc_leds_remove()
424 for (i = 0; i < CHT_WC_LED_COUNT; i++) in cht_wc_leds_disable()
425 cht_wc_leds_brightness_set(&leds->leds[i].cdev, 0); in cht_wc_leds_disable()
427 /* Restore LED1 regs if hw-control was active else leave LED1 off */ in cht_wc_leds_disable()
428 if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL)) in cht_wc_leds_disable()
429 cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs); in cht_wc_leds_disable()
438 for (i = 0; i < CHT_WC_LED_COUNT; i++) { in cht_wc_leds_suspend()
439 ret = cht_wc_led_save_regs(&leds->leds[i], &leds->leds[i].saved_regs); in cht_wc_leds_suspend()
440 if (ret < 0) in cht_wc_leds_suspend()
445 return 0; in cht_wc_leds_suspend()
454 for (i = 0; i < CHT_WC_LED_COUNT; i++) in cht_wc_leds_resume()
455 cht_wc_led_restore_regs(&leds->leds[i], &leds->leds[i].saved_regs); in cht_wc_leds_resume()
457 return 0; in cht_wc_leds_resume()