From 03e255b993ff96bf194c91c28af9dc03f322af51 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 Apr 2014 08:59:18 +0200 Subject: [PATCH 1/8] MAINTAINERS: Add entry for DRM panel drivers Add myself as the maintainer for DRM panel drivers. The plan is to collect panel-related patches in one place to reduce conflicts and unburden Dave. Signed-off-by: Thierry Reding --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cfb4d29..1a43a9409f40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2851,6 +2851,16 @@ F: drivers/gpu/drm/ F: include/drm/ F: include/uapi/drm/ +DRM PANEL DRIVERS +M: Thierry Reding +L: dri-devel@lists.freedesktop.org +T: git git://anongit.freedesktop.org/tegra/linux.git +S: Maintained +F: drivers/gpu/drm/drm_panel.c +F: drivers/gpu/drm/panel/ +F: include/drm/drm_panel.h +F: Documentation/devicetree/bindings/panel/ + INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets) M: Daniel Vetter M: Jani Nikula From ec7c565383ee7fd4847705b8aafefb8e589aea93 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 15 Nov 2013 15:59:32 +0100 Subject: [PATCH 2/8] drm/panel: Add LG 12.9" LCD panel The LP129QE LCD has an LED backlight and a display resolution of 2560x1700 pixels. Signed-off-by: Thierry Reding --- .../devicetree/bindings/panel/lg,lp129qe.txt | 7 ++++++ drivers/gpu/drm/panel/panel-simple.c | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/lg,lp129qe.txt diff --git a/Documentation/devicetree/bindings/panel/lg,lp129qe.txt b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt new file mode 100644 index 000000000000..9f262e0c5a2e --- /dev/null +++ b/Documentation/devicetree/bindings/panel/lg,lp129qe.txt @@ -0,0 +1,7 @@ +LG 12.9" (2560x1700 pixels) TFT LCD panel + +Required properties: +- compatible: should be "lg,lp129qe" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 59d52ca2c67f..0231945c2934 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -361,6 +361,28 @@ static const struct panel_desc chunghwa_claa101wb01 = { }, }; +static const struct drm_display_mode lg_lp129qe_mode = { + .clock = 285250, + .hdisplay = 2560, + .hsync_start = 2560 + 48, + .hsync_end = 2560 + 48 + 32, + .htotal = 2560 + 48 + 32 + 80, + .vdisplay = 1700, + .vsync_start = 1700 + 3, + .vsync_end = 1700 + 3 + 10, + .vtotal = 1700 + 3 + 10 + 36, + .vrefresh = 60, +}; + +static const struct panel_desc lg_lp129qe = { + .modes = &lg_lp129qe_mode, + .num_modes = 1, + .size = { + .width = 272, + .height = 181, + }, +}; + static const struct drm_display_mode samsung_ltn101nt05_mode = { .clock = 54030, .hdisplay = 1024, @@ -393,6 +415,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "chunghwa,claa101wb01", .data = &chunghwa_claa101wb01 + }, { + .compatible = "lg,lp129qe", + .data = &lg_lp129qe, }, { .compatible = "samsung,ltn101nt05", .data = &samsung_ltn101nt05, From cfdf0549f85f9a48e74bf8f6e36572ccdb75d274 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sat, 1 Mar 2014 14:00:58 +0900 Subject: [PATCH 3/8] drm/panel: use gpiod interface for enable GPIO Use the new GPIO descriptor interface to handle the panel's enable GPIO. This considerably simplifies the code. Signed-off-by: Alexandre Courbot [treding@nvidia.com: rework to improve readability] Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 67 ++++++++-------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 0231945c2934..87cc238c8a85 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -22,9 +22,8 @@ */ #include -#include +#include #include -#include #include #include #include @@ -44,9 +43,6 @@ struct panel_desc { } size; }; -/* TODO: convert to gpiod_*() API once it's been merged */ -#define GPIO_ACTIVE_LOW (1 << 0) - struct panel_simple { struct drm_panel base; bool enabled; @@ -57,8 +53,7 @@ struct panel_simple { struct regulator *supply; struct i2c_adapter *ddc; - unsigned long enable_gpio_flags; - int enable_gpio; + struct gpio_desc *enable_gpio; }; static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) @@ -110,12 +105,8 @@ static int panel_simple_disable(struct drm_panel *panel) backlight_update_status(p->backlight); } - if (gpio_is_valid(p->enable_gpio)) { - if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) - gpio_set_value(p->enable_gpio, 1); - else - gpio_set_value(p->enable_gpio, 0); - } + if (p->enable_gpio) + gpiod_set_value(p->enable_gpio, 0); regulator_disable(p->supply); p->enabled = false; @@ -137,12 +128,8 @@ static int panel_simple_enable(struct drm_panel *panel) return err; } - if (gpio_is_valid(p->enable_gpio)) { - if (p->enable_gpio_flags & GPIO_ACTIVE_LOW) - gpio_set_value(p->enable_gpio, 0); - else - gpio_set_value(p->enable_gpio, 1); - } + if (p->enable_gpio) + gpiod_set_value(p->enable_gpio, 1); if (p->backlight) { p->backlight->props.power = FB_BLANK_UNBLANK; @@ -185,7 +172,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) { struct device_node *backlight, *ddc; struct panel_simple *panel; - enum of_gpio_flags flags; int err; panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); @@ -199,29 +185,20 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) if (IS_ERR(panel->supply)) return PTR_ERR(panel->supply); - panel->enable_gpio = of_get_named_gpio_flags(dev->of_node, - "enable-gpios", 0, - &flags); - if (gpio_is_valid(panel->enable_gpio)) { - unsigned int value; - - if (flags & OF_GPIO_ACTIVE_LOW) - panel->enable_gpio_flags |= GPIO_ACTIVE_LOW; - - err = gpio_request(panel->enable_gpio, "enable"); - if (err < 0) { - dev_err(dev, "failed to request GPIO#%u: %d\n", - panel->enable_gpio, err); + panel->enable_gpio = devm_gpiod_get(dev, "enable"); + if (IS_ERR(panel->enable_gpio)) { + err = PTR_ERR(panel->enable_gpio); + if (err != -ENOENT) { + dev_err(dev, "failed to request GPIO: %d\n", err); return err; } - value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0; - - err = gpio_direction_output(panel->enable_gpio, value); + panel->enable_gpio = NULL; + } else { + err = gpiod_direction_output(panel->enable_gpio, 0); if (err < 0) { - dev_err(dev, "failed to setup GPIO%u: %d\n", - panel->enable_gpio, err); - goto free_gpio; + dev_err(dev, "failed to setup GPIO: %d\n", err); + return err; } } @@ -230,10 +207,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) panel->backlight = of_find_backlight_by_node(backlight); of_node_put(backlight); - if (!panel->backlight) { - err = -EPROBE_DEFER; - goto free_gpio; - } + if (!panel->backlight) + return -EPROBE_DEFER; } ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); @@ -265,9 +240,6 @@ free_ddc: free_backlight: if (panel->backlight) put_device(&panel->backlight->dev); -free_gpio: - if (gpio_is_valid(panel->enable_gpio)) - gpio_free(panel->enable_gpio); return err; } @@ -287,9 +259,6 @@ static int panel_simple_remove(struct device *dev) if (panel->backlight) put_device(&panel->backlight->dev); - if (gpio_is_valid(panel->enable_gpio)) - gpio_free(panel->enable_gpio); - regulator_disable(panel->supply); return 0; From 887eb66e3ab2df12b09266724410a66c9400979a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sat, 1 Mar 2014 14:00:59 +0900 Subject: [PATCH 4/8] drm/panel: remove redundant regulator_disable() regulator_disable() is already performed by panel_simple_disable(), which is called by panel_simple_remove(). Signed-off-by: Alexandre Courbot Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 87cc238c8a85..71566d82e482 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -259,8 +259,6 @@ static int panel_simple_remove(struct device *dev) if (panel->backlight) put_device(&panel->backlight->dev); - regulator_disable(panel->supply); - return 0; } From 15c1a919ae9c0a474c9cf4816d164ced5444292d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 14 Mar 2014 12:03:47 +0100 Subject: [PATCH 5/8] drm/panel: simple: Allow GPIO accesses to sleep The enable GPIO for panels may be provided by GPIO expanders on slow busses (such as I2C), and therefore toggling the GPIO may sleep. Since these accesses don't happen in interrupt context, use the *_cansleep() variants of the GPIO API. Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 71566d82e482..789c07937990 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -106,7 +106,7 @@ static int panel_simple_disable(struct drm_panel *panel) } if (p->enable_gpio) - gpiod_set_value(p->enable_gpio, 0); + gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->supply); p->enabled = false; @@ -129,7 +129,7 @@ static int panel_simple_enable(struct drm_panel *panel) } if (p->enable_gpio) - gpiod_set_value(p->enable_gpio, 1); + gpiod_set_value_cansleep(p->enable_gpio, 1); if (p->backlight) { p->backlight->props.power = FB_BLANK_UNBLANK; From 462658b8b3bce3bf8cb158ef59ea88af54ac9277 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 14 Mar 2014 11:24:57 +0100 Subject: [PATCH 6/8] drm/panel: simple: Allow DSI panels to provide mode flags In order to differentiate between the different video modes (burst vs. non-burst, sync pulses vs. sync events) supported by peripherals, pass the flags that specify this mode in the panel description to the DSI peripheral device when probed. Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 789c07937990..9f7024c6ec94 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -425,6 +425,7 @@ static struct platform_driver panel_simple_platform_driver = { struct panel_desc_dsi { struct panel_desc desc; + unsigned long flags; enum mipi_dsi_pixel_format format; unsigned int lanes; }; @@ -451,6 +452,7 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { .height = 136, }, }, + .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, }; @@ -481,6 +483,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) if (err < 0) return err; + dsi->mode_flags = desc->flags; dsi->format = desc->format; dsi->lanes = desc->lanes; From 499ce85af98a93a1cedad78dd80cb3432631b1ee Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 21 Jan 2014 18:57:09 +0900 Subject: [PATCH 7/8] drm/panel: add support for LG LH500WX1-SD03 panel This panel is used by the NVIDIA SHIELD and supported by the simple-panel driver. Signed-off-by: Alexandre Courbot Signed-off-by: Thierry Reding --- .../bindings/panel/lg,lh500wx1-sd03.txt | 7 +++++ drivers/gpu/drm/panel/panel-simple.c | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt diff --git a/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt b/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt new file mode 100644 index 000000000000..a04fd2b2e73d --- /dev/null +++ b/Documentation/devicetree/bindings/panel/lg,lh500wx1-sd03.txt @@ -0,0 +1,7 @@ +LG Corporation 5" HD TFT LCD panel + +Required properties: +- compatible: should be "lg,lh500wx1-sd03" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9f7024c6ec94..355637d61cf3 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -430,6 +430,33 @@ struct panel_desc_dsi { unsigned int lanes; }; +static const struct drm_display_mode lg_lh500wx1_sd03_mode = { + .clock = 67000, + .hdisplay = 720, + .hsync_start = 720 + 12, + .hsync_end = 720 + 12 + 4, + .htotal = 720 + 12 + 4 + 112, + .vdisplay = 1280, + .vsync_start = 1280 + 8, + .vsync_end = 1280 + 8 + 4, + .vtotal = 1280 + 8 + 4 + 12, + .vrefresh = 60, +}; + +static const struct panel_desc_dsi lg_lh500wx1_sd03 = { + .desc = { + .modes = &lg_lh500wx1_sd03_mode, + .num_modes = 1, + .size = { + .width = 62, + .height = 110, + }, + }, + .flags = MIPI_DSI_MODE_VIDEO, + .format = MIPI_DSI_FMT_RGB888, + .lanes = 4, +}; + static const struct drm_display_mode panasonic_vvx10f004b00_mode = { .clock = 157200, .hdisplay = 1920, @@ -459,6 +486,9 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { static const struct of_device_id dsi_of_match[] = { { + .compatible = "lg,lh500wx1-sd03", + .data = &lg_lh500wx1_sd03 + }, { .compatible = "panasonic,vvx10f004b00", .data = &panasonic_vvx10f004b00 }, { From 712ac1ba63448d38e2fc3f2b58e62ca4af9778c2 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 21 Jan 2014 18:57:10 +0900 Subject: [PATCH 8/8] drm/panel: add support for LG LD070WX3-SL01 panel This panel is used by Tegra Note 7 and supported by the simple-panel driver. Signed-off-by: Alexandre Courbot Signed-off-by: Thierry Reding --- .../bindings/panel/lg,ld070wx3-sl01.txt | 7 +++++ drivers/gpu/drm/panel/panel-simple.c | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt diff --git a/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt b/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt new file mode 100644 index 000000000000..5e649cb9aa1a --- /dev/null +++ b/Documentation/devicetree/bindings/panel/lg,ld070wx3-sl01.txt @@ -0,0 +1,7 @@ +LG Corporation 7" WXGA TFT LCD panel + +Required properties: +- compatible: should be "lg,ld070wx3-sl01" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 355637d61cf3..309f29e9234a 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -430,6 +430,33 @@ struct panel_desc_dsi { unsigned int lanes; }; +static const struct drm_display_mode lg_ld070wx3_sl01_mode = { + .clock = 71000, + .hdisplay = 800, + .hsync_start = 800 + 32, + .hsync_end = 800 + 32 + 1, + .htotal = 800 + 32 + 1 + 57, + .vdisplay = 1280, + .vsync_start = 1280 + 28, + .vsync_end = 1280 + 28 + 1, + .vtotal = 1280 + 28 + 1 + 14, + .vrefresh = 60, +}; + +static const struct panel_desc_dsi lg_ld070wx3_sl01 = { + .desc = { + .modes = &lg_ld070wx3_sl01_mode, + .num_modes = 1, + .size = { + .width = 94, + .height = 151, + }, + }, + .flags = MIPI_DSI_MODE_VIDEO, + .format = MIPI_DSI_FMT_RGB888, + .lanes = 4, +}; + static const struct drm_display_mode lg_lh500wx1_sd03_mode = { .clock = 67000, .hdisplay = 720, @@ -486,6 +513,9 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { static const struct of_device_id dsi_of_match[] = { { + .compatible = "lg,ld070wx3-sl01", + .data = &lg_ld070wx3_sl01 + }, { .compatible = "lg,lh500wx1-sd03", .data = &lg_lh500wx1_sd03 }, {