leds: qpnp-wled: Update AMOLED_VOUT programming
For newer PMICs like pmicobalt, AMOLED_VOUT can be programmed via independent registers. Also the option to configure AVDD voltage through SWIRE and SPMI mode is present. Add support to program the AVDD voltage and mode through these registers. AVDD TRIM adjustment is needed only for pmi8952 and pmi8994. It is not needed for pmicobalt. Support it. CRs-Fixed: 1051250 Change-Id: Ia5cc4a6bbf6b6d0d86e13cec7da167f8a49b859d Signed-off-by: Devesh Jhunjhunwala <deveshj@codeaurora.org> Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
This commit is contained in:
parent
7a1b6d0276
commit
9b32ac8b25
2 changed files with 123 additions and 45 deletions
|
@ -61,10 +61,13 @@ Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
|
|||
- qcom,loop-ea-gm : control the gm for gm stage in control loop. default is 3.
|
||||
- qcom,loop-comp-res-kohm : control to select the compensation resistor in kohm. default is 320.
|
||||
- qcom,vref-psm-mv : reference psm voltage in mv. default for amoled is 450.
|
||||
- qcom,avdd-target-voltage-mv: The target voltage desired for the AVDD module in mV.
|
||||
The supported values are:
|
||||
7900, 7600, 7300, 6400, 6100, 5800.
|
||||
If not specified, default value used is 7600.
|
||||
- qcom,avdd-mode-spmi: Boolean property to enable AMOLED_VOUT programming via SPMI. If not specified,
|
||||
AMOLED_VOUT is programmed via S-wire. This can be specified only for newer
|
||||
PMICs like pmicobalt/pm2falcon.
|
||||
- qcom,avdd-target-voltage-mv: The voltage required for AMOLED_VOUT. Accepted values are in the range
|
||||
of 5650 to 7900 in steps of 150. Default value is 7600. Unit is in mV.
|
||||
For old revisions, accepted values are: 7900, 7600, 7300, 6400, 6100,
|
||||
5800.
|
||||
|
||||
Example:
|
||||
qcom,leds@d800 {
|
||||
|
|
|
@ -45,11 +45,13 @@
|
|||
#define QPNP_WLED_SWITCH_FREQ_REG(b) (b + 0x4C)
|
||||
#define QPNP_WLED_OVP_REG(b) (b + 0x4D)
|
||||
#define QPNP_WLED_ILIM_REG(b) (b + 0x4E)
|
||||
#define QPNP_WLED_AMOLED_VOUT_REG(b) (b + 0x4F)
|
||||
#define QPNP_WLED_SOFTSTART_RAMP_DLY(b) (b + 0x53)
|
||||
#define QPNP_WLED_VLOOP_COMP_RES_REG(b) (b + 0x55)
|
||||
#define QPNP_WLED_VLOOP_COMP_GM_REG(b) (b + 0x56)
|
||||
#define QPNP_WLED_PSM_CTRL_REG(b) (b + 0x5B)
|
||||
#define QPNP_WLED_SC_PRO_REG(b) (b + 0x5E)
|
||||
#define QPNP_WLED_SWIRE_AVDD_REG(b) (b + 0x5F)
|
||||
#define QPNP_WLED_CTRL_SPARE_REG(b) (b + 0xDF)
|
||||
#define QPNP_WLED_TEST1_REG(b) (b + 0xE2)
|
||||
#define QPNP_WLED_TEST4_REG(b) (b + 0xE5)
|
||||
|
@ -196,12 +198,19 @@
|
|||
|
||||
#define NUM_SUPPORTED_AVDD_VOLTAGES 6
|
||||
#define QPNP_WLED_DFLT_AVDD_MV 7600
|
||||
#define QPNP_WLED_AVDD_MIN_MV 5650
|
||||
#define QPNP_WLED_AVDD_MAX_MV 7900
|
||||
#define QPNP_WLED_AVDD_STEP_MV 150
|
||||
#define QPNP_WLED_AVDD_MIN_TRIM_VAL 0x0
|
||||
#define QPNP_WLED_AVDD_MAX_TRIM_VAL 0xF
|
||||
#define QPNP_WLED_AVDD_SEL_SPMI_BIT BIT(7)
|
||||
#define QPNP_WLED_AVDD_SET_BIT BIT(4)
|
||||
|
||||
#define NUM_SUPPORTED_OVP_THRESHOLDS 4
|
||||
|
||||
#define QPNP_WLED_AVDD_MV_TO_REG(val) \
|
||||
((val - QPNP_WLED_AVDD_MIN_MV) / QPNP_WLED_AVDD_STEP_MV)
|
||||
|
||||
/* output feedback mode */
|
||||
enum qpnp_wled_fdbk_op {
|
||||
QPNP_WLED_FDBK_AUTO,
|
||||
|
@ -288,6 +297,7 @@ static int qpnp_wled_ovp_thresholds_pmicobalt[NUM_SUPPORTED_OVP_THRESHOLDS] = {
|
|||
* @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
|
||||
* @ strings - supported list of strings
|
||||
* @ num_strings - number of strings
|
||||
* @ avdd_mode_spmi - enable avdd programming via spmi
|
||||
* @ en_9b_dim_res - enable or disable 9bit dimming
|
||||
* @ en_phase_stag - enable or disable phase staggering
|
||||
* @ en_cabc - enable or disable cabc
|
||||
|
@ -330,6 +340,7 @@ struct qpnp_wled {
|
|||
u16 cons_sync_write_delay_us;
|
||||
u8 strings[QPNP_WLED_MAX_STRINGS];
|
||||
u8 num_strings;
|
||||
bool avdd_mode_spmi;
|
||||
bool en_9b_dim_res;
|
||||
bool en_phase_stag;
|
||||
bool en_cabc;
|
||||
|
@ -1089,6 +1100,102 @@ static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qpnp_wled_avdd_trim_config(struct qpnp_wled *wled)
|
||||
{
|
||||
int rc, i;
|
||||
u8 reg;
|
||||
|
||||
for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
|
||||
if (wled->avdd_target_voltage_mv ==
|
||||
qpnp_wled_avdd_target_voltages[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
|
||||
dev_err(&wled->pdev->dev,
|
||||
"Invalid avdd target voltage specified in device tree\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Update WLED_OVP register based on desired target voltage */
|
||||
reg = qpnp_wled_ovp_reg_settings[i];
|
||||
rc = qpnp_wled_masked_write_reg(wled, QPNP_WLED_OVP_MASK, ®,
|
||||
QPNP_WLED_OVP_REG(wled->ctrl_base));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Update WLED_TRIM register based on desired target voltage */
|
||||
rc = qpnp_wled_read_reg(wled, ®,
|
||||
QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
reg += qpnp_wled_avdd_trim_adjustments[i];
|
||||
if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL ||
|
||||
(s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VAL) {
|
||||
dev_dbg(&wled->pdev->dev,
|
||||
"adjusted trim %d is not within range, capping it\n",
|
||||
(s8)reg);
|
||||
if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
|
||||
reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
|
||||
else
|
||||
reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
|
||||
}
|
||||
|
||||
reg &= QPNP_WLED_7P7_TRIM_MASK;
|
||||
rc = qpnp_wled_sec_write_reg(wled, reg,
|
||||
QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
|
||||
if (rc < 0)
|
||||
dev_err(&wled->pdev->dev, "Write to 7P7_TRIM register failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qpnp_wled_avdd_mode_config(struct qpnp_wled *wled)
|
||||
{
|
||||
int rc;
|
||||
u8 reg = 0;
|
||||
|
||||
/*
|
||||
* At present, configuring the mode to SPMI/SWIRE for controlling
|
||||
* AVDD voltage is available only in pmicobalt/pm2falcon.
|
||||
*/
|
||||
if (wled->pmic_rev_id->pmic_subtype != PMICOBALT_SUBTYPE &&
|
||||
wled->pmic_rev_id->pmic_subtype != PM2FALCON_SUBTYPE)
|
||||
return 0;
|
||||
|
||||
/* AMOLED_VOUT should be configured for AMOLED */
|
||||
if (!wled->disp_type_amoled)
|
||||
return 0;
|
||||
|
||||
/* Configure avdd register */
|
||||
if (wled->avdd_target_voltage_mv > QPNP_WLED_AVDD_MAX_MV) {
|
||||
dev_dbg(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
|
||||
QPNP_WLED_AVDD_MAX_MV);
|
||||
wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MAX_MV;
|
||||
} else if (wled->avdd_target_voltage_mv < QPNP_WLED_AVDD_MIN_MV) {
|
||||
dev_info(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
|
||||
QPNP_WLED_AVDD_MIN_MV);
|
||||
wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MIN_MV;
|
||||
}
|
||||
|
||||
reg = QPNP_WLED_AVDD_MV_TO_REG(wled->avdd_target_voltage_mv);
|
||||
|
||||
if (wled->avdd_mode_spmi) {
|
||||
reg |= QPNP_WLED_AVDD_SEL_SPMI_BIT;
|
||||
rc = qpnp_wled_write_reg(wled, reg,
|
||||
QPNP_WLED_AMOLED_VOUT_REG(wled->ctrl_base));
|
||||
} else {
|
||||
rc = qpnp_wled_write_reg(wled, reg,
|
||||
QPNP_WLED_SWIRE_AVDD_REG(wled->ctrl_base));
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
dev_err(&wled->pdev->dev, "Write to VOUT/AVDD register failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Configure WLED registers */
|
||||
static int qpnp_wled_config(struct qpnp_wled *wled)
|
||||
{
|
||||
|
@ -1199,50 +1306,15 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
|
|||
}
|
||||
|
||||
if (is_avdd_trim_adjustment_required(wled)) {
|
||||
for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
|
||||
if (wled->avdd_target_voltage_mv ==
|
||||
qpnp_wled_avdd_target_voltages[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
|
||||
dev_err(&wled->pdev->dev,
|
||||
"Invalid avdd target voltage specified in device tree\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Update WLED_OVP register based on desired target voltage */
|
||||
reg = qpnp_wled_ovp_reg_settings[i];
|
||||
rc = qpnp_wled_masked_write_reg(wled, QPNP_WLED_OVP_MASK, ®,
|
||||
QPNP_WLED_OVP_REG(wled->ctrl_base));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Update WLED_TRIM register based on desired target voltage */
|
||||
rc = qpnp_wled_read_reg(wled, ®,
|
||||
QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
reg += qpnp_wled_avdd_trim_adjustments[i];
|
||||
if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL ||
|
||||
(s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VAL) {
|
||||
dev_info(&wled->pdev->dev,
|
||||
"adjusted trim %d is not within range, capping it\n",
|
||||
(s8)reg);
|
||||
if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
|
||||
reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
|
||||
else
|
||||
reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
|
||||
}
|
||||
|
||||
reg &= QPNP_WLED_7P7_TRIM_MASK;
|
||||
rc = qpnp_wled_sec_write_reg(wled, reg,
|
||||
QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
|
||||
if (rc)
|
||||
rc = qpnp_wled_avdd_trim_config(wled);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = qpnp_wled_avdd_mode_config(wled);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Configure the MODULATION register */
|
||||
if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_1200_KHZ) {
|
||||
wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_1200_KHZ;
|
||||
|
@ -1561,6 +1633,9 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
|
|||
return rc;
|
||||
}
|
||||
|
||||
wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,avdd-mode-spmi");
|
||||
|
||||
wled->avdd_target_voltage_mv = QPNP_WLED_DFLT_AVDD_MV;
|
||||
rc = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,avdd-target-voltage-mv", &temp_val);
|
||||
|
|
Loading…
Add table
Reference in a new issue