Merge "backlight: qcom-spmi-wled: Add support to configure slew ramp time"
This commit is contained in:
commit
6d9f7d36ab
1 changed files with 169 additions and 0 deletions
|
|
@ -181,6 +181,22 @@
|
|||
|
||||
#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_SLEW_RAMP_TIME_SEL GENMASK(3, 0)
|
||||
|
||||
#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,
|
||||
|
|
@ -209,9 +225,11 @@ struct wled_config {
|
|||
int string_cfg;
|
||||
int mod_sel;
|
||||
int cabc_sel;
|
||||
int slew_ramp_time;
|
||||
bool en_cabc;
|
||||
bool ext_pfet_sc_pro_en;
|
||||
bool auto_calib_enabled;
|
||||
bool use_exp_dimming;
|
||||
};
|
||||
|
||||
struct wled_flash_config {
|
||||
|
|
@ -259,6 +277,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 {
|
||||
|
|
@ -508,6 +527,16 @@ static int wled_set_brightness(struct wled *wled, u16 brightness)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool wled_exp_dimming_supported(struct wled *wled)
|
||||
{
|
||||
if (*wled->version == WLED_PM7325B)
|
||||
return true;
|
||||
|
||||
dev_dbg(&wled->pdev->dev, "Exponential dimming not supported for WLED version %d\n",
|
||||
*wled->version);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int wled_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct wled *wled = bl_get_data(bl);
|
||||
|
|
@ -542,6 +571,17 @@ static int wled_update_status(struct backlight_device *bl)
|
|||
pr_err("wled enable failed rc:%d\n", rc);
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
if (wled_exp_dimming_supported(wled)) {
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_SLEW_RAMP_TIME_SEL,
|
||||
wled->cfg.slew_ramp_time);
|
||||
if (rc < 0) {
|
||||
pr_err("Failed to write to SLEW_RATE_REGISTER rc:%d\n", rc);
|
||||
goto unlock_mutex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_wled5(wled)) {
|
||||
|
|
@ -553,6 +593,16 @@ static int wled_update_status(struct backlight_device *bl)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (wled_exp_dimming_supported(wled)) {
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_SLEW_RAMP_TIME_SEL, 0);
|
||||
if (rc < 0) {
|
||||
pr_err("Failed to write to SLEW_RATE_REGISTER rc:%d\n", rc);
|
||||
goto unlock_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
rc = wled_module_enable(wled, brightness);
|
||||
if (rc < 0) {
|
||||
pr_err("wled disable failed rc:%d\n", rc);
|
||||
|
|
@ -1117,6 +1167,77 @@ 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, len;
|
||||
|
||||
if (!wled_exp_dimming_supported(wled))
|
||||
return 0;
|
||||
|
||||
len = of_property_count_elems_of_size(node, "qcom,exp-dimming-map", sizeof(u32));
|
||||
if (len != EXP_DIMMING_TABLE_SIZE) {
|
||||
dev_err(&wled->pdev->dev, "Invalid exponential map length: %d, must be %d bytes length\n",
|
||||
len, EXP_DIMMING_TABLE_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32_array(node, "qcom,exp-dimming-map",
|
||||
wled->exp_map, EXP_DIMMING_TABLE_SIZE);
|
||||
if (rc < 0)
|
||||
dev_err(&wled->pdev->dev, "Error in reading qcom,exp-dimming-map, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wled_program_exp_dimming(struct wled *wled)
|
||||
{
|
||||
int rc, i;
|
||||
u8 val[4];
|
||||
|
||||
if (!wled_exp_dimming_supported(wled))
|
||||
return 0;
|
||||
|
||||
rc = wled_module_enable(wled, 0);
|
||||
if (rc < 0) {
|
||||
dev_err(&wled->pdev->dev, "wled disable failed rc:%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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)
|
||||
goto wled_enable;
|
||||
|
||||
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:
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr + WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_EN_EXP_LUT, 0);
|
||||
wled_enable:
|
||||
wled_module_enable(wled, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wled5_setup(struct wled *wled)
|
||||
{
|
||||
int rc, temp, i;
|
||||
|
|
@ -1217,6 +1338,26 @@ static int wled5_setup(struct wled *wled)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (wled_exp_dimming_supported(wled)) {
|
||||
val = WLED5_EN_SLEW_CTL | wled->cfg.slew_ramp_time;
|
||||
rc = regmap_update_bits(wled->regmap,
|
||||
wled->sink_addr +
|
||||
WLED5_SINK_BRIGHTNESS_SLEW_RATE_CTL_REG,
|
||||
WLED5_EN_SLEW_CTL | WLED5_SLEW_RAMP_TIME_SEL,
|
||||
val);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (wled->cfg.use_exp_dimming) {
|
||||
rc = wled_program_exp_dimming(wled);
|
||||
if (rc < 0) {
|
||||
dev_err(&wled->pdev->dev, "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,
|
||||
|
|
@ -1389,6 +1530,7 @@ static const struct wled_config wled4_config_defaults = {
|
|||
.string_cfg = 0xf,
|
||||
.mod_sel = -EINVAL,
|
||||
.cabc_sel = -EINVAL,
|
||||
.slew_ramp_time = -EINVAL,
|
||||
.en_cabc = 0,
|
||||
.ext_pfet_sc_pro_en = 0,
|
||||
.auto_calib_enabled = 0,
|
||||
|
|
@ -1402,6 +1544,7 @@ static const struct wled_config wled5_config_defaults = {
|
|||
.string_cfg = 0xf,
|
||||
.mod_sel = 0,
|
||||
.cabc_sel = 0,
|
||||
.slew_ramp_time = 6, /* 256 ms */
|
||||
.en_cabc = 0,
|
||||
.ext_pfet_sc_pro_en = 0,
|
||||
.auto_calib_enabled = 0,
|
||||
|
|
@ -1488,6 +1631,17 @@ static const struct wled_var_cfg wled5_cabc_sel_cfg = {
|
|||
.size = 4,
|
||||
};
|
||||
|
||||
/* Applicable only for PM7325B */
|
||||
static const u32 wled5_slew_ramp_time_values[] = {
|
||||
2, 4, 8, 64, 128, 192, 256, 320, 384, 448, 512, 704,
|
||||
896, 1024, 2048, 4096,
|
||||
};
|
||||
|
||||
static const struct wled_var_cfg wled5_slew_ramp_time_cfg = {
|
||||
.values = wled5_slew_ramp_time_values,
|
||||
.size = ARRAY_SIZE(wled5_slew_ramp_time_values),
|
||||
};
|
||||
|
||||
static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx)
|
||||
{
|
||||
if (!cfg)
|
||||
|
|
@ -2261,6 +2415,11 @@ static int wled_configure(struct wled *wled, struct device *dev)
|
|||
.val_ptr = &cfg->cabc_sel,
|
||||
.cfg = &wled5_cabc_sel_cfg,
|
||||
},
|
||||
{
|
||||
.name = "qcom,slew-ramp-time",
|
||||
.val_ptr = &cfg->slew_ramp_time,
|
||||
.cfg = &wled5_slew_ramp_time_cfg,
|
||||
},
|
||||
};
|
||||
|
||||
const struct {
|
||||
|
|
@ -2270,6 +2429,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);
|
||||
|
|
@ -2342,6 +2502,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…
Add table
Add a link
Reference in a new issue