Loading drivers/leds/leds-qpnp-wled.c +58 −20 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; } 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; } mutex_unlock(&wled->lock); } } } Loading Loading @@ -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, Loading Loading @@ -2403,7 +2441,7 @@ static int qpnp_wled_probe(struct platform_device *pdev) wled->pmic_rev_id->pmic_subtype, wled->pmic_rev_id->rev4); prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_SINK_BASE, 0, 0); NULL, NULL); if (!prop) { dev_err(&pdev->dev, "Couldnt find sink's addr rc %d\n", rc); return rc; Loading @@ -2411,7 +2449,7 @@ static int qpnp_wled_probe(struct platform_device *pdev) wled->sink_base = be32_to_cpu(*prop); prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_CTRL_BASE, 0, 0); NULL, NULL); if (!prop) { dev_err(&pdev->dev, "Couldnt find ctrl's addr rc = %d\n", rc); return rc; Loading Loading
drivers/leds/leds-qpnp-wled.c +58 −20 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; } 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; } mutex_unlock(&wled->lock); } } } Loading Loading @@ -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, Loading Loading @@ -2403,7 +2441,7 @@ static int qpnp_wled_probe(struct platform_device *pdev) wled->pmic_rev_id->pmic_subtype, wled->pmic_rev_id->rev4); prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_SINK_BASE, 0, 0); NULL, NULL); if (!prop) { dev_err(&pdev->dev, "Couldnt find sink's addr rc %d\n", rc); return rc; Loading @@ -2411,7 +2449,7 @@ static int qpnp_wled_probe(struct platform_device *pdev) wled->sink_base = be32_to_cpu(*prop); prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_CTRL_BASE, 0, 0); NULL, NULL); if (!prop) { dev_err(&pdev->dev, "Couldnt find ctrl's addr rc = %d\n", rc); return rc; Loading