* [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features
@ 2022-04-28 9:32 cy_huang
2022-04-28 9:32 ` [PATCH 1/4] leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness set cy_huang
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: cy_huang @ 2022-04-28 9:32 UTC (permalink / raw)
To: pavel, matthias.bgg
Cc: cy_huang, jacek.anaszewski, gene_chen, linux-leds,
linux-arm-kernel, linux-mediatek, linux-kernel
From: ChiYuan Huang <cy_huang@richtek.com>
This patch series includes some fixes and add supproted ISNK hardware features.
From MT6360, ISNK can support three modes (CC, PWM, and Breath). The previous
one can only support CC mode.
ChiYuan Huang (4):
leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness
set
leds: flash: mt6360: Remove unused dependency in Kconfig
leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming
mode support
leds: flash: mt6360: Add mt6360 isnk channel hardwre breath mode
support
drivers/leds/flash/Kconfig | 4 +-
drivers/leds/flash/leds-mt6360.c | 413 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 410 insertions(+), 7 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness set
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
@ 2022-04-28 9:32 ` cy_huang
2022-04-28 9:32 ` [PATCH 2/4] leds: flash: mt6360: Remove unused dependency in Kconfig cy_huang
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: cy_huang @ 2022-04-28 9:32 UTC (permalink / raw)
To: pavel, matthias.bgg
Cc: cy_huang, jacek.anaszewski, gene_chen, linux-leds,
linux-arm-kernel, linux-mediatek, linux-kernel
From: ChiYuan Huang <cy_huang@richtek.com>
Fix the wrong enable_reg in multicolor brightness set.
Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
drivers/leds/flash/leds-mt6360.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
index e1066a5..712cd46 100644
--- a/drivers/leds/flash/leds-mt6360.c
+++ b/drivers/leds/flash/leds-mt6360.c
@@ -115,7 +115,8 @@ static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
struct mc_subled *subled = mccdev->subled_info + i;
real_bright = min(lcdev->max_brightness, subled->brightness);
- ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(i),
+ ret = regmap_update_bits(priv->regmap,
+ MT6360_REG_ISNK(subled->channel),
MT6360_ISNK_MASK, real_bright);
if (ret)
goto out;
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] leds: flash: mt6360: Remove unused dependency in Kconfig
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
2022-04-28 9:32 ` [PATCH 1/4] leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness set cy_huang
@ 2022-04-28 9:32 ` cy_huang
2022-04-28 9:32 ` [PATCH 3/4] leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming mode support cy_huang
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: cy_huang @ 2022-04-28 9:32 UTC (permalink / raw)
To: pavel, matthias.bgg
Cc: cy_huang, jacek.anaszewski, gene_chen, linux-leds,
linux-arm-kernel, linux-mediatek, linux-kernel
From: ChiYuan Huang <cy_huang@richtek.com>
Kconfig already guarantee LED_CLASS_FLASH will be selected.
Remove useless dependency for LEDS_CLASS/LEDS_CLASS_FLASH.
Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
drivers/leds/flash/Kconfig | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig
index d3eb689..38b325c 100644
--- a/drivers/leds/flash/Kconfig
+++ b/drivers/leds/flash/Kconfig
@@ -50,8 +50,7 @@ config LEDS_MAX77693
config LEDS_MT6360
tristate "LED Support for Mediatek MT6360 PMIC"
- depends on LEDS_CLASS && OF
- depends on LEDS_CLASS_FLASH || !LEDS_CLASS_FLASH
+ depends on OF
depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR
depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
depends on MFD_MT6360
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming mode support
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
2022-04-28 9:32 ` [PATCH 1/4] leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness set cy_huang
2022-04-28 9:32 ` [PATCH 2/4] leds: flash: mt6360: Remove unused dependency in Kconfig cy_huang
@ 2022-04-28 9:32 ` cy_huang
2022-04-28 9:32 ` [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath " cy_huang
2022-06-14 7:36 ` [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features ChiYuan Huang
4 siblings, 0 replies; 8+ messages in thread
From: cy_huang @ 2022-04-28 9:32 UTC (permalink / raw)
To: pavel, matthias.bgg
Cc: cy_huang, jacek.anaszewski, gene_chen, linux-leds,
linux-arm-kernel, linux-mediatek, linux-kernel
From: ChiYuan Huang <cy_huang@richtek.com>
Add mt6360 isnk channel hardware timer dimming mode support.
Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
drivers/leds/flash/leds-mt6360.c | 209 +++++++++++++++++++++++++++++++++++++--
1 file changed, 203 insertions(+), 6 deletions(-)
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
index 712cd46..8fe3dc4 100644
--- a/drivers/leds/flash/leds-mt6360.c
+++ b/drivers/leds/flash/leds-mt6360.c
@@ -24,9 +24,19 @@ enum {
MT6360_MAX_LEDS
};
+#define MT6360_ISNK_PWM_MODE 0
+#define MT6360_ISNK_CC_MODE 2
+
#define MT6360_REG_RGBEN 0x380
#define MT6360_REG_ISNK(_led_no) (0x381 + (_led_no))
+#define MT6360_REG_DIM(_led_no) (0x385 + (_led_no))
+#define MT6360_REG_FREQ1 0x389
+#define MT6360_REG_FREQ2 0x38A
#define MT6360_ISNK_ENMASK(_led_no) BIT(7 - (_led_no))
+#define MT6360_FREQ13_MASK GENMASK(7, 5)
+#define MT6360_FREQ2_MASK GENMASK(4, 2)
+#define MT6360_ISNK_MODE_MASK GENMASK(7, 6)
+#define MT6360_ISNK_MODE_SHFT 6
#define MT6360_ISNK_MASK GENMASK(4, 0)
#define MT6360_CHRINDSEL_MASK BIT(3)
@@ -98,13 +108,128 @@ struct mt6360_priv {
struct mt6360_led leds[];
};
+static int mt6360_get_selected_freq_duty(unsigned long on, unsigned long off,
+ unsigned int *fsel, unsigned int *dsel)
+{
+ static const unsigned int freq_ms[] = { 8000, 4000, 2000, 1000,
+ 500, 250, 8, 4 };
+ unsigned int sum = on + off;
+ int i;
+
+ /* Check if val is less than the smallest or larger then the largest */
+ if (sum > freq_ms[0] || sum < freq_ms[ARRAY_SIZE(freq_ms) - 1])
+ return -EINVAL;
+
+ /* Find the frequency for less or equal one */
+ for (i = 0; i < ARRAY_SIZE(freq_ms) - 1; i++) {
+ if (sum >= freq_ms[i])
+ break;
+ }
+
+ *fsel = i;
+ *dsel = on * 255 / sum;
+ return 0;
+}
+
+static int mt6360_set_pwm_dimming_param(struct mt6360_priv *priv,
+ unsigned int led_no, unsigned int fsel,
+ unsigned int dsel)
+{
+ unsigned int freq_reg, freq_mask, freq_shift;
+ int ret;
+
+ switch (led_no) {
+ case MT6360_LED_ISNK1:
+ freq_reg = MT6360_REG_FREQ1;
+ freq_mask = MT6360_FREQ13_MASK;
+ break;
+ case MT6360_LED_ISNK2:
+ freq_reg = MT6360_REG_FREQ1;
+ freq_mask = MT6360_FREQ2_MASK;
+ break;
+ case MT6360_LED_ISNK3:
+ freq_reg = MT6360_REG_FREQ2;
+ freq_mask = MT6360_FREQ13_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ freq_shift = ffs(freq_mask) - 1;
+
+ ret = regmap_update_bits(priv->regmap, freq_reg, freq_mask,
+ fsel << freq_shift);
+ if (ret)
+ return ret;
+
+ return regmap_write(priv->regmap, MT6360_REG_DIM(led_no), dsel);
+}
+
+static int mt6360_mc_blink_set(struct led_classdev *lcdev, unsigned long *don,
+ unsigned long *doff)
+{
+ struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
+ struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc);
+ struct mt6360_priv *priv = led->priv;
+ unsigned int freq_sel, duty_sel;
+ u8 mc_reg[3];
+ int i, ret;
+
+ if (!*don && !*doff)
+ *don = *doff = 500;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_raw_read(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+ if (ret)
+ goto out;
+
+ /* Configure all subleds to CC mode first */
+ for (i = 0; i < mccdev->num_colors; i++) {
+ struct mc_subled *subled = mccdev->subled_info + i;
+ int ch_idx = subled->channel;
+
+ mc_reg[ch_idx] &= ~MT6360_ISNK_MODE_MASK;
+ mc_reg[ch_idx] |= MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_raw_write(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+ if (ret)
+ goto out;
+
+ /* Get the desired selector for frequency and duty */
+ ret = mt6360_get_selected_freq_duty(*don, *doff, &freq_sel, &duty_sel);
+ if (ret)
+ goto out;
+
+ /* Configure all subleds dim freq/duty and change to PWM mode */
+ for (i = 0; i < mccdev->num_colors; i++) {
+ struct mc_subled *subled = mccdev->subled_info + i;
+ int ch_idx = subled->channel;
+
+ ret = mt6360_set_pwm_dimming_param(priv, ch_idx, freq_sel,
+ duty_sel);
+ if (ret)
+ goto out;
+
+ mc_reg[ch_idx] &= ~MT6360_ISNK_MODE_MASK;
+ mc_reg[ch_idx] |= MT6360_ISNK_PWM_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_raw_write(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
enum led_brightness level)
{
struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc);
struct mt6360_priv *priv = led->priv;
- u32 real_bright, enable_mask = 0, enable = 0;
+ u32 real_bright, enable_mask = 0, enable = 0, val;
int i, ret;
mutex_lock(&priv->lock);
@@ -113,11 +238,25 @@ static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
for (i = 0; i < mccdev->num_colors; i++) {
struct mc_subled *subled = mccdev->subled_info + i;
+ unsigned int bright_reg = MT6360_REG_ISNK(subled->channel);
real_bright = min(lcdev->max_brightness, subled->brightness);
- ret = regmap_update_bits(priv->regmap,
- MT6360_REG_ISNK(subled->channel),
- MT6360_ISNK_MASK, real_bright);
+
+ ret = regmap_read(priv->regmap, bright_reg, &val);
+ if (ret)
+ goto out;
+
+ /* Assign the new brightness value */
+ val &= ~MT6360_ISNK_MASK;
+ val |= (real_bright & MT6360_ISNK_MASK);
+
+ /* If LED_OFF, always configure back to CC mode */
+ if (level == LED_OFF) {
+ val &= ~MT6360_ISNK_MODE_MASK;
+ val |= MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_write(priv->regmap, bright_reg, val);
if (ret)
goto out;
@@ -134,6 +273,44 @@ static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
return ret;
}
+static int mt6360_isnk_blink_set(struct led_classdev *lcdev, unsigned long *don,
+ unsigned long *doff)
+{
+ struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk);
+ struct mt6360_priv *priv = led->priv;
+ unsigned int freq_sel, duty_sel;
+ int ret;
+
+ if (!*don && !*doff)
+ *don = *doff = 500;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ MT6360_ISNK_MODE_MASK,
+ MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT);
+ if (ret)
+ goto out;
+
+ /* Get the desired selector for frequency and duty */
+ ret = mt6360_get_selected_freq_duty(*don, *doff, &freq_sel, &duty_sel);
+ if (ret)
+ goto out;
+
+ ret = mt6360_set_pwm_dimming_param(priv, led->led_no, freq_sel,
+ duty_sel);
+ if (ret)
+ goto out;
+
+ ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ MT6360_ISNK_MODE_MASK,
+ MT6360_ISNK_PWM_MODE << MT6360_ISNK_MODE_SHFT);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static int mt6360_isnk_brightness_set(struct led_classdev *lcdev,
enum led_brightness level)
{
@@ -141,12 +318,27 @@ static int mt6360_isnk_brightness_set(struct led_classdev *lcdev,
struct mt6360_priv *priv = led->priv;
u32 enable_mask = MT6360_ISNK_ENMASK(led->led_no);
u32 val = level ? MT6360_ISNK_ENMASK(led->led_no) : 0;
+ unsigned int bright_val;
int ret;
mutex_lock(&priv->lock);
- ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
- MT6360_ISNK_MASK, level);
+ ret = regmap_read(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ &bright_val);
+ if (ret)
+ goto out;
+
+ bright_val &= ~MT6360_ISNK_MASK;
+ bright_val |= (level & MT6360_ISNK_MASK);
+
+ /* If LED_OFF, always configure back to CC mode */
+ if (led->led_no != MT6360_LED_ISNKML && level == LED_OFF) {
+ bright_val &= ~MT6360_ISNK_MODE_MASK;
+ bright_val |= MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_write(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ bright_val);
if (ret)
goto out;
@@ -666,6 +858,7 @@ static int mt6360_init_isnk_properties(struct mt6360_led *led,
lcdev = &led->mc.led_cdev;
lcdev->brightness_set_blocking = mt6360_mc_brightness_set;
+ lcdev->blink_set = mt6360_mc_blink_set;
} else {
if (led->led_no == MT6360_LED_ISNKML) {
step_uA = MT6360_ISNKML_STEPUA;
@@ -674,6 +867,10 @@ static int mt6360_init_isnk_properties(struct mt6360_led *led,
lcdev = &led->isnk;
lcdev->brightness_set_blocking = mt6360_isnk_brightness_set;
+
+ /* Suppose only ISNK1/2/3 support mode change */
+ if (led->led_no != MT6360_LED_ISNKML)
+ lcdev->blink_set = mt6360_isnk_blink_set;
}
ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath mode support
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
` (2 preceding siblings ...)
2022-04-28 9:32 ` [PATCH 3/4] leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming mode support cy_huang
@ 2022-04-28 9:32 ` cy_huang
2022-04-28 11:50 ` Matti Vaittinen
2022-06-14 7:36 ` [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features ChiYuan Huang
4 siblings, 1 reply; 8+ messages in thread
From: cy_huang @ 2022-04-28 9:32 UTC (permalink / raw)
To: pavel, matthias.bgg
Cc: cy_huang, jacek.anaszewski, gene_chen, linux-leds,
linux-arm-kernel, linux-mediatek, linux-kernel
From: ChiYuan Huang <cy_huang@richtek.com>
Add mt6360 isnk channel hardware breath mode support.
Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
drivers/leds/flash/Kconfig | 1 +
drivers/leds/flash/leds-mt6360.c | 207 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig
index 38b325c..039ff50 100644
--- a/drivers/leds/flash/Kconfig
+++ b/drivers/leds/flash/Kconfig
@@ -54,6 +54,7 @@ config LEDS_MT6360
depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR
depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
depends on MFD_MT6360
+ select LINEAR_RANGE
help
This option enables support for dual Flash LED drivers found on
Mediatek MT6360 PMIC.
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
index 8fe3dc4..b4a702c 100644
--- a/drivers/leds/flash/leds-mt6360.c
+++ b/drivers/leds/flash/leds-mt6360.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/led-class-flash.h>
#include <linux/led-class-multicolor.h>
+#include <linux/linear_range.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
@@ -24,7 +25,14 @@ enum {
MT6360_MAX_LEDS
};
+enum mt6360_iled_range {
+ MT6360_ILED_RANGE_TRF12ON = 0, /* tr1, tr2, ton, tf1, tf2 */
+ MT6360_ILED_RANGE_TOFF,
+ MT6360_ILED_RANGE_MAX
+};
+
#define MT6360_ISNK_PWM_MODE 0
+#define MT6360_ISNK_BREATH_MODE 1
#define MT6360_ISNK_CC_MODE 2
#define MT6360_REG_RGBEN 0x380
@@ -32,6 +40,7 @@ enum {
#define MT6360_REG_DIM(_led_no) (0x385 + (_led_no))
#define MT6360_REG_FREQ1 0x389
#define MT6360_REG_FREQ2 0x38A
+#define MT6360_REG_ISNK_BREATH(_ledno) (0x38B + ((_ledno) * 3))
#define MT6360_ISNK_ENMASK(_led_no) BIT(7 - (_led_no))
#define MT6360_FREQ13_MASK GENMASK(7, 5)
#define MT6360_FREQ2_MASK GENMASK(4, 2)
@@ -39,6 +48,14 @@ enum {
#define MT6360_ISNK_MODE_SHFT 6
#define MT6360_ISNK_MASK GENMASK(4, 0)
#define MT6360_CHRINDSEL_MASK BIT(3)
+#define MT6360_ISNK_TR1_MASK GENMASK(7, 4)
+#define MT6360_ISNK_TR2_MASK GENMASK(3, 0)
+#define MT6360_ISNK_TF1_MASK GENMASK(7, 4)
+#define MT6360_ISNK_TF2_MASK GENMASK(3, 0)
+#define MT6360_ISNK_TON_MASK GENMASK(7, 4)
+#define MT6360_ISNK_TOFF_MASK GENMASK(3, 0)
+#define MT6360_BREATH_PATTERN_CNT 6
+#define MT6360_BREATH_CFGRG_CNT 3
/* Virtual definition for multicolor */
#define MT6360_VIRTUAL_MULTICOLOR (MT6360_MAX_LEDS + 1)
@@ -108,6 +125,46 @@ struct mt6360_priv {
struct mt6360_led leds[];
};
+static int mt6360_gen_breath_reg_config(struct led_pattern *pattern, u32 len,
+ u8 *vals, int val_len)
+{
+ static const struct linear_range tranges[MT6360_ILED_RANGE_MAX] = {
+ { 125, 0, 15, 250 }, /* tr/f12 and ton, unit: millisecond */
+ { 250, 0, 15, 500 }, /* toff, unit: millisecond */
+ };
+ static const struct {
+ int rg_offset;
+ int mask;
+ enum mt6360_iled_range rid;
+ } params[MT6360_BREATH_PATTERN_CNT] = {
+ { 0, MT6360_ISNK_TR1_MASK, MT6360_ILED_RANGE_TRF12ON },
+ { 0, MT6360_ISNK_TR2_MASK, MT6360_ILED_RANGE_TRF12ON },
+ { 2, MT6360_ISNK_TON_MASK, MT6360_ILED_RANGE_TRF12ON },
+ { 1, MT6360_ISNK_TF1_MASK, MT6360_ILED_RANGE_TRF12ON },
+ { 1, MT6360_ISNK_TF2_MASK, MT6360_ILED_RANGE_TRF12ON },
+ { 2, MT6360_ISNK_TOFF_MASK, MT6360_ILED_RANGE_TOFF }
+ };
+ unsigned int sel;
+ int i, shift;
+
+ /* Must contain 6 tuples to configure tr1, tr2, ton, tf1, tf2, toff */
+ if (len != MT6360_BREATH_PATTERN_CNT ||
+ val_len != MT6360_BREATH_CFGRG_CNT)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(params); i++) {
+ linear_range_get_selector_within(tranges + params[i].rid,
+ pattern[i].delta_t, &sel);
+
+ shift = ffs(params[i].mask) - 1;
+
+ vals[params[i].rg_offset] &= ~params[i].mask;
+ vals[params[i].rg_offset] |= sel << shift;
+ }
+
+ return 0;
+}
+
static int mt6360_get_selected_freq_duty(unsigned long on, unsigned long off,
unsigned int *fsel, unsigned int *dsel)
{
@@ -165,6 +222,95 @@ static int mt6360_set_pwm_dimming_param(struct mt6360_priv *priv,
return regmap_write(priv->regmap, MT6360_REG_DIM(led_no), dsel);
}
+static int mt6360_mc_pattern_set(struct led_classdev *lcdev,
+ struct led_pattern *pattern, u32 len,
+ int repeat)
+{
+ struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
+ struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc);
+ struct mt6360_priv *priv = led->priv;
+ unsigned int reg_base;
+ u8 cfg_vals[MT6360_BREATH_CFGRG_CNT] = {0};
+ u8 mc_reg[3];
+ int i, ret;
+
+ ret = mt6360_gen_breath_reg_config(pattern, len, cfg_vals,
+ sizeof(cfg_vals));
+ if (ret)
+ return ret;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_raw_read(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+ if (ret)
+ goto out;
+
+ /* Configure all subleds to CC mode first */
+ for (i = 0; i < mccdev->num_colors; i++) {
+ struct mc_subled *subled = mccdev->subled_info + i;
+ int ch_idx = subled->channel;
+
+ mc_reg[ch_idx] &= ~MT6360_ISNK_MODE_MASK;
+ mc_reg[ch_idx] |= MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_raw_write(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < mccdev->num_colors; i++) {
+ struct mc_subled *subled = mccdev->subled_info + i;
+ int ch_idx = subled->channel;
+
+ reg_base = MT6360_REG_ISNK_BREATH(ch_idx);
+
+ ret = regmap_raw_write(priv->regmap, reg_base, cfg_vals,
+ sizeof(cfg_vals));
+ if (ret)
+ goto out;
+
+ mc_reg[ch_idx] &= ~MT6360_ISNK_MODE_MASK;
+ mc_reg[ch_idx] |=
+ MT6360_ISNK_BREATH_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_raw_write(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
+static int mt6360_mc_pattern_clear(struct led_classdev *lcdev)
+{
+ struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
+ struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc);
+ struct mt6360_priv *priv = led->priv;
+ u8 mc_reg[3];
+ int i, ret;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_raw_read(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+ if (ret)
+ goto out;
+
+ /* Configure all subleds to CC mode first */
+ for (i = 0; i < mccdev->num_colors; i++) {
+ struct mc_subled *subled = mccdev->subled_info + i;
+ int ch_idx = subled->channel;
+
+ mc_reg[ch_idx] &= ~MT6360_ISNK_MODE_MASK;
+ mc_reg[ch_idx] |= MT6360_ISNK_CC_MODE << MT6360_ISNK_MODE_SHFT;
+ }
+
+ ret = regmap_raw_write(priv->regmap, MT6360_REG_ISNK(0), mc_reg, 3);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static int mt6360_mc_blink_set(struct led_classdev *lcdev, unsigned long *don,
unsigned long *doff)
{
@@ -273,6 +419,60 @@ static int mt6360_mc_brightness_set(struct led_classdev *lcdev,
return ret;
}
+static int mt6360_isnk_pattern_set(struct led_classdev *lcdev,
+ struct led_pattern *pattern, u32 len,
+ int repeat)
+{
+ struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk);
+ struct mt6360_priv *priv = led->priv;
+ unsigned int reg_base = MT6360_REG_ISNK_BREATH(led->led_no);
+ u8 cfg_vals[MT6360_BREATH_CFGRG_CNT] = {0};
+ int ret;
+
+ ret = mt6360_gen_breath_reg_config(pattern, len, cfg_vals,
+ sizeof(cfg_vals));
+ if (ret)
+ return ret;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_raw_write(priv->regmap, reg_base, cfg_vals,
+ sizeof(cfg_vals));
+ if (ret)
+ goto out;
+
+ /* Toggle mode change to make new parameter applied */
+ ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ MT6360_ISNK_MODE_MASK, MT6360_ISNK_CC_MODE
+ << MT6360_ISNK_MODE_SHFT);
+ if (ret)
+ goto out;
+
+ ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ MT6360_ISNK_MODE_MASK, MT6360_ISNK_BREATH_MODE
+ << MT6360_ISNK_MODE_SHFT);
+
+out:
+ mutex_unlock(&priv->lock);
+ return 0;
+}
+
+static int mt6360_isnk_pattern_clear(struct led_classdev *lcdev)
+{
+ struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk);
+ struct mt6360_priv *priv = led->priv;
+ int ret;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no),
+ MT6360_ISNK_MODE_MASK, MT6360_ISNK_CC_MODE
+ << MT6360_ISNK_MODE_SHFT);
+
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static int mt6360_isnk_blink_set(struct led_classdev *lcdev, unsigned long *don,
unsigned long *doff)
{
@@ -859,6 +1059,8 @@ static int mt6360_init_isnk_properties(struct mt6360_led *led,
lcdev = &led->mc.led_cdev;
lcdev->brightness_set_blocking = mt6360_mc_brightness_set;
lcdev->blink_set = mt6360_mc_blink_set;
+ lcdev->pattern_set = mt6360_mc_pattern_set;
+ lcdev->pattern_clear = mt6360_mc_pattern_clear;
} else {
if (led->led_no == MT6360_LED_ISNKML) {
step_uA = MT6360_ISNKML_STEPUA;
@@ -869,8 +1071,11 @@ static int mt6360_init_isnk_properties(struct mt6360_led *led,
lcdev->brightness_set_blocking = mt6360_isnk_brightness_set;
/* Suppose only ISNK1/2/3 support mode change */
- if (led->led_no != MT6360_LED_ISNKML)
+ if (led->led_no != MT6360_LED_ISNKML) {
lcdev->blink_set = mt6360_isnk_blink_set;
+ lcdev->pattern_set = mt6360_isnk_pattern_set;
+ lcdev->pattern_clear = mt6360_isnk_pattern_clear;
+ }
}
ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath mode support
2022-04-28 9:32 ` [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath " cy_huang
@ 2022-04-28 11:50 ` Matti Vaittinen
2022-04-28 14:57 ` ChiYuan Huang
0 siblings, 1 reply; 8+ messages in thread
From: Matti Vaittinen @ 2022-04-28 11:50 UTC (permalink / raw)
To: cy_huang
Cc: Pavel Machek, Matthias Brugger, ChiYuan Huang, Jacek Anaszewski,
Gene Chen, linux-leds, linux-arm Mailing List,
moderated list:ARM/Mediatek SoC support,
Linux Kernel Mailing List
Hi ChiYuan!
On Thu, Apr 28, 2022 at 1:03 PM cy_huang <u0084500@gmail.com> wrote:
> From: ChiYuan Huang <cy_huang@richtek.com>
>
> Add mt6360 isnk channel hardware breath mode support.
>
> Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
>
> +static int mt6360_gen_breath_reg_config(struct led_pattern *pattern, u32 len,
> + u8 *vals, int val_len)
> +{
> + static const struct linear_range tranges[MT6360_ILED_RANGE_MAX] = {
> + { 125, 0, 15, 250 }, /* tr/f12 and ton, unit: millisecond */
> + { 250, 0, 15, 500 }, /* toff, unit: millisecond */
> + };
It's nice to see you are using the linear_ranges helpers here! Just a
minor remark - do you think you could use field names in linear_ranges
initializations? That would make it less likely the driver breaks if
someone changes the struct linear_range definition. Eg, use something
like:
static const struct linear_range tranges[MT6360_ILED_RANGE_MAX] = {
/* tr/f12 and ton, unit: millisecond */
{ .min = 125, .min_sel = 0, .max_sel = 15, .step = 250 },
/* toff, unit: millisecond */
{ .min = 250, .min_sel = 0, .max_sel = 15, .step = 500 },
};
Do you think that would work?
Best Regards
-- Matti
--
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland
~~ When things go utterly wrong vim users can always type :help! ~~
Discuss - Estimate - Plan - Report and finally accomplish this:
void do_work(int time) __attribute__ ((const));
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath mode support
2022-04-28 11:50 ` Matti Vaittinen
@ 2022-04-28 14:57 ` ChiYuan Huang
0 siblings, 0 replies; 8+ messages in thread
From: ChiYuan Huang @ 2022-04-28 14:57 UTC (permalink / raw)
To: Matti Vaittinen
Cc: Pavel Machek, Matthias Brugger, ChiYuan Huang, Jacek Anaszewski,
Gene Chen, Linux LED Subsystem, linux-arm Mailing List,
moderated list:ARM/Mediatek SoC support,
Linux Kernel Mailing List
Matti Vaittinen <mazziesaccount@gmail.com> 於 2022年4月28日 週四 下午7:51寫道:
>
> Hi ChiYuan!
>
> On Thu, Apr 28, 2022 at 1:03 PM cy_huang <u0084500@gmail.com> wrote:
> > From: ChiYuan Huang <cy_huang@richtek.com>
> >
> > Add mt6360 isnk channel hardware breath mode support.
> >
> > Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
> >
> > +static int mt6360_gen_breath_reg_config(struct led_pattern *pattern, u32 len,
> > + u8 *vals, int val_len)
> > +{
> > + static const struct linear_range tranges[MT6360_ILED_RANGE_MAX] = {
> > + { 125, 0, 15, 250 }, /* tr/f12 and ton, unit: millisecond */
> > + { 250, 0, 15, 500 }, /* toff, unit: millisecond */
> > + };
>
> It's nice to see you are using the linear_ranges helpers here! Just a
> minor remark - do you think you could use field names in linear_ranges
> initializations? That would make it less likely the driver breaks if
> someone changes the struct linear_range definition. Eg, use something
> like:
>
> static const struct linear_range tranges[MT6360_ILED_RANGE_MAX] = {
> /* tr/f12 and ton, unit: millisecond */
> { .min = 125, .min_sel = 0, .max_sel = 15, .step = 250 },
> /* toff, unit: millisecond */
> { .min = 250, .min_sel = 0, .max_sel = 15, .step = 500 },
> };
>
> Do you think that would work?
Sure, it works.
To specify the field name can be compatible if the struct changes in the future.
Thanks.
>
> Best Regards
> -- Matti
>
> --
>
> Matti Vaittinen
> Linux kernel developer at ROHM Semiconductors
> Oulu Finland
>
> ~~ When things go utterly wrong vim users can always type :help! ~~
>
> Discuss - Estimate - Plan - Report and finally accomplish this:
> void do_work(int time) __attribute__ ((const));
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
` (3 preceding siblings ...)
2022-04-28 9:32 ` [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath " cy_huang
@ 2022-06-14 7:36 ` ChiYuan Huang
4 siblings, 0 replies; 8+ messages in thread
From: ChiYuan Huang @ 2022-06-14 7:36 UTC (permalink / raw)
To: Pavel Machek, Matthias Brugger
Cc: cy_huang, Jacek Anaszewski, Gene Chen, Linux LED Subsystem,
linux-arm Mailing List, moderated list:ARM/Mediatek SoC support,
lkml
Hi:
Is there any comment about this patch series?
One is for the fix, second is Kconfig refine, others are for the HW
PWM/Breath feature added.
cy_huang <u0084500@gmail.com> 於 2022年4月28日 週四 下午5:33寫道:
>
> From: ChiYuan Huang <cy_huang@richtek.com>
>
> This patch series includes some fixes and add supproted ISNK hardware features.
> From MT6360, ISNK can support three modes (CC, PWM, and Breath). The previous
> one can only support CC mode.
>
> ChiYuan Huang (4):
> leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness
> set
> leds: flash: mt6360: Remove unused dependency in Kconfig
> leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming
> mode support
> leds: flash: mt6360: Add mt6360 isnk channel hardwre breath mode
> support
>
> drivers/leds/flash/Kconfig | 4 +-
> drivers/leds/flash/leds-mt6360.c | 413 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 410 insertions(+), 7 deletions(-)
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-06-14 7:36 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-28 9:32 [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features cy_huang
2022-04-28 9:32 ` [PATCH 1/4] leds: flash: mt6360: Fix the wrong enable_reg in multicolor brightness set cy_huang
2022-04-28 9:32 ` [PATCH 2/4] leds: flash: mt6360: Remove unused dependency in Kconfig cy_huang
2022-04-28 9:32 ` [PATCH 3/4] leds: flash: mt6360: Add mt6360 isnk channel hardware timer dimming mode support cy_huang
2022-04-28 9:32 ` [PATCH 4/4] leds: flash: mt6360: Add mt6360 isnk channel hardwre breath " cy_huang
2022-04-28 11:50 ` Matti Vaittinen
2022-04-28 14:57 ` ChiYuan Huang
2022-06-14 7:36 ` [PATCH 0/4] leds: flash: mt6360: Apply the fixes and hardware features ChiYuan Huang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).