summaryrefslogtreecommitdiff
path: root/drivers/leds
diff options
context:
space:
mode:
authorAnirudh Ghayal <aghayal@codeaurora.org>2017-08-31 12:11:06 +0530
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>2017-10-24 16:34:20 -0700
commit11e17644b79b45ee175e2de757b11cb8880924f7 (patch)
tree9234542f6f640d46e489d772fef6c9142ac1d725 /drivers/leds
parent9551e129dd2625ea2ab4fa5620820849b069ce2f (diff)
leds: qpnp-wled: Run auto-calibration during init
If the OVP fault is present during boot-up run a WLED string auto-calibration. Change-Id: I4b0e85cd64a1e8bca9bc7de17521d1f83798ed12 Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/leds-qpnp-wled.c74
1 files changed, 56 insertions, 18 deletions
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index c85b3e42c8c8..27f4a3bebc93 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -123,6 +123,7 @@
#define QPNP_WLED_ILIM_FAULT_BIT BIT(0)
#define QPNP_WLED_OVP_FAULT_BIT BIT(1)
#define QPNP_WLED_SC_FAULT_BIT BIT(2)
+#define QPNP_WLED_OVP_FLT_RT_STS_BIT BIT(1)
/* sink registers */
#define QPNP_WLED_CURR_SINK_REG(b) (b + 0x46)
@@ -1103,14 +1104,6 @@ static int wled_auto_calibrate(struct qpnp_wled *wled)
int rc = 0, i;
u8 reg = 0, sink_config = 0, sink_test = 0, sink_valid = 0, int_sts;
- mutex_lock(&wled->lock);
-
- /* disable OVP IRQ */
- if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
- disable_irq_nosync(wled->ovp_irq);
- wled->ovp_irq_disabled = true;
- }
-
/* read configured sink configuration */
rc = qpnp_wled_read_reg(wled,
QPNP_WLED_CURR_SINK_REG(wled->sink_base), &sink_config);
@@ -1259,7 +1252,8 @@ static int wled_auto_calibrate(struct qpnp_wled *wled)
}
/* restore brightness */
- rc = qpnp_wled_set_level(wled, wled->cdev.brightness);
+ rc = qpnp_wled_set_level(wled, !wled->cdev.brightness ?
+ AUTO_CALIB_BRIGHTNESS : wled->cdev.brightness);
if (rc < 0) {
pr_err("Failed to set brightness after calibration rc=%d\n",
rc);
@@ -1280,11 +1274,6 @@ static int wled_auto_calibrate(struct qpnp_wled *wled)
QPNP_WLED_SOFT_START_DLY_US + 1000);
failed_calib:
- if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
- enable_irq(wled->ovp_irq);
- wled->ovp_irq_disabled = false;
- }
- mutex_unlock(&wled->lock);
return rc;
}
@@ -1320,6 +1309,38 @@ static bool qpnp_wled_auto_cal_required(struct qpnp_wled *wled)
return false;
}
+static int qpnp_wled_auto_calibrate_at_init(struct qpnp_wled *wled)
+{
+ int rc;
+ u8 fault_status = 0, rt_status = 0;
+
+ if (!wled->auto_calib_enabled)
+ return 0;
+
+ rc = qpnp_wled_read_reg(wled,
+ QPNP_WLED_INT_RT_STS(wled->ctrl_base), &rt_status);
+ if (rc < 0)
+ pr_err("Failed to read RT status rc=%d\n", rc);
+
+ rc = qpnp_wled_read_reg(wled,
+ QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_status);
+ if (rc < 0)
+ pr_err("Failed to read fault status rc=%d\n", rc);
+
+ if ((rt_status & QPNP_WLED_OVP_FLT_RT_STS_BIT) ||
+ (fault_status & QPNP_WLED_OVP_FAULT_BIT)) {
+ mutex_lock(&wled->lock);
+ rc = wled_auto_calibrate(wled);
+ if (rc < 0)
+ pr_err("Failed auto-calibration rc=%d\n", rc);
+ else
+ wled->auto_calib_done = true;
+ mutex_unlock(&wled->lock);
+ }
+
+ return rc;
+}
+
/* ovp irq handler */
static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
{
@@ -1348,13 +1369,26 @@ static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
if (fault_sts & QPNP_WLED_OVP_FAULT_BIT) {
if (wled->auto_calib_enabled && !wled->auto_calib_done) {
if (qpnp_wled_auto_cal_required(wled)) {
+ mutex_lock(&wled->lock);
+ if (wled->ovp_irq > 0 &&
+ !wled->ovp_irq_disabled) {
+ disable_irq_nosync(wled->ovp_irq);
+ wled->ovp_irq_disabled = true;
+ }
+
rc = wled_auto_calibrate(wled);
- if (rc < 0) {
+ if (rc < 0)
pr_err("Failed auto-calibration rc=%d\n",
- rc);
- return IRQ_HANDLED;
+ rc);
+ else
+ wled->auto_calib_done = true;
+
+ if (wled->ovp_irq > 0 &&
+ wled->ovp_irq_disabled) {
+ enable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = false;
}
- wled->auto_calib_done = true;
+ mutex_unlock(&wled->lock);
}
}
}
@@ -1946,6 +1980,10 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
return rc;
}
+ rc = qpnp_wled_auto_calibrate_at_init(wled);
+ if (rc < 0)
+ pr_err("Failed to auto-calibrate at init rc=%d\n", rc);
+
/* setup ovp and sc irqs */
if (wled->ovp_irq >= 0) {
rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq,