leds: qpnp-wled: Add support to configure AUTO_GM settings

WLED in pmicobalt supports AUTO_GM configuration in CTRL_VLOOP_COMP_GM
register. Add two properties to enable auto-gm and set auto-gm threshold.
Meanwhile, move "qcom,loop-ea-gm" property outside of AMOLED constraint
because WLED in LCD mode also support it.

CRs-Fixed: 1081738
Change-Id: Iee99e9d1b999c84ece075d2f17e9cdf6aef9a2ac
Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org>
This commit is contained in:
Fenglin Wu 2016-11-08 16:38:41 +08:00
parent e146a32840
commit c8f85b42fe
2 changed files with 100 additions and 31 deletions

View file

@ -68,9 +68,12 @@ Optional properties for WLED:
- qcom,cons-sync-write-delay-us : Specify in 'us' the duration of delay between two consecutive writes to
SYNC register.
- qcom,sc-deb-cycles : debounce time for short circuit detection
- qcom,loop-ea-gm : control the gm for gm stage in control loop. default is 3.
- qcom,loop-auto-gm-en : A boolean property to specify if auto gm is enabled.
- qcom,loop-auto-gm-thresh : Specify auto gm threshold if "loop-auto-gm-en" is defined.
Supported values are: 0 - 3.
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-mode-spmi: Boolean property to enable AMOLED_VOUT programming via SPMI. If not specified,

View file

@ -69,11 +69,18 @@
#define QPNP_WLED_LOOP_COMP_RES_STEP_KOHM 20
#define QPNP_WLED_LOOP_COMP_RES_MIN_KOHM 20
#define QPNP_WLED_LOOP_COMP_RES_MAX_KOHM 320
#define QPNP_WLED_VLOOP_COMP_GM_MASK 0xF0
#define QPNP_WLED_VLOOP_COMP_GM_MASK GENMASK(3, 0)
#define QPNP_WLED_VLOOP_COMP_GM_OVERWRITE 0x80
#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED 0x03
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_EN BIT(6)
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK GENMASK(5, 4)
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT 4
#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994 0x03
#define QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT 0x09
#define QPNP_WLED_LOOP_GM_DFLT_WLED 0x09
#define QPNP_WLED_LOOP_EA_GM_MIN 0x0
#define QPNP_WLED_LOOP_EA_GM_MAX 0xF
#define QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX 3
#define QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH 1
#define QPNP_WLED_VREF_PSM_MASK 0xF8
#define QPNP_WLED_VREF_PSM_STEP_MV 50
#define QPNP_WLED_VREF_PSM_MIN_MV 400
@ -319,6 +326,8 @@ static struct wled_vref_setting vref_setting_pmicobalt = {
* @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
* @ strings - supported list of strings
* @ num_strings - number of strings
* @ loop_auto_gm_thresh - the clamping level for auto gm
* @ loop_auto_gm_en - select if auto gm is enabled
* @ 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
@ -362,6 +371,8 @@ struct qpnp_wled {
u16 cons_sync_write_delay_us;
u8 strings[QPNP_WLED_MAX_STRINGS];
u8 num_strings;
u8 loop_auto_gm_thresh;
bool loop_auto_gm_en;
bool avdd_mode_spmi;
bool en_9b_dim_res;
bool en_phase_stag;
@ -987,24 +998,6 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
if (rc)
return rc;
/* Configure the LOOP COMP GM register for AMOLED */
if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;
rc = qpnp_wled_read_reg(wled, &reg,
QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
if (rc < 0)
return rc;
reg &= QPNP_WLED_VLOOP_COMP_GM_MASK;
reg |= (wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE);
rc = qpnp_wled_write_reg(wled, reg,
QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
if (rc)
return rc;
/* Configure the CTRL TEST4 register for AMOLED */
rc = qpnp_wled_read_reg(wled, &reg,
QPNP_WLED_TEST4_REG(wled->ctrl_base));
@ -1084,6 +1077,45 @@ static bool is_avdd_trim_adjustment_required(struct qpnp_wled *wled)
return !(reg & QPNP_WLED_AVDD_SET_BIT);
}
static int qpnp_wled_gm_config(struct qpnp_wled *wled)
{
int rc;
u8 mask = 0, reg = 0;
/* Configure the LOOP COMP GM register */
if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
if (wled->loop_auto_gm_en)
reg |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN;
if (wled->loop_auto_gm_thresh >
QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX)
wled->loop_auto_gm_thresh =
QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX;
reg |= wled->loop_auto_gm_thresh <<
QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT;
mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
}
if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;
reg |= wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
mask |= QPNP_WLED_VLOOP_COMP_GM_MASK |
QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
rc = qpnp_wled_masked_write_reg(wled, mask, &reg,
QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
if (rc)
pr_err("write VLOOP_COMP_GM_REG failed, rc=%d]\n", rc);
return rc;
}
static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
{
int rc, i, *ovp_table;
@ -1317,6 +1349,13 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
return rc;
}
/* Configure VLOOP_COMP_GM register */
rc = qpnp_wled_gm_config(wled);
if (rc < 0) {
pr_err("Error in configureing wled gm, rc=%d\n", rc);
return rc;
}
/* Configure the ILIM register */
rc = qpnp_wled_ilim_config(wled);
if (rc < 0) {
@ -1689,16 +1728,6 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
return rc;
}
wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,loop-ea-gm", &temp_val);
if (!rc) {
wled->loop_ea_gm = temp_val;
} else if (rc != -EINVAL) {
dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
return rc;
}
wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
"qcom,avdd-mode-spmi");
@ -1713,6 +1742,43 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
}
}
if (wled->disp_type_amoled) {
if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE)
wled->loop_ea_gm =
QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT;
else
wled->loop_ea_gm =
QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994;
} else {
wled->loop_ea_gm = QPNP_WLED_LOOP_GM_DFLT_WLED;
}
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,loop-ea-gm", &temp_val);
if (!rc) {
wled->loop_ea_gm = temp_val;
} else if (rc != -EINVAL) {
dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
return rc;
}
if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
wled->loop_auto_gm_en =
of_property_read_bool(pdev->dev.of_node,
"qcom,loop-auto-gm-en");
wled->loop_auto_gm_thresh = QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH;
rc = of_property_read_u8(pdev->dev.of_node,
"qcom,loop-auto-gm-thresh",
&wled->loop_auto_gm_thresh);
if (rc && rc != -EINVAL) {
dev_err(&pdev->dev,
"Unable to read loop-auto-gm-thresh\n");
return rc;
}
}
wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_DFLT;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,sc-deb-cycles", &temp_val);