The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them.
Applies cleanly on 3.10rc4.
Darren Etheridge (5): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to present selection of invalid modes drm/tilcdc: whitespace fixes and tidyup
.../devicetree/bindings/drm/tilcdc/tilcdc.txt | 8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 115 +++++++++++++++++--- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 15 +++- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 22 ++++ drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 + 5 files changed, 147 insertions(+), 14 deletions(-)
TI LCD controller version 2 has an extended eleventh bit that enables horizontal resolutions greater than 1024 pixels to be specified (upto 2048). This patch adds support for setting this bit on LCDC V2.
Signed-off-by: Darren Etheridge detheridge@ti.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 +++++++++++++++ drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 + 2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 5dd3c7d..84fdf25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -310,6 +310,21 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, ((vsw & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+ /* + * be sure to set Bit 10 for the V2 LCDC controller, + * otherwise limited to 1024 pixels width, stopping + * 1920x1080 being suppoted. + */ + if (priv->rev == 2) { + if ((mode->vdisplay - 1) & 0x400) { + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } else { + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, + LCDC_LPP_B10); + } + } + /* Configure display type: */ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 17fd1b4..1bf5e25 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -80,6 +80,7 @@ #define LCDC_INVERT_PIXEL_CLOCK BIT(22) #define LCDC_INVERT_HSYNC BIT(21) #define LCDC_INVERT_VSYNC BIT(20) +#define LCDC_LPP_B10 BIT(26)
/* LCDC Block */ #define LCDC_PID_REG 0x0
Adding support for max-pixelclock and max-width device tree entries. As some devices that use the tilcdc hardware module have restrictions on the allowed/tested values. Also update DT bindings document to reflect new parameters.
Signed-off-by: Darren Etheridge detheridge@ti.com --- .../devicetree/bindings/drm/tilcdc/tilcdc.txt | 8 +++++++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++++++++++++++++++- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 15 ++++++++++++- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 22 +++++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt index e5f1301..fff10da 100644 --- a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt @@ -10,6 +10,14 @@ Recommended properties: services interrupts for this device. - ti,hwmods: Name of the hwmod associated to the LCDC
+Optional properties: + - max-bandwidth: The maximum pixels per second that the memory + interface / lcd controller combination can sustain + - max-width: The maximum horizontal pixel width supported by + the lcd controller. + - max-pixelclock: The maximum pixel clock that can be supported + by the lcd controller in KHz. + Example:
fb: fb@4830e000 { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 84fdf25..05f2b14 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -448,10 +448,29 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y;
+ /* + * some devices have a maximum allowed pixel clock + * configured from the DT + */ + if (mode->clock > priv->max_pixelclock) { + DBG("Pruning mode, pixel clock too high"); + return MODE_CLOCK_HIGH; + } + + /* + * some devices further limit the max horizontal resolution + * configured from the DT + */ + if (mode->hdisplay > priv->max_width) + return MODE_BAD_WIDTH; + /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) + bandwidth = mode->hdisplay * mode->vdisplay * + drm_mode_vrefresh(mode); + if (bandwidth > priv->max_bandwidth) { + DBG("Pruning mode, exceeds defined bandwidth limit"); return MODE_BAD; + }
return MODE_OK; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 2b5461b..b40fa91 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -210,7 +210,20 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) #endif
if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; + priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH; + + DBG("Maximum Bandwidth Value %d", priv->max_bandwidth); + + if (of_property_read_u32(node, "ti,max-width", &priv->max_width)) + priv->max_width = TILCDC_DEFAULT_MAX_WIDTH; + + DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width); + + if (of_property_read_u32(node, "ti,max-pixelclock", + &priv->max_pixelclock)) + priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK; + + DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
pm_runtime_enable(dev->dev);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 8242b5a..edb89a5 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -34,6 +34,18 @@ #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
+/* Defaulting to pixel clock defined on AM335x */ +#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 +/* Defaulting to max width as defined on AM335x */ +#define TILCDC_DEFAULT_MAX_WIDTH 2048 +/* + * This may need some tweaking, but want to allow at least 1280x1024@60 + * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to + * be supportable + */ +#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) + + struct tilcdc_drm_private { void __iomem *mmio;
@@ -43,6 +55,16 @@ struct tilcdc_drm_private {
/* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; + /* + * Pixel Clock will be restricted to some value as + * defined in the device datasheet measured in KHz + */ + uint32_t max_pixelclock; + /* + * Max allowable width is limited on a per device basis + * measured in pixels + */ + uint32_t max_width;
/* register contents saved across suspend/resume: */ u32 saved_register[12];
When hooking up to an HDMI analyzer noticed some timings were off by one. Referring to the hardware technical reference manual for the lcd controller some of the timing registers use 0 to represent 1. This patch addresses that issue.
Signed-off-by: Darren Etheridge detheridge@ti.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 05f2b14..4455a41 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -289,17 +289,22 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); + + /* + * subtract one from hfp, hbp, hsw because the hardware uses + * a value of 0 as 1 + */ if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; + reg |= ((hfp-1) & 0x300) >> 8; + reg |= ((hbp-1) & 0x300) >> 4; + reg |= ((hsw-1) & 0x3c0) << 21; } tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); + (((hbp-1) & 0xff) << 24) | + (((hfp-1) & 0xff) << 16) | + (((hsw-1) & 0x3f) << 10); if (priv->rev == 2) reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); @@ -307,7 +312,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, reg = ((mode->vdisplay - 1) & 0x3ff) | ((vbp & 0xff) << 24) | ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); + (((vsw-1) & 0x3f) << 10); tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
/*
The tilcdc has a number of limitations for the allowed sizes of the various adjustable timing parameter. Some modes are outside of these timings. This commit will prune modes that report timings that will overflow the allowed sizes in the tilcdc.
Signed-off-by: Darren Etheridge detheridge@ti.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 46 ++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4455a41..283e0a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -442,7 +442,12 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; + uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
+ /* + * check to see if the width is within the range that + * the LCD Controller physically supports + */ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) return MODE_VIRTUAL_X;
@@ -453,6 +458,47 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) if (mode->vdisplay > 2048) return MODE_VIRTUAL_Y;
+ DBG("Processing mode %dx%d@%d with pixel clock %d", + mode->hdisplay, mode->vdisplay, + drm_mode_vrefresh(mode), mode->clock); + + hbp = mode->htotal - mode->hsync_end; + hfp = mode->hsync_start - mode->hdisplay; + hsw = mode->hsync_end - mode->hsync_start; + vbp = mode->vtotal - mode->vsync_end; + vfp = mode->vsync_start - mode->vdisplay; + vsw = mode->vsync_end - mode->vsync_start; + + if ((hbp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Back Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hfp-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Front Porch out of range"); + return MODE_HBLANK_WIDE; + } + + if ((hsw-1) & ~0x3ff) { + DBG("Pruning mode: Horizontal Sync Width out of range"); + return MODE_HSYNC_WIDE; + } + + if (vbp & ~0xff) { + DBG("Pruning mode: Vertical Back Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if (vfp & ~0xff) { + DBG("Pruning mode: Vertical Front Porch out of range"); + return MODE_VBLANK_WIDE; + } + + if ((vsw-1) & ~0x3f) { + DBG("Pruning mode: Vertical Sync Width out of range"); + return MODE_VSYNC_WIDE; + } + /* * some devices have a maximum allowed pixel clock * configured from the DT
keeping checkpatch happy.
Signed-off-by: Darren Etheridge detheridge@ti.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 283e0a6..6118651 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -42,7 +42,8 @@ struct tilcdc_crtc {
static void unref_worker(struct work_struct *work) { - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); + struct tilcdc_crtc *tilcdc_crtc = + container_of(work, struct tilcdc_crtc, work); struct drm_device *dev = tilcdc_crtc->base.dev; struct drm_framebuffer *fb;
@@ -55,10 +56,12 @@ static void unref_worker(struct work_struct *work) static void set_scanout(struct drm_crtc *crtc, int n) { static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, + LCDC_DMA_FB_BASE_ADDR_0_REG, + LCDC_DMA_FB_BASE_ADDR_1_REG, }; static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, + LCDC_DMA_FB_CEILING_ADDR_0_REG, + LCDC_DMA_FB_CEILING_ADDR_1_REG, }; static const uint32_t stat[] = { LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, @@ -194,7 +197,8 @@ static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) tilcdc_crtc->frame_done = false; stop(crtc);
- /* if necessary wait for framedone irq which will still come + /* + * if necessary wait for framedone irq which will still come * before putting things to sleep.. */ if (priv->rev == 2) { @@ -504,7 +508,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) * configured from the DT */ if (mode->clock > priv->max_pixelclock) { - DBG("Pruning mode, pixel clock too high"); + DBG("Pruning mode: pixel clock too high"); return MODE_CLOCK_HIGH; }
@@ -519,7 +523,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); if (bandwidth > priv->max_bandwidth) { - DBG("Pruning mode, exceeds defined bandwidth limit"); + DBG("Pruning mode: exceeds defined bandwidth limit"); return MODE_BAD; }
On Mon, Jun 3, 2013 at 4:59 PM, Darren Etheridge detheridge@ti.com wrote:
The series of patches that follow are intended to address issues that have been found in the tilcdc drm driver. The patchset enables support for screen resolutions with horizontal resolutions greater than 1024 pixels. The patchset also addresses a limitation where certain monitor timings would overflow LCD controller timing registers causing either no monitor signal or a very corrupted display. This patchset will stop monitor modes from being reported as valid if the lcd controller cannot support them.
Looks good, thanks! For the series:
Signed-off-by: Rob Clark robdclark@gmail.com
Applies cleanly on 3.10rc4.
Darren Etheridge (5): drm/tilcdc: support pixel widths greater than 1024 drm/tilcdc: adding some more devicetree config drm/tilcdc: fixing off by one errors found on analyzer drm/tilcdc: adding more guards to present selection of invalid modes drm/tilcdc: whitespace fixes and tidyup
.../devicetree/bindings/drm/tilcdc/tilcdc.txt | 8 ++ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 115 +++++++++++++++++--- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 15 +++- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 22 ++++ drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 + 5 files changed, 147 insertions(+), 14 deletions(-)
dri-devel@lists.freedesktop.org