mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
leds: leds-rgb13h add pwm control
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: Id8800dc98543d4e082182a027f3fb25dbd30295c
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/pwm.h>
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0)
|
||||
|
||||
@@ -38,6 +39,7 @@ struct rgb13h_led {
|
||||
/* maximum flash timeout */
|
||||
u32 max_flash_tm;
|
||||
u32 intensity;
|
||||
u32 intensity_torch;
|
||||
bool strobe_state;
|
||||
/* brightness cache */
|
||||
u32 torch_brightness;
|
||||
@@ -55,6 +57,9 @@ struct rgb13h_led {
|
||||
|
||||
u32 module_index;
|
||||
const char *module_facing;
|
||||
struct pwm_device *pwm;
|
||||
u32 pwm_period;
|
||||
u32 pwm_duty;
|
||||
};
|
||||
|
||||
static struct rgb13h_led *fled_cdev_to_led(struct led_classdev_flash *fled_cdev)
|
||||
@@ -70,7 +75,24 @@ static struct rgb13h_led *sd_to_led(struct v4l2_subdev *subdev)
|
||||
static int rgb13h_set_output(struct rgb13h_led *led, bool on)
|
||||
{
|
||||
mutex_lock(&led->lock);
|
||||
gpiod_direction_output(led->gpio_en, on);
|
||||
if (!IS_ERR(led->gpio_en))
|
||||
gpiod_direction_output(led->gpio_en, on);
|
||||
if (!IS_ERR(led->pwm)) {
|
||||
if (led->led_mode == V4L2_FLASH_LED_MODE_TORCH)
|
||||
led->pwm_duty = led->pwm_period -
|
||||
led->intensity_torch * led->pwm_period / led->max_mm_current;
|
||||
else
|
||||
led->pwm_duty = led->pwm_period -
|
||||
led->intensity * led->pwm_period / led->max_flash_current;
|
||||
if (on) {
|
||||
pwm_config(led->pwm, led->pwm_duty, led->pwm_period);
|
||||
pwm_enable(led->pwm);
|
||||
dev_dbg(&led->pdev->dev, "led pwm duty=%d, period=%d, polarity=%d\n",
|
||||
led->pwm_duty, led->pwm_period, led->pwm->args.polarity);
|
||||
} else {
|
||||
pwm_disable(led->pwm);
|
||||
}
|
||||
}
|
||||
if (!on) {
|
||||
led->strobe_state = false;
|
||||
if (led->waiting) {
|
||||
@@ -187,7 +209,17 @@ static int rgb13h_led_parse_dt(struct rgb13h_led *led,
|
||||
led->gpio_en = devm_gpiod_get(dev, "enable", GPIOD_ASIS);
|
||||
if (IS_ERR(led->gpio_en)) {
|
||||
ret = PTR_ERR(led->gpio_en);
|
||||
dev_err(dev, "Unable to claim enable-gpio\n");
|
||||
dev_info(dev, "Unable to claim enable-gpio\n");
|
||||
}
|
||||
led->pwm = devm_pwm_get(dev, NULL);
|
||||
if (IS_ERR(led->pwm)) {
|
||||
ret = PTR_ERR(led->pwm);
|
||||
dev_info(dev, "Unable to get pwm device\n");
|
||||
} else {
|
||||
led->pwm_period = led->pwm->args.period;
|
||||
}
|
||||
if (IS_ERR(led->gpio_en) && IS_ERR(led->pwm)) {
|
||||
dev_err(dev, "Neither enable-gpio nor pwm can be get,return error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -199,6 +231,11 @@ static int rgb13h_led_parse_dt(struct rgb13h_led *led,
|
||||
if (ret < 0)
|
||||
dev_warn(dev,
|
||||
"led-max-microamp DT property missing\n");
|
||||
if (led->max_mm_current <= 0) {
|
||||
led->max_mm_current = 20000;
|
||||
dev_warn(dev,
|
||||
"get led-max-microamp error value, used default value 20000\n");
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(child_node, "flash-max-microamp",
|
||||
&led->max_flash_current);
|
||||
@@ -207,6 +244,11 @@ static int rgb13h_led_parse_dt(struct rgb13h_led *led,
|
||||
"flash-max-microamp DT property missing\n");
|
||||
return ret;
|
||||
}
|
||||
if (led->max_flash_current <= 0) {
|
||||
led->max_flash_current = 20000;
|
||||
dev_warn(dev,
|
||||
"get flash-max-microamp error value, used default value 20000\n");
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(child_node, "flash-max-timeout-us",
|
||||
&led->max_flash_tm);
|
||||
@@ -215,6 +257,11 @@ static int rgb13h_led_parse_dt(struct rgb13h_led *led,
|
||||
"flash-max-timeout-us DT property missing\n");
|
||||
return ret;
|
||||
}
|
||||
if (led->max_flash_tm <= 0) {
|
||||
led->max_flash_tm = 1000000;
|
||||
dev_warn(dev,
|
||||
"get flash-max-timeout-us error value, used default value 1s\n");
|
||||
}
|
||||
|
||||
*sub_node = child_node;
|
||||
return ret;
|
||||
@@ -262,9 +309,11 @@ static int rgb13h_get_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ctrl->val = led->strobe_state;
|
||||
break;
|
||||
case V4L2_CID_FLASH_INTENSITY:
|
||||
case V4L2_CID_FLASH_TORCH_INTENSITY:
|
||||
ctrl->val = led->intensity;
|
||||
break;
|
||||
case V4L2_CID_FLASH_TORCH_INTENSITY:
|
||||
ctrl->val = led->intensity_torch;
|
||||
break;
|
||||
case V4L2_CID_FLASH_LED_MODE:
|
||||
ctrl->val = led->led_mode;
|
||||
break;
|
||||
@@ -287,7 +336,7 @@ static int rgb13h_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
led->led_mode = ctrl->val;
|
||||
rgb13h_set_output(led, LED_OFF);
|
||||
if (led->led_mode == V4L2_FLASH_LED_MODE_TORCH)
|
||||
return rgb13h_set_output(led, !!led->intensity);
|
||||
return rgb13h_set_output(led, LED_ON);
|
||||
break;
|
||||
|
||||
case V4L2_CID_FLASH_STROBE_SOURCE:
|
||||
@@ -305,12 +354,15 @@ static int rgb13h_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_FLASH_TIMEOUT:
|
||||
return rgb13h_led_flash_timeout_set(&led->fled_cdev, ctrl->val);
|
||||
case V4L2_CID_FLASH_INTENSITY:
|
||||
if (led->led_mode != V4L2_FLASH_LED_MODE_FLASH)
|
||||
return -EBUSY;
|
||||
led->intensity = ctrl->val;
|
||||
break;
|
||||
case V4L2_CID_FLASH_TORCH_INTENSITY:
|
||||
if (led->led_mode != V4L2_FLASH_LED_MODE_TORCH)
|
||||
break;
|
||||
led->intensity = ctrl->val;
|
||||
return rgb13h_set_output(led, !!ctrl->val);
|
||||
led->intensity_torch = ctrl->val;
|
||||
return rgb13h_set_output(led, LED_ON);
|
||||
default:
|
||||
dev_err(&led->pdev->dev,
|
||||
"ctrl 0x%x not supported\n", ctrl->id);
|
||||
@@ -358,18 +410,24 @@ static int rgb13h_init_controls(struct rgb13h_led *led)
|
||||
led->max_flash_tm);
|
||||
led->timeout = led->max_flash_tm;
|
||||
/* V4L2_CID_FLASH_INTENSITY */
|
||||
v4l2_ctrl_new_std(&led->ctrls, &rgb13h_ctrl_ops,
|
||||
ctrl = v4l2_ctrl_new_std(&led->ctrls, &rgb13h_ctrl_ops,
|
||||
V4L2_CID_FLASH_INTENSITY, 0,
|
||||
led->max_flash_current,
|
||||
led->max_flash_current,
|
||||
1,
|
||||
led->max_flash_current);
|
||||
if (ctrl && IS_ERR(led->pwm))
|
||||
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||
led->intensity = led->max_flash_current;
|
||||
/* V4L2_CID_FLASH_TORCH_INTENSITY */
|
||||
v4l2_ctrl_new_std(&led->ctrls, &rgb13h_ctrl_ops,
|
||||
ctrl = v4l2_ctrl_new_std(&led->ctrls, &rgb13h_ctrl_ops,
|
||||
V4L2_CID_FLASH_TORCH_INTENSITY, 0,
|
||||
led->max_mm_current,
|
||||
led->max_mm_current,
|
||||
1,
|
||||
led->max_mm_current);
|
||||
led->intensity = led->max_mm_current;
|
||||
if (ctrl && IS_ERR(led->pwm))
|
||||
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||
led->intensity_torch = led->max_mm_current;
|
||||
|
||||
/* V4L2_CID_FLASH_FAULT */
|
||||
ctrl = v4l2_ctrl_new_std(&led->ctrls, &rgb13h_ctrl_ops,
|
||||
V4L2_CID_FLASH_FAULT, 0,
|
||||
|
||||
Reference in New Issue
Block a user