diff options
author | Dave Airlie <airlied@redhat.com> | 2016-09-02 15:50:51 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-09-02 15:50:51 +1000 |
commit | eb97027f0789bd6dcfa088b66de0c287dc4ff57a (patch) | |
tree | a1604c6926bb4385717311091d02fdadf52bec27 | |
parent | 2c07d5a8b827364af27df4bd6e669705d182be12 (diff) | |
parent | c56653855250ca6072d6e0ad7fe537c1a6628c70 (diff) | |
download | linux-stable-eb97027f0789bd6dcfa088b66de0c287dc4ff57a.tar.gz linux-stable-eb97027f0789bd6dcfa088b66de0c287dc4ff57a.tar.bz2 linux-stable-eb97027f0789bd6dcfa088b66de0c287dc4ff57a.zip |
Merge tag 'tilcdc-4.9-fixes' of https://github.com/jsarha/linux into drm-next
tilcdc fixes for v4.9
* tag 'tilcdc-4.9-fixes' of https://github.com/jsarha/linux:
drm/tilcdc: Choose console BPP that supports RGB
drm/tilcdc: Add blue-and-red-crossed devicetree property
drm/tilcdc: Write DMA base and ceiling address with single instruction
drm/tilcdc: Remove drm_helper_disable_unused_functions() call
drm/tilcdc: Enable EOF interrupts for v1 LCDC
drm/tilcdc: Adjust the FB_CEILING address
drm/tilcdc: Fix check for remote port parent
-rw-r--r-- | Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_external.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_external.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_plane.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_regs.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 2 |
10 files changed, 104 insertions, 30 deletions
diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt index 6efa4c55d118..a5007aa437f3 100644 --- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt +++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt @@ -17,6 +17,18 @@ Optional properties: the lcd controller. - max-pixelclock: The maximum pixel clock that can be supported by the lcd controller in KHz. + - blue-and-red-wiring: Recognized values "default", "straight" or + "crossed". This property deals with the LCDC revision 2 (found on + AM335x) color errata [1]. + - "straight" indicates normal wiring that supports RGB565, + BGR888, and XBGR8888 color formats. + - "crossed" indicates wiring that has blue and red wires + crossed. This setup supports BGR565, RGB888 and XRGB8888 + formats. + - If the property is not present or its value is not recognized + the legacy mode is assumed. This configuration supports RGB565, + RGB888 and XRGB8888 formats. However, depending on wiring, the red + and blue colors are swapped in either 16 or 24-bit color modes. Optional nodes: @@ -28,6 +40,14 @@ Optional nodes: Documentation/devicetree/bindings/display/tilcdc/tfp410.txt for connecting tfp410 DVI encoder or lcd panel to lcdc +[1] There is an errata about AM335x color wiring. For 16-bit color mode + the wires work as they should (LCD_DATA[0:4] is for Blue[3:7]), + but for 24 bit color modes the wiring of blue and red components is + crossed and LCD_DATA[0:4] is for Red[3:7] and LCD_DATA[11:15] is + for Blue[3-7]. For more details see section 3.1.1 in AM335x + Silicon Errata: + http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sprz360 + Example: fb: fb@4830e000 { @@ -37,6 +57,8 @@ Example: interrupts = <36>; ti,hwmods = "lcdc"; + blue-and-red-wiring = "crossed"; + port { lcdc_0: endpoint@0 { remote-endpoint = <&hdmi_0>; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 25d6b220ee8a..208768922030 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -69,6 +69,7 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) struct drm_gem_cma_object *gem; unsigned int depth, bpp; dma_addr_t start, end; + u64 dma_base_and_ceiling; drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); gem = drm_fb_cma_get_gem_obj(fb, 0); @@ -79,8 +80,13 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) end = start + (crtc->mode.vdisplay * fb->pitches[0]); - tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, start); - tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG, end); + /* Write LCDC_DMA_FB_BASE_ADDR_0_REG and LCDC_DMA_FB_CEILING_ADDR_0_REG + * with a single insruction, if available. This should make it more + * unlikely that LCDC would fetch the DMA addresses in the middle of + * an update. + */ + dma_base_and_ceiling = (u64)(end - 1) << 32 | start; + tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_base_and_ceiling); if (tilcdc_crtc->curr_fb) drm_flip_work_queue(&tilcdc_crtc->unref_work, @@ -98,6 +104,8 @@ static void tilcdc_crtc_enable_irqs(struct drm_device *dev) if (priv->rev == 1) { tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA); + tilcdc_set(dev, LCDC_DMA_CTRL_REG, + LCDC_V1_END_OF_FRAME_INT_ENA); } else { tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA | diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 4405e4bc8056..f8892e9ad169 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -33,6 +33,20 @@ static LIST_HEAD(module_list); +static const u32 tilcdc_rev1_formats[] = { DRM_FORMAT_RGB565 }; + +static const u32 tilcdc_straight_formats[] = { DRM_FORMAT_RGB565, + DRM_FORMAT_BGR888, + DRM_FORMAT_XBGR8888 }; + +static const u32 tilcdc_crossed_formats[] = { DRM_FORMAT_BGR565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888 }; + +static const u32 tilcdc_legacy_formats[] = { DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888 }; + void tilcdc_module_init(struct tilcdc_module *mod, const char *name, const struct tilcdc_module_ops *funcs) { @@ -226,7 +240,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) struct platform_device *pdev = dev->platformdev; struct device_node *node = pdev->dev.of_node; struct tilcdc_drm_private *priv; - struct tilcdc_module *mod; struct resource *res; u32 bpp = 0; int ret; @@ -318,6 +331,37 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) pm_runtime_put_sync(dev->dev); + if (priv->rev == 1) { + DBG("Revision 1 LCDC supports only RGB565 format"); + priv->pixelformats = tilcdc_rev1_formats; + priv->num_pixelformats = ARRAY_SIZE(tilcdc_rev1_formats); + bpp = 16; + } else { + const char *str = "\0"; + + of_property_read_string(node, "blue-and-red-wiring", &str); + if (0 == strcmp(str, "crossed")) { + DBG("Configured for crossed blue and red wires"); + priv->pixelformats = tilcdc_crossed_formats; + priv->num_pixelformats = + ARRAY_SIZE(tilcdc_crossed_formats); + bpp = 32; /* Choose bpp with RGB support for fbdef */ + } else if (0 == strcmp(str, "straight")) { + DBG("Configured for straight blue and red wires"); + priv->pixelformats = tilcdc_straight_formats; + priv->num_pixelformats = + ARRAY_SIZE(tilcdc_straight_formats); + bpp = 16; /* Choose bpp with RGB support for fbdef */ + } else { + DBG("Blue and red wiring '%s' unknown, use legacy mode", + str); + priv->pixelformats = tilcdc_legacy_formats; + priv->num_pixelformats = + ARRAY_SIZE(tilcdc_legacy_formats); + bpp = 16; /* This is just a guess */ + } + } + ret = modeset_init(dev); if (ret < 0) { dev_err(dev->dev, "failed to initialize mode setting\n"); @@ -331,7 +375,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) if (ret < 0) goto fail_mode_config_cleanup; - ret = tilcdc_add_external_encoders(dev, &bpp); + ret = tilcdc_add_external_encoders(dev); if (ret < 0) goto fail_component_cleanup; } @@ -354,15 +398,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) goto fail_vblank_cleanup; } - list_for_each_entry(mod, &module_list, list) { - DBG("%s: preferred_bpp: %d", mod->name, mod->preferred_bpp); - bpp = mod->preferred_bpp; - if (bpp > 0) - break; - } - - drm_helper_disable_unused_functions(dev); - drm_mode_config_reset(dev); priv->fbdev = drm_fbdev_cma_init(dev, bpp, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 13001df7dbe8..a6e5e6d4970c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -65,6 +65,10 @@ struct tilcdc_drm_private { */ uint32_t max_width; + /* Supported pixel formats */ + const uint32_t *pixelformats; + uint32_t num_pixelformats; + /* The context for pm susped/resume cycle is stored here */ struct drm_atomic_state *saved_state; @@ -112,7 +116,6 @@ struct tilcdc_module { const char *name; struct list_head list; const struct tilcdc_module_ops *funcs; - unsigned int preferred_bpp; }; void tilcdc_module_init(struct tilcdc_module *mod, const char *name, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c index ad3db4d30b49..68e895021005 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c @@ -52,7 +52,7 @@ static int tilcdc_external_mode_valid(struct drm_connector *connector, return MODE_OK; } -static int tilcdc_add_external_encoder(struct drm_device *dev, int *bpp, +static int tilcdc_add_external_encoder(struct drm_device *dev, struct drm_connector *connector) { struct tilcdc_drm_private *priv = dev->dev_private; @@ -64,7 +64,6 @@ static int tilcdc_add_external_encoder(struct drm_device *dev, int *bpp, /* Only tda998x is supported at the moment. */ tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true); tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x); - *bpp = panel_info_tda998x.bpp; connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs), GFP_KERNEL); @@ -94,7 +93,7 @@ static int tilcdc_add_external_encoder(struct drm_device *dev, int *bpp, return 0; } -int tilcdc_add_external_encoders(struct drm_device *dev, int *bpp) +int tilcdc_add_external_encoders(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; struct drm_connector *connector; @@ -108,7 +107,7 @@ int tilcdc_add_external_encoders(struct drm_device *dev, int *bpp) if (connector == priv->connectors[i]) found = true; if (!found) { - ret = tilcdc_add_external_encoder(dev, bpp, connector); + ret = tilcdc_add_external_encoder(dev, connector); if (ret) return ret; } @@ -154,7 +153,7 @@ int tilcdc_get_external_components(struct device *dev, while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) { node = of_graph_get_remote_port_parent(ep); - if (!node && !of_device_is_available(node)) { + if (!node || !of_device_is_available(node)) { of_node_put(node); continue; } diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.h b/drivers/gpu/drm/tilcdc/tilcdc_external.h index 6aabe2788760..c700e0c1623e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.h @@ -18,7 +18,7 @@ #ifndef __TILCDC_EXTERNAL_H__ #define __TILCDC_EXTERNAL_H__ -int tilcdc_add_external_encoders(struct drm_device *dev, int *bpp); +int tilcdc_add_external_encoders(struct drm_device *dev); void tilcdc_remove_external_encoders(struct drm_device *dev); int tilcdc_get_external_components(struct device *dev, struct component_match **match); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 4ac1d25eb79b..7b3650901930 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -397,8 +397,6 @@ static int panel_probe(struct platform_device *pdev) goto fail_timings; } - mod->preferred_bpp = panel_mod->info->bpp; - return 0; fail_timings: diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 41911e3110e8..74c65fa859b2 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -24,10 +24,6 @@ #include "tilcdc_drv.h" -static const u32 tilcdc_formats[] = { DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888 }; - static struct drm_plane_funcs tilcdc_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -114,12 +110,13 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { int tilcdc_plane_init(struct drm_device *dev, struct drm_plane *plane) { + struct tilcdc_drm_private *priv = dev->dev_private; int ret; ret = drm_plane_init(dev, plane, 1, &tilcdc_plane_funcs, - tilcdc_formats, - ARRAY_SIZE(tilcdc_formats), + priv->pixelformats, + priv->num_pixelformats, true); if (ret) { dev_err(dev->dev, "Failed to initialize plane: %d\n", ret); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 1bf5e2553acc..f57c0d62c76a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -119,6 +119,20 @@ static inline void tilcdc_write(struct drm_device *dev, u32 reg, u32 data) iowrite32(data, priv->mmio + reg); } +static inline void tilcdc_write64(struct drm_device *dev, u32 reg, u64 data) +{ + struct tilcdc_drm_private *priv = dev->dev_private; + volatile void __iomem *addr = priv->mmio + reg; + +#ifdef iowrite64 + iowrite64(data, addr); +#else + __iowmb(); + /* This compiles to strd (=64-bit write) on ARM7 */ + *(volatile u64 __force *)addr = __cpu_to_le64(data); +#endif +} + static inline u32 tilcdc_read(struct drm_device *dev, u32 reg) { struct tilcdc_drm_private *priv = dev->dev_private; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 741c7b5b8302..c6a70da6473d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -327,8 +327,6 @@ static int tfp410_probe(struct platform_device *pdev) goto fail; } - mod->preferred_bpp = dvi_info.bpp; - i2c_node = of_find_node_by_phandle(i2c_phandle); if (!i2c_node) { dev_err(&pdev->dev, "could not get i2c bus node\n"); |