summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Semwal <sumit.semwal@linaro.org>2020-05-07 18:02:24 +0530
committerSumit Semwal <sumit.semwal@linaro.org>2020-05-07 20:14:02 +0530
commit8967ba9d7727005e665a74da020acc53e0313a97 (patch)
tree6d9da44c3cd29c5bbb4e371f5fa1d8b4416ae792
parentb81c64fa251983e628b397a84eb3388e5c9b5889 (diff)
drm: panel: lg-sw43408: Add lab regulator SC notify supportdev/p3_labibb_upstreaming
Lab regulator requires the clients to register for the short circuit notification sent via REGULATOR_EVENT_OVER_CURRENT. They should try to enable the regulator on getting this event. If it doesn't get enabled, they need to assume that short circuit is permanent and disable themselves. Add this support to the panel driver, who is a client. Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
-rw-r--r--drivers/gpu/drm/panel/panel-lg-sw43408.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
index d9befd42b995..02495f6548fb 100644
--- a/drivers/gpu/drm/panel/panel-lg-sw43408.c
+++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
@@ -84,6 +84,8 @@ struct panel_info {
struct pinctrl_state *active;
struct pinctrl_state *suspend;
+ struct notifier_block nb;
+
bool prepared;
bool enabled;
bool first_enable;
@@ -94,7 +96,6 @@ static inline struct panel_info *to_panel_info(struct drm_panel *panel)
return container_of(panel, struct panel_info, base);
}
-
/*
* Need to reset gpios and regulators once in the beginning,
*/
@@ -416,6 +417,65 @@ pr_err("In sw43408 panel_enable\n");
return 0;
}
+static int panel_lab_regulator_event(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct panel_info *pinfo =
+ container_of(nb, struct panel_info, nb);
+ int ret;
+pr_err("In sw43408 panel_lab_regulator_event\n");
+
+ if (event & REGULATOR_EVENT_OVER_CURRENT) {
+ /* Try to reinitialise the panel, since lab regulator would
+ * have been disabled by the short circuit.
+ * if it throws an error, then the panel won't recover;
+ * shutdown the panel.
+ */
+ ret = lg_panel_prepare(&pinfo->base);
+
+ if (ret) {
+ dev_err(pinfo->base.dev,
+ "Failed to re-enable lab regulator: %d\n",
+ ret);
+ lg_panel_unprepare(&pinfo->base);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int panel_register_lab_notify(struct panel_info *pinfo)
+{
+ int i, ret = 0;
+ struct regulator *lab_reg = NULL;
+pr_err("In sw43408 panel_register_lab_notify\n");
+
+ pinfo->nb.notifier_call = panel_lab_regulator_event;
+
+ for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) {
+ if (strcmp(pinfo->supplies[i].supply, "lab") == 0) {
+ lab_reg = pinfo->supplies[i].consumer;
+ break;
+ }
+ }
+
+ if (lab_reg != NULL) {
+ ret = devm_regulator_register_notifier(lab_reg, &pinfo->nb);
+
+ if (ret)
+ dev_err(pinfo->base.dev,
+ "Failed to register lab notifier: %d\n", ret);
+ } else {
+ dev_err(pinfo->base.dev,
+ "Invalid name while trying to register lab notifier: %d\n", ret);
+
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int lg_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
@@ -635,6 +695,10 @@ pr_err("In sw43408 panel add\n");
if (ret < 0)
return ret;
+ ret = panel_register_lab_notify(pinfo);
+ if (ret < 0)
+ return ret;
+
pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->reset_gpio)) {
DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n",