From 40e53d108391d5692a4e57ff4cb41d76dcc78c8f Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Mon, 1 Jul 2019 17:59:06 +0800 Subject: [PATCH] drm/panel: add panel loader protest Change-Id: I4abb3739144b5a3c99fd57d76e0ff87ccb664667 Signed-off-by: Sandy Huang --- drivers/gpu/drm/panel/panel-simple.c | 72 +++++++++++++++++++++++++++- include/drm/drm_panel.h | 10 ++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 29342ed5ea9e..3486431dd935 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -80,6 +80,7 @@ struct panel_simple { struct drm_panel base; bool prepared; bool enabled; + bool power_invert; const struct panel_desc *desc; @@ -160,6 +161,69 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel) return num; } +static int panel_simple_regulator_enable(struct drm_panel *panel) +{ + struct panel_simple *p = to_panel_simple(panel); + int err = 0; + + if (p->power_invert) { + if (regulator_is_enabled(p->supply) > 0) + regulator_disable(p->supply); + } else { + err = regulator_enable(p->supply); + if (err < 0) { + dev_err(panel->dev, "failed to enable supply: %d\n", + err); + return err; + } + } + + return err; +} + +static int panel_simple_regulator_disable(struct drm_panel *panel) +{ + struct panel_simple *p = to_panel_simple(panel); + int err = 0; + + if (p->power_invert) { + if (!regulator_is_enabled(p->supply)) { + err = regulator_enable(p->supply); + if (err < 0) { + dev_err(panel->dev, "failed to enable supply: %d\n", + err); + return err; + } + } + } else { + regulator_disable(p->supply); + } + + return err; +} + +static int panel_simple_loader_protect(struct drm_panel *panel, bool on) +{ + struct panel_simple *p = to_panel_simple(panel); + int err; + + if (on) { + err = panel_simple_regulator_enable(panel); + if (err < 0) { + dev_err(panel->dev, "failed to enable supply: %d\n", + err); + return err; + } + + p->prepared = true; + p->enabled = true; + } else { + /* do nothing */ + } + + return 0; +} + static int panel_simple_disable(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); @@ -190,7 +254,7 @@ static int panel_simple_unprepare(struct drm_panel *panel) gpiod_set_value_cansleep(p->enable_gpio, 0); - regulator_disable(p->supply); + panel_simple_regulator_disable(panel); if (p->desc->delay.unprepare) msleep(p->desc->delay.unprepare); @@ -208,7 +272,7 @@ static int panel_simple_prepare(struct drm_panel *panel) if (p->prepared) return 0; - err = regulator_enable(p->supply); + err = panel_simple_regulator_enable(panel); if (err < 0) { dev_err(panel->dev, "failed to enable supply: %d\n", err); return err; @@ -284,6 +348,7 @@ static int panel_simple_get_timings(struct drm_panel *panel, } static const struct drm_panel_funcs panel_simple_funcs = { + .loader_protect = panel_simple_loader_protect, .disable = panel_simple_disable, .unprepare = panel_simple_unprepare, .prepare = panel_simple_prepare, @@ -319,6 +384,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) return err; } + panel->power_invert = + of_property_read_bool(dev->of_node, "power-invert"); + backlight = of_parse_phandle(dev->of_node, "backlight", 0); if (backlight) { panel->backlight = of_find_backlight_by_node(backlight); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 777814755fa6..233efacc2863 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -34,6 +34,7 @@ struct drm_panel; struct display_timing; /** + * @loader_protect: protect loader logo panel's power * struct drm_panel_funcs - perform operations on a given panel * @disable: disable panel (turn off back light, etc.) * @unprepare: turn off panel @@ -68,6 +69,7 @@ struct display_timing; * the panel. This is the job of the .unprepare() function. */ struct drm_panel_funcs { + int (*loader_protect)(struct drm_panel *panel, bool on); int (*disable)(struct drm_panel *panel); int (*unprepare)(struct drm_panel *panel); int (*prepare)(struct drm_panel *panel); @@ -95,6 +97,14 @@ struct drm_panel { struct list_head list; }; +static inline int drm_panel_loader_protect(struct drm_panel *panel, bool on) +{ + if (panel && panel->funcs && panel->funcs->loader_protect) + return panel->funcs->loader_protect(panel, on); + + return -EINVAL; +} + /** * drm_disable_unprepare - power off a panel * @panel: DRM panel