From c63b1ec0904a074ae311103109b3e9946e38f2fa Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 May 2016 15:46:19 +0300 Subject: [PATCH] drm/omap: clean up the LCD clk mux code The code to set the clock muxes for DISPC's LCD clock inputs is very confusing. Especially on DRA7, there's an additional clock muxing that needs to be done, which at the moment is done in dpi.c using dss_ctrl_pll_set_control_mux(). Clean this all up by: - Using dss_clk_source instead of dss_pll_id, as dss_pll_id doesn't specify the clock source quite correctly. - Splitting the dss_select_lcd_clk_source() up into DSS version specific helper functions. - Using dss_ctrl_pll_set_control_mux() from the helper functions, so that dpi.c doesn't have to call it. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/dss/dpi.c | 4 - drivers/gpu/drm/omapdrm/dss/dss.c | 186 ++++++++++++++++++++++-------- drivers/gpu/drm/omapdrm/dss/dss.h | 2 - 3 files changed, 141 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 487d0549bd23..d4fbc46536d9 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -606,10 +606,6 @@ static void dpi_init_pll(struct dpi_data *dpi) if (!pll) return; - /* On DRA7 we need to set a mux to use the PLL */ - if (omapdss_get_version() == OMAPDSS_VER_DRA7xx) - dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel); - if (dpi_verify_dsi_pll(pll)) { DSSWARN("DSI PLL not operational\n"); return; diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 598a51b44e4a..2937a2812690 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -75,6 +75,8 @@ struct dss_features { const enum omap_display_type *ports; int num_ports; int (*dpi_select_source)(int port, enum omap_channel channel); + int (*select_lcd_source)(enum omap_channel channel, + enum dss_clk_source clk_src); }; static struct { @@ -205,68 +207,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable) 1 << shift, val << shift); } -void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, +static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src, enum omap_channel channel) { unsigned shift, val; if (!dss.syscon_pll_ctrl) - return; + return -EINVAL; switch (channel) { case OMAP_DSS_CHANNEL_LCD: shift = 3; - switch (pll_id) { - case DSS_PLL_VIDEO1: + switch (clk_src) { + case DSS_CLK_SRC_PLL1_1: val = 0; break; - case DSS_PLL_HDMI: + case DSS_CLK_SRC_HDMI_PLL: val = 1; break; default: DSSERR("error in PLL mux config for LCD\n"); - return; + return -EINVAL; } break; case OMAP_DSS_CHANNEL_LCD2: shift = 5; - switch (pll_id) { - case DSS_PLL_VIDEO1: + switch (clk_src) { + case DSS_CLK_SRC_PLL1_3: val = 0; break; - case DSS_PLL_VIDEO2: + case DSS_CLK_SRC_PLL2_3: val = 1; break; - case DSS_PLL_HDMI: + case DSS_CLK_SRC_HDMI_PLL: val = 2; break; default: DSSERR("error in PLL mux config for LCD2\n"); - return; + return -EINVAL; } break; case OMAP_DSS_CHANNEL_LCD3: shift = 7; - switch (pll_id) { - case DSS_PLL_VIDEO1: - val = 1; break; - case DSS_PLL_VIDEO2: + switch (clk_src) { + case DSS_CLK_SRC_PLL2_1: val = 0; break; - case DSS_PLL_HDMI: + case DSS_CLK_SRC_PLL1_3: + val = 1; break; + case DSS_CLK_SRC_HDMI_PLL: val = 2; break; default: DSSERR("error in PLL mux config for LCD3\n"); - return; + return -EINVAL; } break; default: DSSERR("error in PLL mux config\n"); - return; + return -EINVAL; } regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, 0x3 << shift, val << shift); + + return 0; } void dss_sdi_init(int datapairs) @@ -404,11 +408,34 @@ static void dss_dump_regs(struct seq_file *s) #undef DUMPREG } +static int dss_get_channel_index(enum omap_channel channel) +{ + switch (channel) { + case OMAP_DSS_CHANNEL_LCD: + return 0; + case OMAP_DSS_CHANNEL_LCD2: + return 1; + case OMAP_DSS_CHANNEL_LCD3: + return 2; + default: + WARN_ON(1); + return 0; + } +} + static void dss_select_dispc_clk_source(enum dss_clk_source clk_src) { int b; u8 start, end; + /* + * We always use PRCM clock as the DISPC func clock, except on DSS3, + * where we don't have separate DISPC and LCD clock sources. + */ + if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) && + clk_src != DSS_CLK_SRC_FCK)) + return; + switch (clk_src) { case DSS_CLK_SRC_FCK: b = 0; @@ -459,41 +486,108 @@ void dss_select_dsi_clk_source(int dsi_module, dss.dsi_clk_source[dsi_module] = clk_src; } +static int dss_lcd_clk_mux_dra7(enum omap_channel channel, + enum dss_clk_source clk_src) +{ + const u8 ctrl_bits[] = { + [OMAP_DSS_CHANNEL_LCD] = 0, + [OMAP_DSS_CHANNEL_LCD2] = 12, + [OMAP_DSS_CHANNEL_LCD3] = 19, + }; + + u8 ctrl_bit = ctrl_bits[channel]; + int r; + + if (clk_src == DSS_CLK_SRC_FCK) { + /* LCDx_CLK_SWITCH */ + REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit); + return -EINVAL; + } + + r = dss_ctrl_pll_set_control_mux(clk_src, channel); + if (r) + return r; + + REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit); + + return 0; +} + +static int dss_lcd_clk_mux_omap5(enum omap_channel channel, + enum dss_clk_source clk_src) +{ + const u8 ctrl_bits[] = { + [OMAP_DSS_CHANNEL_LCD] = 0, + [OMAP_DSS_CHANNEL_LCD2] = 12, + [OMAP_DSS_CHANNEL_LCD3] = 19, + }; + const enum dss_clk_source allowed_plls[] = { + [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1, + [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK, + [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1, + }; + + u8 ctrl_bit = ctrl_bits[channel]; + + if (clk_src == DSS_CLK_SRC_FCK) { + /* LCDx_CLK_SWITCH */ + REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit); + return -EINVAL; + } + + if (WARN_ON(allowed_plls[channel] != clk_src)) + return -EINVAL; + + REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit); + + return 0; +} + +static int dss_lcd_clk_mux_omap4(enum omap_channel channel, + enum dss_clk_source clk_src) +{ + const u8 ctrl_bits[] = { + [OMAP_DSS_CHANNEL_LCD] = 0, + [OMAP_DSS_CHANNEL_LCD2] = 12, + }; + const enum dss_clk_source allowed_plls[] = { + [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1, + [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1, + }; + + u8 ctrl_bit = ctrl_bits[channel]; + + if (clk_src == DSS_CLK_SRC_FCK) { + /* LCDx_CLK_SWITCH */ + REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit); + return 0; + } + + if (WARN_ON(allowed_plls[channel] != clk_src)) + return -EINVAL; + + REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit); + + return 0; +} + void dss_select_lcd_clk_source(enum omap_channel channel, enum dss_clk_source clk_src) { - int b, ix, pos; + int idx = dss_get_channel_index(channel); + int r; if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { dss_select_dispc_clk_source(clk_src); + dss.lcd_clk_source[idx] = clk_src; return; } - switch (clk_src) { - case DSS_CLK_SRC_FCK: - b = 0; - break; - case DSS_CLK_SRC_PLL1_1: - BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); - b = 1; - break; - case DSS_CLK_SRC_PLL2_1: - BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 && - channel != OMAP_DSS_CHANNEL_LCD3); - b = 1; - break; - default: - BUG(); + r = dss.feat->select_lcd_source(channel, clk_src); + if (r) return; - } - - pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : - (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19); - REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ - ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : - (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); - dss.lcd_clk_source[ix] = clk_src; + dss.lcd_clk_source[idx] = clk_src; } enum dss_clk_source dss_get_dispc_clk_source(void) @@ -509,9 +603,8 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module) enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) { if (dss_has_feature(FEAT_LCD_CLK_SRC)) { - int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : - (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); - return dss.lcd_clk_source[ix]; + int idx = dss_get_channel_index(channel); + return dss.lcd_clk_source[idx]; } else { /* LCD_CLK source is the same as DISPC_FCLK source for * OMAP2 and OMAP3 */ @@ -860,6 +953,7 @@ static const struct dss_features omap44xx_dss_feats = { .dpi_select_source = &dss_dpi_select_source_omap4, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), + .select_lcd_source = &dss_lcd_clk_mux_omap4, }; static const struct dss_features omap54xx_dss_feats = { @@ -869,6 +963,7 @@ static const struct dss_features omap54xx_dss_feats = { .dpi_select_source = &dss_dpi_select_source_omap5, .ports = omap2plus_ports, .num_ports = ARRAY_SIZE(omap2plus_ports), + .select_lcd_source = &dss_lcd_clk_mux_omap5, }; static const struct dss_features am43xx_dss_feats = { @@ -887,6 +982,7 @@ static const struct dss_features dra7xx_dss_feats = { .dpi_select_source = &dss_dpi_select_source_dra7xx, .ports = dra7xx_ports, .num_ports = ARRAY_SIZE(dra7xx_ports), + .select_lcd_source = &dss_lcd_clk_mux_dra7, }; static int dss_init_features(struct platform_device *pdev) diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 52895ba2d717..1ef53bbdddea 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -265,8 +265,6 @@ void dss_debug_dump_clocks(struct seq_file *s); #endif void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); -void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, - enum omap_channel channel); void dss_sdi_init(int datapairs); int dss_sdi_enable(void); -- 2.39.5