From: Sean Paul <seanpaul@chromium.org>
To: dri-devel@lists.freedesktop.org,
linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org
Cc: "Thierry Reding" <thierry.reding@gmail.com>,
"Mark Rutland" <mark.rutland@arm.com>,
"Jeffy Chen" <jeffy.chen@rock-chips.com>,
"Doug Anderson" <dianders@chromium.org>,
"Rob Herring" <robh+dt@kernel.org>,
"Stéphane Marchesin" <marcheu@chromium.org>
Subject: [PATCH 1/3] drm/panel: simple: Add ability to override typical timing
Date: Tue, 6 Feb 2018 11:56:20 -0500 [thread overview]
Message-ID: <20180206165626.37692-2-seanpaul@chromium.org> (raw)
In-Reply-To: <20180206165626.37692-1-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
Cc: Doug Anderson <dianders@chromium.org>
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
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
.../bindings/display/panel/simple-panel.txt | 20 +++++++
drivers/gpu/drm/panel/panel-simple.c | 69 +++++++++++++++++++++-
2 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/panel/simple-panel.txt b/Documentation/devicetree/bindings/display/panel/simple-panel.txt
index 16d8ff088b7d..590bbff6fc90 100644
--- a/Documentation/devicetree/bindings/display/panel/simple-panel.txt
+++ b/Documentation/devicetree/bindings/display/panel/simple-panel.txt
@@ -7,6 +7,14 @@ Optional properties:
- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
- enable-gpios: GPIO pin to enable or disable the panel
- backlight: phandle of the backlight device attached to the panel
+- override-mode: For devices which require a mode which differs from the
+ display_timing's "typical" mode, and whose restrictions cannot
+ be applied across the entire platform. The mode must fall
+ within the bounds of the panel's specified display_timing, and
+ cannot be used if the panel already specifies a single fixed
+ mode. The format is specified under "timing subnode" in
+ display-timing.txt
+
Example:
@@ -18,4 +26,16 @@ Example:
enable-gpios = <&gpio 90 0>;
backlight = <&backlight>;
+
+ override-mode {
+ clock-frequency = <266604720>;
+ hactive = <2400>;
+ hfront-porch = <48>;
+ hback-porch = <84>;
+ hsync-len = <32>;
+ vactive = <1600>;
+ vfront-porch = <3>;
+ vback-porch = <120>;
+ vsync-len = <10>;
+ }
};
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 5591984a392b..b774365f3635 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 {
@@ -87,6 +88,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)
@@ -99,11 +102,22 @@ static 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;
+ bool has_override = panel->override_mode.type;
unsigned int i, 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++;
+ } else {
+ dev_err(drm->dev, "failed to add override mode\n");
+ }
+ }
+
for (i = 0; i < panel->desc->num_timings; i++) {
const struct display_timing *dt = &panel->desc->timings[i];
struct videomode vm;
@@ -120,7 +134,7 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
mode->type |= DRM_MODE_TYPE_DRIVER;
- if (panel->desc->num_timings == 1)
+ if (panel->desc->num_timings == 1 && !has_override)
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
@@ -291,10 +305,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_add_override_mode(struct device *dev,
+ struct panel_simple *panel,
+ const struct display_timing *ot)
+{
+ const struct panel_desc *desc = panel->desc;
+ struct videomode vm;
+ int i;
+
+ if (desc->num_modes) {
+ dev_err(dev, "Reject override mode: panel has a fixed mode\n");
+ return;
+ }
+ if (!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;
+ return;
+ }
+
+ dev_err(dev, "Reject override mode: No display_timing found\n");
+ return;
+}
+
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 override_timing;
int err;
panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
@@ -338,6 +400,11 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
}
}
+ err = of_get_display_timing(dev->of_node, "override-mode",
+ &override_timing);
+ if (!err)
+ panel_simple_add_override_mode(dev, panel, &override_timing);
+
drm_panel_init(&panel->base);
panel->base.dev = dev;
panel->base.funcs = &panel_simple_funcs;
--
2.16.0.rc1.238.g530d649a79-goog
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2018-02-06 16:56 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-06 16:56 [PATCH 0/3] drm/panel: simple: Add mode support to devicetree Sean Paul
2018-02-06 16:56 ` Sean Paul [this message]
[not found] ` <20180206165626.37692-2-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-02-06 20:19 ` [PATCH 1/3] drm/panel: simple: Add ability to override typical timing Rob Herring
2018-02-06 21:48 ` Sean Paul
2018-02-07 17:41 ` Rob Herring
[not found] ` <CAL_JsqJDvPN3CtKtj980egDRuC-ZjiKOAWe5ECYVBSv4hVOnYw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-02-07 19:27 ` Sean Paul
2018-02-07 9:51 ` Thierry Reding
2018-02-06 16:56 ` [PATCH 2/3] drm/panel: simple: Use display_timing for lq123p1jx31 Sean Paul
2018-02-06 16:56 ` [PATCH 3/3] arm64: dts: rockchip: Specify override mode for kevin panel Sean Paul
[not found] ` <20180206165626.37692-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-02-07 9:16 ` [PATCH 0/3] drm/panel: simple: Add mode support to devicetree Eric Anholt
2018-02-07 15:27 ` Sean Paul
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=20180206165626.37692-2-seanpaul@chromium.org \
--to=seanpaul@chromium.org \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jeffy.chen@rock-chips.com \
--cc=linux-rockchip@lists.infradead.org \
--cc=marcheu@chromium.org \
--cc=mark.rutland@arm.com \
--cc=robh+dt@kernel.org \
--cc=thierry.reding@gmail.com \
/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).