mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
backlight: qcom-spmi-wled: Add support for exponential dimming
Add support to enable writing a lookup table of brightness values into WLED_SINK peripheral to enable more granular control over brightness, to help end user see brightness change smoothly instead of in visible steps. Change-Id: Ifd2dd382bf3e1274a5b994e8d83b87833c975970 Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
This commit is contained in:
parent
ff3868e2a2
commit
d02fbd0d0d
1 changed files with 109 additions and 0 deletions
|
|
@ -180,6 +180,21 @@
|
|||
|
||||
#define WLED5_SINK_FLASH_SHDN_CLR_REG 0xb6
|
||||
|
||||
#define WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG 0xb8
|
||||
#define WLED5_EN_SLEW_CTL BIT(7)
|
||||
#define WLED5_EN_EXP_LUT BIT(6)
|
||||
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT0_LSB_REG 0xc0
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT0_MSB_REG 0xc1
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT1_LSB_REG 0xc2
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT1_MSB_REG 0xc3
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT_LSB_MASK GENMASK(7, 0)
|
||||
#define WLED5_SINK_DIMMING_EXP_LUT_MSB_MASK GENMASK(6, 0)
|
||||
|
||||
#define WLED5_SINK_EXP_LUT_INDEX_REG 0xc9
|
||||
|
||||
#define EXP_DIMMING_TABLE_SIZE 256
|
||||
|
||||
enum wled_version {
|
||||
WLED_PMI8998 = 4,
|
||||
WLED_PM660L,
|
||||
|
|
@ -211,6 +226,7 @@ struct wled_config {
|
|||
bool en_cabc;
|
||||
bool ext_pfet_sc_pro_en;
|
||||
bool auto_calib_enabled;
|
||||
bool use_exp_dimming;
|
||||
};
|
||||
|
||||
struct wled_flash_config {
|
||||
|
|
@ -258,6 +274,7 @@ struct wled {
|
|||
enum wled_flash_mode flash_mode;
|
||||
u8 num_strings;
|
||||
u32 leds_per_string;
|
||||
u32 exp_map[EXP_DIMMING_TABLE_SIZE];
|
||||
};
|
||||
|
||||
enum wled5_mod_sel {
|
||||
|
|
@ -1099,6 +1116,78 @@ static inline u8 get_wled_safety_time(int time_ms)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wled_read_exp_dimming_map(struct device_node *node, struct wled *wled)
|
||||
{
|
||||
int rc = 0, len;
|
||||
|
||||
if (*wled->version != WLED_PM7325B) {
|
||||
pr_err("Exponential dimming not supported for WLED version %d\n", *wled->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = of_property_count_elems_of_size(node, "qcom,exp-dimming-map", sizeof(u32));
|
||||
if (len != EXP_DIMMING_TABLE_SIZE) {
|
||||
pr_err("Invalid exponential map length: %d, must be 256 bytes length\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32_array(node, "qcom,exp-dimming-map",
|
||||
wled->exp_map, EXP_DIMMING_TABLE_SIZE);
|
||||
if (rc < 0)
|
||||
pr_err("Error in reading qcom,exp-dimming-map, rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wled_program_exp_dimming(struct wled *wled)
|
||||
{
|
||||
int rc = 0, i;
|
||||
u8 val[4];
|
||||
|
||||
if (*wled->version != WLED_PM7325B) {
|
||||
pr_err("Exponential dimming not supported for WLED version %d\n", *wled->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wled_module_enable(wled, 0);
|
||||
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_EN_EXP_LUT, WLED5_EN_EXP_LUT);
|
||||
if (rc < 0) {
|
||||
wled_module_enable(wled, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < EXP_DIMMING_TABLE_SIZE / 2; i++) {
|
||||
val[0] = wled->exp_map[2 * i] & WLED5_SINK_DIMMING_EXP_LUT_LSB_MASK;
|
||||
val[1] = (wled->exp_map[2 * i] >> 8) & WLED5_SINK_DIMMING_EXP_LUT_MSB_MASK;
|
||||
val[2] = wled->exp_map[2 * i + 1] & WLED5_SINK_DIMMING_EXP_LUT_LSB_MASK;
|
||||
val[3] = (wled->exp_map[2 * i + 1] >> 8) & WLED5_SINK_DIMMING_EXP_LUT_MSB_MASK;
|
||||
|
||||
rc = regmap_write(wled->regmap, wled->sink_addr + WLED5_SINK_EXP_LUT_INDEX_REG, i);
|
||||
if (rc < 0)
|
||||
goto exp_dimm_fail;
|
||||
|
||||
rc = regmap_bulk_write(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_DIMMING_EXP_LUT0_LSB_REG,
|
||||
val, sizeof(val));
|
||||
if (rc < 0)
|
||||
goto exp_dimm_fail;
|
||||
}
|
||||
|
||||
wled_module_enable(wled, 1);
|
||||
return rc;
|
||||
|
||||
exp_dimm_fail:
|
||||
regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_EN_EXP_LUT, 0);
|
||||
|
||||
wled_module_enable(wled, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wled5_setup(struct wled *wled)
|
||||
{
|
||||
int rc, temp, i;
|
||||
|
|
@ -1199,6 +1288,14 @@ static int wled5_setup(struct wled *wled)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (wled->cfg.use_exp_dimming) {
|
||||
rc = wled_program_exp_dimming(wled);
|
||||
if (rc < 0) {
|
||||
pr_err("Programming exponential dimming map failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (wled->ovp_irq >= 0) {
|
||||
rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq,
|
||||
NULL, wled_ovp_irq_handler, IRQF_ONESHOT,
|
||||
|
|
@ -1374,6 +1471,7 @@ static const struct wled_config wled4_config_defaults = {
|
|||
.en_cabc = 0,
|
||||
.ext_pfet_sc_pro_en = 0,
|
||||
.auto_calib_enabled = 0,
|
||||
.use_exp_dimming = 0,
|
||||
};
|
||||
|
||||
static const struct wled_config wled5_config_defaults = {
|
||||
|
|
@ -1387,6 +1485,7 @@ static const struct wled_config wled5_config_defaults = {
|
|||
.en_cabc = 0,
|
||||
.ext_pfet_sc_pro_en = 0,
|
||||
.auto_calib_enabled = 0,
|
||||
.use_exp_dimming = 0,
|
||||
};
|
||||
|
||||
struct wled_var_cfg {
|
||||
|
|
@ -2252,6 +2351,7 @@ static int wled_configure(struct wled *wled, struct device *dev)
|
|||
{ "qcom,en-cabc", &cfg->en_cabc, },
|
||||
{ "qcom,ext-pfet-sc-pro", &cfg->ext_pfet_sc_pro_en, },
|
||||
{ "qcom,auto-calibration", &cfg->auto_calib_enabled, },
|
||||
{ "qcom,use-exp-dimming", &cfg->use_exp_dimming, },
|
||||
};
|
||||
|
||||
prop_addr = of_get_address(dev->of_node, 0, NULL, NULL);
|
||||
|
|
@ -2324,6 +2424,15 @@ static int wled_configure(struct wled *wled, struct device *dev)
|
|||
*bool_opts[i].val_ptr = true;
|
||||
}
|
||||
|
||||
if (wled->cfg.use_exp_dimming) {
|
||||
rc = wled_read_exp_dimming_map(dev->of_node, wled);
|
||||
if (rc < 0) {
|
||||
dev_err(&wled->pdev->dev,
|
||||
"Reading exponential dimming map failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
wled->sc_irq = platform_get_irq_byname(wled->pdev, "sc-irq");
|
||||
if (wled->sc_irq < 0)
|
||||
dev_dbg(&wled->pdev->dev, "sc irq is not used\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue