From: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
To: Thierry Reding
<thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>,
Sean Paul <seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
"Rob Herring" <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
"Eric Anholt" <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>,
"David Airlie" <airlied-cv59FeDIM0c@public.gmane.org>,
"Jeffy Chen" <jeffy.chen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>,
"Doug Anderson"
<dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
"Boris Brezillon"
<boris.brezillon-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>,
"Laurent Pinchart"
<laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>,
"Daniel Vetter" <daniel-/w4YWyX8dFk@public.gmane.org>,
"Enric Balletbò"
<enric.balletbo-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>,
"Stéphane Marchesin"
<marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
"Ezequiel Garcia"
<ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>,
mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org
Subject: [PATCH v5 2/7] drm/panel: simple: Add ability to override typical timing
Date: Mon, 1 Apr 2019 10:17:19 -0700 [thread overview]
Message-ID: <20190401171724.215780-3-dianders@chromium.org> (raw)
In-Reply-To: <20190401171724.215780-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
From: Sean Paul <seanpaul@chromium.org>
This patch adds the ability to override the typical display timing for a
given panel. This is useful for devices which have timing constraints
that do not apply across the entire display driver (eg: to avoid
crosstalk between panel and digitizer on certain laptops). The rules are
as follows:
- panel must not specify fixed mode (since the override mode will
either be the same as the fixed mode, or we'll be unable to
check the bounds of the overried)
- panel must specify at least one display_timing range which will be
used to ensure the override mode fits within its bounds
Changes in v2:
- Parse the full display-timings node (using the native-mode) (Rob)
Changes in v3:
- No longer parse display-timings subnode, use panel-timing (Rob)
Changes in v4:
- Don't add mode from timing if override was specified (Thierry)
- Add warning if timing and fixed mode was specified (Thierry)
- Don't add fixed mode if timing was specified (Thierry)
- Refactor/rename a bit to avoid extra indentation from "if" tests
- i should be unsigned (Thierry)
- Add annoying WARN_ONs for some cases (Thierry)
- Simplify 'No display_timing found' handling (Thierry)
- Rename to panel_simple_parse_override_mode() (Thierry)
Changes in v5:
- Added Heiko's Tested-by
Cc: Doug Anderson <dianders@chromium.org>
Cc: Eric Anholt <eric@anholt.net>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Jeffy Chen <jeffy.chen@rock-chips.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stéphane Marchesin <marcheu@chromium.org>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: devicetree@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Tested-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/gpu/drm/panel/panel-simple.c | 109 +++++++++++++++++++++++++--
1 file changed, 104 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 9e8218f6a3f2..ad4f4aac2d44 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -34,6 +34,7 @@
#include <drm/drm_panel.h>
#include <video/display_timing.h>
+#include <video/of_display_timing.h>
#include <video/videomode.h>
struct panel_desc {
@@ -91,6 +92,8 @@ struct panel_simple {
struct i2c_adapter *ddc;
struct gpio_desc *enable_gpio;
+
+ struct drm_display_mode override_mode;
};
static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
@@ -98,16 +101,13 @@ static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
return container_of(panel, struct panel_simple, base);
}
-static int panel_simple_get_fixed_modes(struct panel_simple *panel)
+static unsigned int panel_simple_get_timings_modes(struct panel_simple *panel)
{
struct drm_connector *connector = panel->base.connector;
struct drm_device *drm = panel->base.drm;
struct drm_display_mode *mode;
unsigned int i, num = 0;
- if (!panel->desc)
- return 0;
-
for (i = 0; i < panel->desc->num_timings; i++) {
const struct display_timing *dt = &panel->desc->timings[i];
struct videomode vm;
@@ -131,6 +131,16 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
num++;
}
+ return num;
+}
+
+static unsigned int panel_simple_get_fixed_modes(struct panel_simple *panel)
+{
+ struct drm_connector *connector = panel->base.connector;
+ struct drm_device *drm = panel->base.drm;
+ struct drm_display_mode *mode;
+ unsigned int i, num = 0;
+
for (i = 0; i < panel->desc->num_modes; i++) {
const struct drm_display_mode *m = &panel->desc->modes[i];
@@ -152,6 +162,44 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
num++;
}
+ return num;
+}
+
+static int panel_simple_get_non_edid_modes(struct panel_simple *panel)
+{
+ struct drm_connector *connector = panel->base.connector;
+ struct drm_device *drm = panel->base.drm;
+ struct drm_display_mode *mode;
+ bool has_override = panel->override_mode.type;
+ unsigned int num = 0;
+
+ if (!panel->desc)
+ return 0;
+
+ if (has_override) {
+ mode = drm_mode_duplicate(drm, &panel->override_mode);
+ if (mode) {
+ drm_mode_probed_add(connector, mode);
+ num = 1;
+ } else {
+ dev_err(drm->dev, "failed to add override mode\n");
+ }
+ }
+
+ /* Only add timings if override was not there or failed to validate */
+ if (num == 0 && panel->desc->num_timings)
+ num = panel_simple_get_timings_modes(panel);
+
+ /*
+ * Only add fixed modes if timings/override added no mode.
+ *
+ * We should only ever have either the display timings specified
+ * or a fixed mode. Anything else is rather bogus.
+ */
+ WARN_ON(panel->desc->num_timings && panel->desc->num_modes);
+ if (num == 0)
+ num = panel_simple_get_fixed_modes(panel);
+
connector->display_info.bpc = panel->desc->bpc;
connector->display_info.width_mm = panel->desc->size.width;
connector->display_info.height_mm = panel->desc->size.height;
@@ -268,7 +316,7 @@ static int panel_simple_get_modes(struct drm_panel *panel)
}
/* add hard-coded panel modes */
- num += panel_simple_get_fixed_modes(p);
+ num += panel_simple_get_non_edid_modes(p);
return num;
}
@@ -299,10 +347,58 @@ static const struct drm_panel_funcs panel_simple_funcs = {
.get_timings = panel_simple_get_timings,
};
+#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \
+ (to_check->field.typ >= bounds->field.min && \
+ to_check->field.typ <= bounds->field.max)
+static void panel_simple_parse_override_mode(struct device *dev,
+ struct panel_simple *panel,
+ const struct display_timing *ot)
+{
+ const struct panel_desc *desc = panel->desc;
+ struct videomode vm;
+ unsigned int i;
+
+ if (WARN_ON(desc->num_modes)) {
+ dev_err(dev, "Reject override mode: panel has a fixed mode\n");
+ return;
+ }
+ if (WARN_ON(!desc->num_timings)) {
+ dev_err(dev, "Reject override mode: no timings specified\n");
+ return;
+ }
+
+ for (i = 0; i < panel->desc->num_timings; i++) {
+ const struct display_timing *dt = &panel->desc->timings[i];
+
+ if (!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hactive) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hfront_porch) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hback_porch) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hsync_len) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vactive) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vfront_porch) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vback_porch) ||
+ !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vsync_len))
+ continue;
+
+ if (ot->flags != dt->flags)
+ continue;
+
+ videomode_from_timing(ot, &vm);
+ drm_display_mode_from_videomode(&vm, &panel->override_mode);
+ panel->override_mode.type |= DRM_MODE_TYPE_DRIVER |
+ DRM_MODE_TYPE_PREFERRED;
+ break;
+ }
+
+ if (WARN_ON(!panel->override_mode.type))
+ dev_err(dev, "Reject override mode: No display_timing found\n");
+}
+
static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
{
struct device_node *backlight, *ddc;
struct panel_simple *panel;
+ struct display_timing dt;
int err;
panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
@@ -348,6 +444,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
}
}
+ if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
+ panel_simple_parse_override_mode(dev, panel, &dt);
+
drm_panel_init(&panel->base);
panel->base.dev = dev;
panel->base.funcs = &panel_simple_funcs;
--
2.21.0.392.gf8f6787159e-goog
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
next prev parent reply other threads:[~2019-04-01 17:17 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-01 17:17 [PATCH v5 0/7] drm/panel: simple: Add mode support to devicetree Douglas Anderson
2019-04-01 17:17 ` [PATCH v5 1/7] dt-bindings: Add panel-timing subnode to simple-panel Douglas Anderson
2019-04-06 6:06 ` Rob Herring
2019-04-08 9:10 ` Boris Brezillon
2019-04-08 10:32 ` Thierry Reding
2019-04-08 14:39 ` Doug Anderson
2019-05-20 18:35 ` Doug Anderson
2019-06-28 23:47 ` Thierry Reding
2019-06-30 20:02 ` Sam Ravnborg
2019-07-01 16:59 ` Doug Anderson
[not found] ` <20190401171724.215780-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2019-04-01 17:17 ` Douglas Anderson [this message]
2019-04-08 9:10 ` [PATCH v5 2/7] drm/panel: simple: Add ability to override typical timing Boris Brezillon
2019-06-28 23:49 ` Thierry Reding
2019-06-30 20:22 ` Sam Ravnborg
2019-06-30 20:55 ` Sam Ravnborg
2019-07-01 16:39 ` Doug Anderson
2019-07-08 17:56 ` Sam Ravnborg
2019-07-10 22:56 ` Doug Anderson
2019-07-11 19:16 ` Sean Paul
2019-07-01 16:39 ` Doug Anderson
2019-07-08 17:50 ` Sam Ravnborg
2019-07-10 22:39 ` Doug Anderson
2019-07-11 19:38 ` Sam Ravnborg
2019-04-01 17:17 ` [PATCH v5 3/7] arm64: dts: rockchip: Specify override mode for kevin panel Douglas Anderson
2019-07-11 21:30 ` Heiko Stübner
2019-04-01 17:17 ` [PATCH v5 6/7] ARM: dts: rockchip: Specify rk3288-veyron-chromebook's display timings Douglas Anderson
2019-04-07 1:15 ` Urja Rannikko
2019-04-08 15:21 ` Doug Anderson
2019-04-08 16:26 ` Urja Rannikko
2019-04-13 0:07 ` Doug Anderson
2019-07-11 21:27 ` Heiko Stübner
2019-07-11 21:52 ` Heiko Stübner
2019-04-01 17:17 ` [PATCH v5 7/7] ARM: dts: rockchip: Specify rk3288-veyron-minnie's " Douglas Anderson
2019-07-11 21:28 ` Heiko Stübner
2019-06-14 10:39 ` [PATCH v5 0/7] drm/panel: simple: Add mode support to devicetree Heiko Stuebner
2019-06-26 13:00 ` Sam Ravnborg
2019-06-26 14:41 ` Doug Anderson
2019-06-28 15:55 ` Doug Anderson
2019-06-28 16:10 ` Rob Herring
2019-06-28 17:13 ` Sam Ravnborg
2019-06-29 14:09 ` Heiko Stübner
2019-07-08 15:58 ` Doug Anderson
2019-07-11 19:35 ` Sam Ravnborg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190401171724.215780-3-dianders@chromium.org \
--to=dianders-f7+t8e8rja9g9huczpvpmw@public.gmane.org \
--cc=airlied-cv59FeDIM0c@public.gmane.org \
--cc=boris.brezillon-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=daniel-/w4YWyX8dFk@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=enric.balletbo-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org \
--cc=ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org \
--cc=jeffy.chen-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
--cc=mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
--cc=thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).