From 1511c75be01d0511df36096561ef2cbaaa36fa07 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 25 Sep 2014 17:56:43 +0000 Subject: [PATCH 01/16] OMAPDSS: fix AM43xx minimum pixel clock divider AM43xx supports pixel clock divider of 1, just like all OMAP3+ SoCs. Fix the minimum divider value. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dss_features.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c index 376270b777f8..b0b6dfd657bf 100644 --- a/drivers/video/fbdev/omap2/dss/dss_features.c +++ b/drivers/video/fbdev/omap2/dss/dss_features.c @@ -440,7 +440,7 @@ static const struct dss_param_range omap3_dss_param_range[] = { static const struct dss_param_range am43xx_dss_param_range[] = { [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, - [FEAT_PARAM_DSS_PCD] = { 2, 255 }, + [FEAT_PARAM_DSS_PCD] = { 1, 255 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, }; From 7b205455ccd1aa7bda065c4c5d9362f53a831d85 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 19 Sep 2014 16:59:00 +0000 Subject: [PATCH 02/16] OMAPDSS: HDMI5: Increase DDC SDA-HOLD time It has been observed that the current SDA-HOLD time is too short for some board/cable/monitor combinations. Increase the SDA-HOLD time to 1000ns. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/hdmi5_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/dss/hdmi5_core.c index a3cfe3d708f7..bfc0c4c297d6 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5_core.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.c @@ -55,7 +55,7 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core) const unsigned ss_scl_low = 4700; /* ns */ const unsigned fs_scl_high = 600; /* ns */ const unsigned fs_scl_low = 1300; /* ns */ - const unsigned sda_hold = 300; /* ns */ + const unsigned sda_hold = 1000; /* ns */ const unsigned sfr_div = 10; unsigned long long sfr; unsigned v; From e566658f2efac45bae7603f56fe44e3211c7c5a8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 28 Nov 2014 14:34:15 +0200 Subject: [PATCH 03/16] OMAPDSS: fix paddr check for TILER addresses The DISPC driver checks that the buffer address is not 0. However, when using TILER, the address space is TILER specific and 0 is a valid address. Fix the check to allow address of 0 for TILER. Signed-off-by: Tomi Valkeinen Reported-by: srinivas pulukuru --- drivers/video/fbdev/omap2/dss/dispc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 31b743c70272..a19a1d4b2d19 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -2441,7 +2441,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long lclk = dispc_plane_lclk_rate(plane); - if (paddr == 0) + if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) return -EINVAL; out_width = out_width == 0 ? width : out_width; From 6246c8b57c1467791fd5b2d25cb5b0b9059cf856 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 25 Sep 2014 16:00:44 +0300 Subject: [PATCH 04/16] OMAPDSS: TFP410: fix input sync signals TFP410 requires that DE is active high and the data and syncs are driven on rising pixel clock edge. However, at the moment the driver doesn't request such syncs, and the end result is that the sync settings depend on default values, which are not right in all cases. Set the sync values explicitly. Signed-off-by: Tomi Valkeinen --- .../video/fbdev/omap2/displays-new/encoder-tfp410.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c index 92919a74e715..d9048b3df495 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c @@ -114,12 +114,21 @@ static void tfp410_disable(struct omap_dss_device *dssdev) dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } +static void tfp410_fix_timings(struct omap_video_timings *timings) +{ + timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; +} + static void tfp410_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; + tfp410_fix_timings(timings); + ddata->timings = *timings; dssdev->panel.timings = *timings; @@ -140,6 +149,8 @@ static int tfp410_check_timings(struct omap_dss_device *dssdev, struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; + tfp410_fix_timings(timings); + return in->ops.dpi->check_timings(in, timings); } From 7a16360d56f6846da5a7c8cb50b14e3464ad133a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 2 Oct 2014 17:58:48 +0000 Subject: [PATCH 05/16] OMAPDSS: DISPC: remove OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES DISPC can drive data lines either on rising or falling pixel clock edge, which can be configured by the user. Sync lines can also be driven on rising or falling pixel clock edge, but additionally the HW can be configured to drive the sync lines on opposite clock edge from the data lines. This opposite edge setting does not make any sense, as the same effect can be achieved by just setting the sync lines to be driven on the other edge compared to the data lines. It feels like some kind of backward compatibility option, even if all DSS versions seem to have the same implementation. To simplify the code and configuration of the signals, and to make the dispc timings more compatible with what is used on other platforms, let's just remove the whole opposite-edge support. The drivers that used OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES setting are changed so that they use the opposite setting from the data edge. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_connector.c | 2 +- drivers/video/fbdev/omap2/displays-new/connector-dvi.c | 2 +- .../omap2/displays-new/panel-lgphilips-lb035q02.c | 2 +- .../fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c | 2 +- .../fbdev/omap2/displays-new/panel-sony-acx565akm.c | 2 +- .../fbdev/omap2/displays-new/panel-tpo-td028ttec1.c | 2 +- .../fbdev/omap2/displays-new/panel-tpo-td043mtea1.c | 2 +- drivers/video/fbdev/omap2/dss/dispc.c | 10 +++------- drivers/video/fbdev/omap2/dss/display.c | 4 +++- drivers/video/fbdev/omap2/dss/dsi.c | 2 +- drivers/video/fbdev/omap2/dss/rfbi.c | 2 +- drivers/video/fbdev/omap2/omapfb/omapfb-main.c | 4 ++-- include/video/omapdss.h | 1 - 13 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index a94b11f7859d..2c2173bc3f00 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -102,7 +102,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; } static enum drm_connector_status omap_connector_detect( diff --git a/drivers/video/fbdev/omap2/displays-new/connector-dvi.c b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c index 0cdc97413020..a8ce920fa797 100644 --- a/drivers/video/fbdev/omap2/displays-new/connector-dvi.c +++ b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c @@ -37,7 +37,7 @@ static const struct omap_video_timings dvic_default_timings = { .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; struct panel_drv_data { diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c index 27d4fcfa1824..9974a37a11af 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c @@ -37,7 +37,7 @@ static struct omap_video_timings lb035q02_timings = { .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; struct panel_drv_data { diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c index 18b19b6e1ac2..eae263702964 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c @@ -54,7 +54,7 @@ static const struct omap_video_timings sharp_ls_timings = { .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c index 337ccc5c0f5e..90cbc4c3406c 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c @@ -108,7 +108,7 @@ static const struct omap_video_timings acx565akm_panel_timings = { .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c index fbba0b8ca871..9edc51133c59 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c @@ -58,7 +58,7 @@ static struct omap_video_timings td028ttec1_panel_timings = { .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, }; #define JBT_COMMAND 0x000 diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c index 5aba76bca25a..79e4a029aab9 100644 --- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c +++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c @@ -91,7 +91,7 @@ static const struct omap_video_timings tpo_td043_timings = { .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, .de_level = OMAPDSS_SIG_ACTIVE_HIGH, - .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, }; #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index a19a1d4b2d19..11bd780fcdfa 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -2934,22 +2934,18 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, case OMAPDSS_DRIVE_SIG_FALLING_EDGE: ipc = true; break; - case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES: default: BUG(); } + /* always use the 'rf' setting */ + onoff = true; + switch (sync_pclk_edge) { - case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES: - onoff = false; - rf = false; - break; case OMAPDSS_DRIVE_SIG_FALLING_EDGE: - onoff = true; rf = false; break; case OMAPDSS_DRIVE_SIG_RISING_EDGE: - onoff = true; rf = true; break; default: diff --git a/drivers/video/fbdev/omap2/dss/display.c b/drivers/video/fbdev/omap2/dss/display.c index 2412a0dd0c13..a6fd2d35ad60 100644 --- a/drivers/video/fbdev/omap2/dss/display.c +++ b/drivers/video/fbdev/omap2/dss/display.c @@ -295,7 +295,9 @@ void videomode_to_omap_video_timings(const struct videomode *vm, OMAPDSS_DRIVE_SIG_RISING_EDGE : OMAPDSS_DRIVE_SIG_FALLING_EDGE; - ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + ovt->sync_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? + OMAPDSS_DRIVE_SIG_FALLING_EDGE : + OMAPDSS_DRIVE_SIG_RISING_EDGE; } EXPORT_SYMBOL(videomode_to_omap_video_timings); diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c index 5081f6fb1737..28b0bc11669d 100644 --- a/drivers/video/fbdev/omap2/dss/dsi.c +++ b/drivers/video/fbdev/omap2/dss/dsi.c @@ -4137,7 +4137,7 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; - dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; dss_mgr_set_timings(mgr, &dsi->timings); diff --git a/drivers/video/fbdev/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/dss/rfbi.c index 28e694b11ff9..065effca9236 100644 --- a/drivers/video/fbdev/omap2/dss/rfbi.c +++ b/drivers/video/fbdev/omap2/dss/rfbi.c @@ -869,7 +869,7 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; - rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; dss_mgr_set_timings(mgr, &rfbi.timings); } diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c index 22f07f88bc40..4f0cbb54d4db 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c @@ -2073,7 +2073,7 @@ static int omapfb_mode_to_timings(const char *mode_str, } else { timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; } timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000; @@ -2223,7 +2223,7 @@ static void fb_videomode_to_omap_timings(struct fb_videomode *m, } else { t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; t->de_level = OMAPDSS_SIG_ACTIVE_HIGH; - t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; } t->x_res = m->xres; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 60de61fea8e3..7414e4a97508 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -134,7 +134,6 @@ enum omap_dss_signal_level { }; enum omap_dss_signal_edge { - OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, OMAPDSS_DRIVE_SIG_RISING_EDGE, OMAPDSS_DRIVE_SIG_FALLING_EDGE, }; From ed35188158552d4b1e7a8df2a10dedf88c813539 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 2 Oct 2014 17:58:49 +0000 Subject: [PATCH 06/16] OMAPDSS: DISPC: explicit handling for sync and de levels When configuring the lcd timings, instead of writing enum values directly to the HW, use switch-case to get the value to be programmed. This is safer and also allows us to change the enum values. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dispc.c | 41 ++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 11bd780fcdfa..8805266a52f4 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -2915,7 +2915,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, { u32 timing_h, timing_v, l; - bool onoff, rf, ipc; + bool onoff, rf, ipc, vs, hs, de; timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) | FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | @@ -2927,6 +2927,39 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); + switch (vsync_level) { + case OMAPDSS_SIG_ACTIVE_LOW: + vs = true; + break; + case OMAPDSS_SIG_ACTIVE_HIGH: + vs = false; + break; + default: + BUG(); + } + + switch (hsync_level) { + case OMAPDSS_SIG_ACTIVE_LOW: + hs = true; + break; + case OMAPDSS_SIG_ACTIVE_HIGH: + hs = false; + break; + default: + BUG(); + } + + switch (de_level) { + case OMAPDSS_SIG_ACTIVE_LOW: + de = true; + break; + case OMAPDSS_SIG_ACTIVE_HIGH: + de = false; + break; + default: + BUG(); + } + switch (data_pclk_edge) { case OMAPDSS_DRIVE_SIG_RISING_EDGE: ipc = false; @@ -2954,10 +2987,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, l = FLD_VAL(onoff, 17, 17) | FLD_VAL(rf, 16, 16) | - FLD_VAL(de_level, 15, 15) | + FLD_VAL(de, 15, 15) | FLD_VAL(ipc, 14, 14) | - FLD_VAL(hsync_level, 13, 13) | - FLD_VAL(vsync_level, 12, 12); + FLD_VAL(hs, 13, 13) | + FLD_VAL(vs, 12, 12); dispc_write_reg(DISPC_POL_FREQ(channel), l); From 7ad582be12728ea76b11ce4f4c2f1202d11bf13c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 2 Oct 2014 17:58:50 +0000 Subject: [PATCH 07/16] OMAPDSS: change signal_level & signal_edge enum values At the moment the enum values for ACTIVE_HIGH and RISING_EDGE are 0, and ACTIVE_LOW and FALLING_EDGE are 1, to match the values programmed to HW. The previous patch removed this dependency. Swap the enum values the other way around. This doesn't change the behavior in any way, but makes it easier to debug as value of '1' means HIGH or RISING. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 7414e4a97508..45a230190720 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -129,13 +129,13 @@ enum omap_rfbi_te_mode { }; enum omap_dss_signal_level { - OMAPDSS_SIG_ACTIVE_HIGH = 0, - OMAPDSS_SIG_ACTIVE_LOW = 1, + OMAPDSS_SIG_ACTIVE_LOW, + OMAPDSS_SIG_ACTIVE_HIGH, }; enum omap_dss_signal_edge { - OMAPDSS_DRIVE_SIG_RISING_EDGE, OMAPDSS_DRIVE_SIG_FALLING_EDGE, + OMAPDSS_DRIVE_SIG_RISING_EDGE, }; enum omap_dss_venc_type { From 386f167c69ca1c6920581f2cb78be8a1f6691539 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 2 Oct 2014 17:58:51 +0000 Subject: [PATCH 08/16] OMAPDSS: DISPC: change sync_pclk_edge default value The common 'struct videomode' does not have a flag to select when the sync signals should be driven. The default behavior of DISPC HW is to drive the sync signal on the opposite pixel clock edge from data signal, which is also what the videomode_to_omap_video_timings() uses. However, it looks like what panels usually expect is that the data and sync signals are driven on the same edge, so let's change videomode_to_omap_video_timings() to set the sync_pclk_edge accordingly. Note that this only affect panels drivers that use videomode_to_omap_video_timings(), probably when getting the video timings directly from DT data. The drivers can still configure the sync_pclk_edge independently if they so wish. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/display.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/video/fbdev/omap2/dss/display.c b/drivers/video/fbdev/omap2/dss/display.c index a6fd2d35ad60..ef5b9027985d 100644 --- a/drivers/video/fbdev/omap2/dss/display.c +++ b/drivers/video/fbdev/omap2/dss/display.c @@ -295,9 +295,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, OMAPDSS_DRIVE_SIG_RISING_EDGE : OMAPDSS_DRIVE_SIG_FALLING_EDGE; - ovt->sync_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? - OMAPDSS_DRIVE_SIG_FALLING_EDGE : - OMAPDSS_DRIVE_SIG_RISING_EDGE; + ovt->sync_pclk_edge = ovt->data_pclk_edge; } EXPORT_SYMBOL(videomode_to_omap_video_timings); From 4e1d3ca0836b6b44c358c5ace79aa15a091a4142 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 3 Oct 2014 15:14:09 +0000 Subject: [PATCH 09/16] OMAPDSS: DISPC: fix div by zero issue in overlay scaling omapdrm doesn't always configure the overlays correctly, causing the overlay setup functions to be called with zero timings. This leads to division by zero error. This happens, for example, when a HDMI cable is not connected, but a user tries to setup a plane with scaling. Fixing omapdrm is a big job, so for now let's check for the bad timings in DISPC and return an error. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dispc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 8805266a52f4..1123111d3940 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -2322,6 +2322,11 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, if (width == out_width && height == out_height) return 0; + if (pclk == 0 || mgr_timings->pixelclock == 0) { + DSSERR("cannot calculate scaling settings: pclk is zero\n"); + return -EINVAL; + } + if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0) return -EINVAL; From d49cd15550d9d4495f6187425318c245d58cb63f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 10 Nov 2014 12:23:00 +0200 Subject: [PATCH 10/16] OMAPDSS: DISPC: lock access to DISPC_CONTROL & DISPC_CONFIG Dispc driver presumes that the callers handle locking for all normal functions. However, omapdrm doesn't handle this, and presumes that all overlay manager registers are private to that overlay manager, and thus presumes that configurations for overlay managers can be written via different threads freely. For many registers the above is true. The exceptions are DISPC_CONTROL and DISPC_CONFIG registers, which contain bits for both LCD and TV overlay managers. Fixing this properly in omapdrm means a big omapdrm rewrite. So, for now, add locking to dispc for the problematic registers. Signed-off-by: Tomi Valkeinen Reported-by: Somnath Mukherjee --- drivers/video/fbdev/omap2/dss/dispc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 1123111d3940..766c985cbfa7 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -123,6 +123,9 @@ static struct { struct regmap *syscon_pol; u32 syscon_pol_offset; + + /* DISPC_CONTROL & DISPC_CONFIG lock*/ + spinlock_t control_lock; } dispc; enum omap_color_component { @@ -261,7 +264,16 @@ static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld) static void mgr_fld_write(enum omap_channel channel, enum mgr_reg_fields regfld, int val) { const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld]; + const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG; + unsigned long flags; + + if (need_lock) + spin_lock_irqsave(&dispc.control_lock, flags); + REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low); + + if (need_lock) + spin_unlock_irqrestore(&dispc.control_lock, flags); } #define SR(reg) \ @@ -3804,6 +3816,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) dispc.pdev = pdev; + spin_lock_init(&dispc.control_lock); + r = dispc_init_features(dispc.pdev); if (r) return r; From 47fc469b3af5fc63d65a51e21acaa3ed06c288e7 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 29 Sep 2014 20:46:17 +0000 Subject: [PATCH 11/16] OMAPDSS: setup default fifo thresholds At the moment we don't setup FIFO thresholds by default in omapdss. It's supposed to be done by the user of omapdss. And that is missing from omapdrm, causing unoptimal thresholds to be used when using omapdrm. While I believe it's in theory better to allow the user of omapdss to setup the fifo thresholds, in practice we always use the same values, and we could as well setup the thresholds in omapdss. Furthermore, in omapdss init we always swap the FIFO used for GFX and WB overlays, but we don't swap the FIFO thresholds for those overlays (which is the reason for omapdrm using unoptimal HW reset values). So it would make sense to setup the thresholds to account for the swapping of the FIFOs. So, this patch adds code to setup default FIFO tresholds at omapdss init. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dispc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 766c985cbfa7..6296a3e5124f 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -1138,6 +1138,7 @@ static void dispc_init_fifos(void) int fifo; u8 start, end; u32 unit; + int i; unit = dss_feat_get_buffer_size_unit(); @@ -1177,6 +1178,20 @@ static void dispc_init_fifos(void) dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB; dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX; } + + /* + * Setup default fifo thresholds. + */ + for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + u32 low, high; + const bool use_fifomerge = false; + const bool manual_update = false; + + dispc_ovl_compute_fifo_thresholds(i, &low, &high, + use_fifomerge, manual_update); + + dispc_ovl_set_fifo_threshold(i, low, high); + } } static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) From c64aa3a6600fa5ab25c3ff535d134c8f09add5aa Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 29 Sep 2014 20:46:18 +0000 Subject: [PATCH 12/16] OMAPDSS: Add support for MFLAG OMAP5 has support for MFLAG feature, which allows DSS to dynamically increase the priority of DISPC's DMA traffic. At the moment we don't have support for it. It was noticed that on DRA7 with high bandwidth use cases we see FIFO underflows. Implementing MFLAG support removed those underflows. Interestingly, on OMAP5 uEVM no such overflows were seen. This patch adds a simple MFLAG implementation, where we use a fixed MFLAG threshold value based on the FIFO size. The thresholds are set to 4/8 of fifo size for low threshold, and 5/8 of fifo size for high threshold. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dispc.c | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 6296a3e5124f..6b056d0ce187 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -1305,6 +1305,53 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, } EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds); +static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable) +{ + int bit; + + if (plane == OMAP_DSS_GFX) + bit = 14; + else + bit = 23; + + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); +} + +static void dispc_ovl_set_mflag_threshold(enum omap_plane plane, + int low, int high) +{ + dispc_write_reg(DISPC_OVL_MFLAG_THRESHOLD(plane), + FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0)); +} + +static void dispc_init_mflag(void) +{ + int i; + + dispc_write_reg(DISPC_GLOBAL_MFLAG_ATTRIBUTE, + (2 << 0) | /* MFLAG_CTRL = enable */ + (0 << 2)); /* MFLAG_START = disable */ + + for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + u32 size = dispc_ovl_get_fifo_size(i); + u32 unit = dss_feat_get_buffer_size_unit(); + u32 low, high; + + dispc_ovl_set_mflag(i, true); + + /* + * Simulation team suggests below thesholds: + * HT = fifosize * 5 / 8; + * LT = fifosize * 4 / 8; + */ + + low = size * 4 / 8 / unit; + high = size * 5 / 8 / unit; + + dispc_ovl_set_mflag_threshold(i, low, high); + } +} + static void dispc_ovl_set_fir(enum omap_plane plane, int hinc, int vinc, enum omap_color_component color_comp) @@ -3630,6 +3677,9 @@ static void _omap_dispc_initial_config(void) if (dispc.feat->mstandby_workaround) REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); + + if (dss_has_feature(FEAT_MFLAG)) + dispc_init_mflag(); } static const struct dispc_features omap24xx_dispc_feats __initconst = { From fe59e5cf4abb922d37caea2ced6331cce48fb8b8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 19 Nov 2014 12:50:16 +0200 Subject: [PATCH 13/16] OMAPDSS: workaround for MFLAG + NV12 issue It was found that having two displays enabled and having an NV12 overlay on one of the displays will cause underflows/synclosts. Debugging this pointed to some issue with MFLAG. It is unclear why this issue is happening, but it looks like there is a HW bug related to MFLAG and FIFO management. Disabling MFLAG makes this issue go away, but then we lose the benefit of MFLAG. Also forcing MFLAG always on makes the issue go away. Also, using certain values for MFLAG_START, MFLAG thresholds and PRELOAD makes the issue go away, but there was no obvious logic to which values work and which don't. As a workaround until more information about this is found, force MFLAG always on to make NV12 usable. Signed-off-by: Tomi Valkeinen --- drivers/video/fbdev/omap2/dss/dispc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 6b056d0ce187..f4fc77d9d3bf 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c @@ -1328,8 +1328,18 @@ static void dispc_init_mflag(void) { int i; + /* + * HACK: NV12 color format and MFLAG seem to have problems working + * together: using two displays, and having an NV12 overlay on one of + * the displays will cause underflows/synclosts when MFLAG_CTRL=2. + * Changing MFLAG thresholds and PRELOAD to certain values seem to + * remove the errors, but there doesn't seem to be a clear logic on + * which values work and which not. + * + * As a work-around, set force MFLAG to always on. + */ dispc_write_reg(DISPC_GLOBAL_MFLAG_ATTRIBUTE, - (2 << 0) | /* MFLAG_CTRL = enable */ + (1 << 0) | /* MFLAG_CTRL = force always on */ (0 << 2)); /* MFLAG_START = disable */ for (i = 0; i < dss_feat_get_num_ovls(); ++i) { From cb17a4ae3bbf1daa3b179147b6d476ea2482e2d3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 25 Feb 2015 12:08:14 +0200 Subject: [PATCH 14/16] OMAPDSS: disable VT switch We don't need VT switch when suspending/resuming, so disable it. This speeds up suspend/resume. Signed-off-by: Tomi Valkeinen Cc: NeilBrown --- drivers/video/fbdev/omap2/dss/dss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index a6d10d4279f3..7f978b6a34e8 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c @@ -38,6 +38,7 @@ #include #include #include +#include #include