drm/panel: add panel loader protest

Change-Id: I4abb3739144b5a3c99fd57d76e0ff87ccb664667
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2019-07-01 17:59:06 +08:00
parent a966346935
commit 40e53d1083
2 changed files with 80 additions and 2 deletions

View File

@@ -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);

View File

@@ -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