From d66b15818c16af35ddb5da7b53905d9f6f62a45b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 24 Sep 2012 15:15:06 +0300 Subject: [PATCH 1/9] OMAPDSS: DSI: improve DSI clock calcs for DISPC Commit ee144e645a081daad5de1ccac77f0a0e98e6a67b added dsi_pll_calc_ddrfreq() which calculates PLL dividers based on given DSI bus clock speed. The function works ok, but it can be improved for the DISPC clock calc. The current version calculates the clock going from the PLL to the DISPC simply by setting the clock as close to DISPC maximum as possible, and the pixel clock is calculated based on that. This patch changes the function to calculate DISPC clock more dynamically, iterating through different DISPC clocks and pixel clock values, and thus we'll get more suitable pixel clocks. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 144 ++++++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 31 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 8d815e39e45..8d47fb7c4b8 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1454,26 +1454,17 @@ found: } static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, - unsigned long req_clk, struct dsi_clock_info *cinfo) + unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_clock_info cur, best; - unsigned long dss_sys_clk, max_dss_fck, max_dsi_fck; - unsigned long req_clkin4ddr; DSSDBG("dsi_pll_calc_ddrfreq\n"); - dss_sys_clk = clk_get_rate(dsi->sys_clk); - - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); - memset(&best, 0, sizeof(best)); memset(&cur, 0, sizeof(cur)); - cur.clkin = dss_sys_clk; - - req_clkin4ddr = req_clk * 4; + cur.clkin = clk_get_rate(dsi->sys_clk); for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { cur.fint = cur.clkin / cur.regn; @@ -1503,18 +1494,107 @@ static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, } } found: - best.regm_dispc = DIV_ROUND_UP(best.clkin4ddr, max_dss_fck); - best.dsi_pll_hsdiv_dispc_clk = best.clkin4ddr / best.regm_dispc; - - best.regm_dsi = DIV_ROUND_UP(best.clkin4ddr, max_dsi_fck); - best.dsi_pll_hsdiv_dsi_clk = best.clkin4ddr / best.regm_dsi; - if (cinfo) *cinfo = best; return 0; } +static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, + struct dsi_clock_info *cinfo) +{ + unsigned long max_dsi_fck; + + max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); + + cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck); + cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; +} + +static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev, + unsigned long req_pck, struct dsi_clock_info *cinfo, + struct dispc_clock_info *dispc_cinfo) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + unsigned regm_dispc, best_regm_dispc; + unsigned long dispc_clk, best_dispc_clk; + int min_fck_per_pck; + unsigned long max_dss_fck; + struct dispc_clock_info best_dispc; + bool match; + + max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + + if (min_fck_per_pck && + req_pck * min_fck_per_pck > max_dss_fck) { + DSSERR("Requested pixel clock not possible with the current " + "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " + "the constraint off.\n"); + min_fck_per_pck = 0; + } + +retry: + best_regm_dispc = 0; + best_dispc_clk = 0; + memset(&best_dispc, 0, sizeof(best_dispc)); + match = false; + + for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) { + struct dispc_clock_info cur_dispc; + + dispc_clk = cinfo->clkin4ddr / regm_dispc; + + /* this will narrow down the search a bit, + * but still give pixclocks below what was + * requested */ + if (dispc_clk < req_pck) + break; + + if (dispc_clk > max_dss_fck) + continue; + + if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck) + continue; + + match = true; + + dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc); + + if (abs(cur_dispc.pck - req_pck) < + abs(best_dispc.pck - req_pck)) { + best_regm_dispc = regm_dispc; + best_dispc_clk = dispc_clk; + best_dispc = cur_dispc; + + if (cur_dispc.pck == req_pck) + goto found; + } + } + + if (!match) { + if (min_fck_per_pck) { + DSSERR("Could not find suitable clock settings.\n" + "Turning FCK/PCK constraint off and" + "trying again.\n"); + min_fck_per_pck = 0; + goto retry; + } + + DSSERR("Could not find suitable clock settings.\n"); + + return -EINVAL; + } +found: + cinfo->regm_dispc = best_regm_dispc; + cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk; + + *dispc_cinfo = best_dispc; + + return 0; +} + int dsi_pll_set_clock_div(struct platform_device *dsidev, struct dsi_clock_info *cinfo) { @@ -4188,33 +4268,35 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, mutex_lock(&dsi->lock); - r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk, &cinfo); + /* Calculate PLL output clock */ + r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo); if (r) goto err; + /* Calculate PLL's DSI clock */ + dsi_pll_calc_dsi_fck(dsidev, &cinfo); + + /* Calculate PLL's DISPC clock and pck & lck divs */ + pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; + DSSDBG("finding dispc dividers for pck %lu\n", pck); + r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo); + if (r) + goto err; + + /* Calculate LP clock */ + dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; + lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); + dssdev->clocks.dsi.regn = cinfo.regn; dssdev->clocks.dsi.regm = cinfo.regm; dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc; dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi; - - dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; - lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); - dssdev->clocks.dsi.lp_clk_div = lp_clk_div; - /* pck = TxByteClkHS * datalanes * 8 / bitsperpixel */ - - pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; - - DSSDBG("finding dispc dividers for pck %lu\n", pck); - - dispc_find_clk_divs(pck, cinfo.dsi_pll_hsdiv_dispc_clk, &dispc_cinfo); - dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div; - dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; dssdev->clocks.dispc.channel.lcd_clk_src = From 233628328037c02cf3db6165cab5d3f43587c5f3 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Sun, 8 Apr 2012 16:47:01 +0530 Subject: [PATCH 2/9] OMAPDSS: Add basic omap5 features to dss and dispc Add basic omap5 features for dss and dispc. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 2 + drivers/video/omap2/dss/dss.c | 8 +++ drivers/video/omap2/dss/dss_features.c | 93 ++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index d512c389741..e52c5778938 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3829,6 +3829,8 @@ static int __init dispc_init_features(struct device *dev) src = &omap34xx_rev3_0_dispc_feats; } else if (cpu_is_omap44xx()) { src = &omap44xx_dispc_feats; + } else if (soc_is_omap54xx()) { + src = &omap44xx_dispc_feats; } else { return -ENODEV; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 759dbee4834..4524c174ac5 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -123,6 +123,12 @@ static const struct dss_features omap44xx_dss_feats __initconst = { .clk_name = "dpll_per_m5x2_ck", }; +static const struct dss_features omap54xx_dss_feats __initconst = { + .fck_div_max = 64, + .dss_fck_multiplier = 1, + .clk_name = "dpll_per_h12x2_ck", +}; + static inline void dss_write_reg(const struct dss_reg idx, u32 val) { __raw_writel(val, dss.base + idx.idx); @@ -740,6 +746,8 @@ static int __init dss_init_features(struct device *dev) src = &omap3630_dss_feats; else if (cpu_is_omap44xx()) src = &omap44xx_dss_feats; + else if (soc_is_omap54xx()) + src = &omap54xx_dss_feats; else return -ENODEV; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index c26fc1fb7db..af4775a2070 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -106,6 +106,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = { [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, }; +static const struct dss_reg_field omap5_dss_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, + [FEAT_REG_FIFOSIZE] = { 15, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, + [FEAT_REG_VERTICALACCU] = { 26, 16 }, + [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 }, + [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, + [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, + [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, + [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, +}; + static const enum omap_display_type omap2_dss_supported_displays[] = { /* OMAP_DSS_CHANNEL_LCD */ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, @@ -144,6 +159,19 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_DSI, }; +static const enum omap_display_type omap5_dss_supported_displays[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | + OMAP_DISPLAY_TYPE_DSI, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | + OMAP_DISPLAY_TYPE_DSI, +}; + static const enum omap_color_mode omap2_dss_supported_color_modes[] = { /* OMAP_DSS_GFX */ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | @@ -298,6 +326,14 @@ static const char * const omap4_dss_clk_source_names[] = { [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", }; +static const char * const omap5_dss_clk_source_names[] = { + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1", + [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2", + [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK", + [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1", + [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2", +}; + static const struct dss_param_range omap2_dss_param_range[] = { [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, [FEAT_PARAM_DSS_PCD] = { 2, 255 }, @@ -349,6 +385,22 @@ static const struct dss_param_range omap4_dss_param_range[] = { [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, }; +static const struct dss_param_range omap5_dss_param_range[] = { + [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, + [FEAT_PARAM_DSS_PCD] = { 1, 255 }, + [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, + [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, + [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, + [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, + [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, + [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, + [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, + [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, + [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 }, +}; + static const enum dss_feat_id omap2_dss_feat_list[] = { FEAT_LCDENABLEPOL, FEAT_LCDENABLESIGNAL, @@ -450,6 +502,25 @@ static const enum dss_feat_id omap4_dss_feat_list[] = { FEAT_BURST_2D, }; +static const enum dss_feat_id omap5_dss_feat_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, + FEAT_DSI_DCS_CMD_CONFIG_VC, + FEAT_DSI_VC_OCP_WIDTH, + FEAT_DSI_GNQ, + FEAT_HDMI_CTS_SWMODE, + FEAT_HDMI_AUDIO_USE_MCLK, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + FEAT_BURST_2D, +}; + /* OMAP2 DSS Features */ static const struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, @@ -570,6 +641,26 @@ static const struct omap_dss_features omap4_dss_features = { .burst_size_unit = 16, }; +/* OMAP5 DSS Features */ +static const struct omap_dss_features omap5_dss_features = { + .reg_fields = omap5_dss_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields), + + .features = omap5_dss_feat_list, + .num_features = ARRAY_SIZE(omap5_dss_feat_list), + + .num_mgrs = 3, + .num_ovls = 4, + .supported_displays = omap5_dss_supported_displays, + .supported_color_modes = omap4_dss_supported_color_modes, + .overlay_caps = omap4_dss_overlay_caps, + .clksrc_names = omap5_dss_clk_source_names, + .dss_params = omap5_dss_param_range, + .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, + .buffer_size_unit = 16, + .burst_size_unit = 16, +}; + #if defined(CONFIG_OMAP4_DSS_HDMI) /* HDMI OMAP4 Functions*/ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { @@ -707,6 +798,8 @@ void dss_features_init(void) omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; else if (cpu_is_omap44xx()) omap_current_dss_features = &omap4_dss_features; + else if (soc_is_omap54xx()) + omap_current_dss_features = &omap5_dss_features; else DSSWARN("Unsupported OMAP version"); } From 84273a9593306926af56ad5b4a69029c2886c5de Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 21 Sep 2012 12:03:31 +0300 Subject: [PATCH 3/9] OMAPDSS: move dss feats to the end of dss.c Move dss_features to the end of dss.c the same way they are in dispc.c, so that we don't have to declare prototypes for static feat-related functions. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 60 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 4524c174ac5..660813b0119 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -99,36 +99,6 @@ static const char * const dss_generic_clk_source_names[] = { [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", }; -static const struct dss_features omap24xx_dss_feats __initconst = { - .fck_div_max = 16, - .dss_fck_multiplier = 2, - .clk_name = NULL, -}; - -static const struct dss_features omap34xx_dss_feats __initconst = { - .fck_div_max = 16, - .dss_fck_multiplier = 2, - .clk_name = "dpll4_m4_ck", -}; - -static const struct dss_features omap3630_dss_feats __initconst = { - .fck_div_max = 32, - .dss_fck_multiplier = 1, - .clk_name = "dpll4_m4_ck", -}; - -static const struct dss_features omap44xx_dss_feats __initconst = { - .fck_div_max = 32, - .dss_fck_multiplier = 1, - .clk_name = "dpll_per_m5x2_ck", -}; - -static const struct dss_features omap54xx_dss_feats __initconst = { - .fck_div_max = 64, - .dss_fck_multiplier = 1, - .clk_name = "dpll_per_h12x2_ck", -}; - static inline void dss_write_reg(const struct dss_reg idx, u32 val) { __raw_writel(val, dss.base + idx.idx); @@ -727,6 +697,36 @@ void dss_debug_dump_clocks(struct seq_file *s) } #endif +static const struct dss_features omap24xx_dss_feats __initconst = { + .fck_div_max = 16, + .dss_fck_multiplier = 2, + .clk_name = NULL, +}; + +static const struct dss_features omap34xx_dss_feats __initconst = { + .fck_div_max = 16, + .dss_fck_multiplier = 2, + .clk_name = "dpll4_m4_ck", +}; + +static const struct dss_features omap3630_dss_feats __initconst = { + .fck_div_max = 32, + .dss_fck_multiplier = 1, + .clk_name = "dpll4_m4_ck", +}; + +static const struct dss_features omap44xx_dss_feats __initconst = { + .fck_div_max = 32, + .dss_fck_multiplier = 1, + .clk_name = "dpll_per_m5x2_ck", +}; + +static const struct dss_features omap54xx_dss_feats __initconst = { + .fck_div_max = 64, + .dss_fck_multiplier = 1, + .clk_name = "dpll_per_h12x2_ck", +}; + static int __init dss_init_features(struct device *dev) { const struct dss_features *src; From de09e4555592986219132b518c3f7834a28823cd Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 21 Sep 2012 12:09:54 +0300 Subject: [PATCH 4/9] OMAPDSS: Add support for DPI source selection We can select the video source for DPI output as follows: OMAP2/3: always LCD1 OMAP4: LCD2 or DIGIT OMAP5: LCD1/LCD2/LCD3/DIGIT This patch adds support to select the source, and makes dpi.c call the function to set the source. Signed-off-by: Tomi Valkeinen Cc: David Anders --- drivers/video/omap2/dss/dpi.c | 5 +++ drivers/video/omap2/dss/dss.c | 65 +++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss.h | 1 + 3 files changed, 71 insertions(+) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 5ccce9b69e4..b7233882fcf 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -203,6 +203,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) if (r) goto err_get_dispc; + r = dss_dpi_select_source(dssdev->channel); + if (r) + goto err_src_sel; + if (dpi_use_dsi_pll(dssdev)) { r = dsi_runtime_get(dpi.dsidev); if (r) @@ -237,6 +241,7 @@ err_dsi_pll_init: if (dpi_use_dsi_pll(dssdev)) dsi_runtime_put(dpi.dsidev); err_get_dsi: +err_src_sel: dispc_runtime_put(); err_get_dispc: if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 660813b0119..2ab1c3e9655 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -69,6 +69,7 @@ struct dss_features { u8 fck_div_max; u8 dss_fck_multiplier; const char *clk_name; + int (*dpi_select_source)(enum omap_channel channel); }; static struct { @@ -623,6 +624,65 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) return REG_GET(DSS_CONTROL, 15, 15); } +static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) +{ + if (channel != OMAP_DSS_CHANNEL_LCD) + return -EINVAL; + + return 0; +} + +static int dss_dpi_select_source_omap4(enum omap_channel channel) +{ + int val; + + switch (channel) { + case OMAP_DSS_CHANNEL_LCD2: + val = 0; + break; + case OMAP_DSS_CHANNEL_DIGIT: + val = 1; + break; + default: + return -EINVAL; + } + + REG_FLD_MOD(DSS_CONTROL, val, 17, 17); + + return 0; +} + +static int dss_dpi_select_source_omap5(enum omap_channel channel) +{ + int val; + + switch (channel) { + case OMAP_DSS_CHANNEL_LCD: + val = 1; + break; + case OMAP_DSS_CHANNEL_LCD2: + val = 2; + break; + case OMAP_DSS_CHANNEL_LCD3: + val = 3; + break; + case OMAP_DSS_CHANNEL_DIGIT: + val = 0; + break; + default: + return -EINVAL; + } + + REG_FLD_MOD(DSS_CONTROL, val, 17, 16); + + return 0; +} + +int dss_dpi_select_source(enum omap_channel channel) +{ + return dss.feat->dpi_select_source(channel); +} + static int dss_get_clocks(void) { struct clk *clk; @@ -701,30 +761,35 @@ static const struct dss_features omap24xx_dss_feats __initconst = { .fck_div_max = 16, .dss_fck_multiplier = 2, .clk_name = NULL, + .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap34xx_dss_feats __initconst = { .fck_div_max = 16, .dss_fck_multiplier = 2, .clk_name = "dpll4_m4_ck", + .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap3630_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, .clk_name = "dpll4_m4_ck", + .dpi_select_source = &dss_dpi_select_source_omap2_omap3, }; static const struct dss_features omap44xx_dss_feats __initconst = { .fck_div_max = 32, .dss_fck_multiplier = 1, .clk_name = "dpll_per_m5x2_ck", + .dpi_select_source = &dss_dpi_select_source_omap4, }; static const struct dss_features omap54xx_dss_feats __initconst = { .fck_div_max = 64, .dss_fck_multiplier = 1, .clk_name = "dpll_per_h12x2_ck", + .dpi_select_source = &dss_dpi_select_source_omap5, }; static int __init dss_init_features(struct device *dev) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 5e9fd769172..2a51ae99474 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -277,6 +277,7 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl); int dss_init_platform_driver(void) __init; void dss_uninit_platform_driver(void); +int dss_dpi_select_source(enum omap_channel channel); void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); From f8ef3d696651df01029d289f1e15c02d4f566610 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 22 Aug 2012 16:00:31 +0300 Subject: [PATCH 5/9] OMAPDSS: DSI: Add FEAT_DSI_PLL_SELFREQDCO Add FEAT_DSI_PLL_SELFREQDCO. OMAP5's DSI PLL has a new configuration option that needs to be programmed depending on the PLL's output clock frequency. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 12 ++++++++---- drivers/video/omap2/dss/dss_features.c | 1 + drivers/video/omap2/dss/dss_features.h | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 8d47fb7c4b8..0c3afc2b469 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1671,18 +1671,22 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); + l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); + if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { f = cinfo->fint < 1000000 ? 0x3 : cinfo->fint < 1250000 ? 0x4 : cinfo->fint < 1500000 ? 0x5 : cinfo->fint < 1750000 ? 0x6 : 0x7; + + l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ + } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) { + f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4; + + l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */ } - l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); - - if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) - l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index af4775a2070..177f6e8d2d7 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -519,6 +519,7 @@ static const enum dss_feat_id omap5_dss_feat_list[] = { FEAT_ALPHA_FREE_ZORDER, FEAT_FIFO_MERGE, FEAT_BURST_2D, + FEAT_DSI_PLL_SELFREQDCO, }; /* OMAP2 DSS Features */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b81d603310a..f9b9d28ed31 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -65,6 +65,7 @@ enum dss_feat_id { /* An unknown HW bug causing the normal FIFO thresholds not to work */ FEAT_OMAP3_DSI_FIFO_BUG, FEAT_BURST_2D, + FEAT_DSI_PLL_SELFREQDCO, }; /* DSS register field id */ From 6d44610f8321a9aa3bc408026f888872b1390712 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 22 Aug 2012 16:00:40 +0300 Subject: [PATCH 6/9] OMAPDSS: DSI: Add FEAT_DSI_PLL_REFSEL Add FEAT_DSI_PLL_REFSEL. OMAP5's DSI PLL needs configuration to select the reference clock to be used. We always use SYSCLK. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 2 ++ drivers/video/omap2/dss/dss_features.c | 1 + drivers/video/omap2/dss/dss_features.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0c3afc2b469..a16c8b229ea 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1690,6 +1690,8 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ + if (dss_has_feature(FEAT_DSI_PLL_REFSEL)) + l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */ dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 177f6e8d2d7..46855316d21 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -520,6 +520,7 @@ static const enum dss_feat_id omap5_dss_feat_list[] = { FEAT_FIFO_MERGE, FEAT_BURST_2D, FEAT_DSI_PLL_SELFREQDCO, + FEAT_DSI_PLL_REFSEL, }; /* OMAP2 DSS Features */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index f9b9d28ed31..0020bf66f3f 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -66,6 +66,7 @@ enum dss_feat_id { FEAT_OMAP3_DSI_FIFO_BUG, FEAT_BURST_2D, FEAT_DSI_PLL_SELFREQDCO, + FEAT_DSI_PLL_REFSEL, }; /* DSS register field id */ From 2ac80fbea1018404560294797da86d5e72a807f4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 22 Aug 2012 16:00:47 +0300 Subject: [PATCH 7/9] OMAPDSS: DSI: Add new linebuffer size for OMAP5 OMAP5's DSI has a larger line buffer than earlier OMAPs. This patch adds support for this to the DSI driver. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index a16c8b229ea..0dc24f2689c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2155,6 +2155,8 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) return 1194 * 3; /* 1194x24 bits */ case 6: return 1365 * 3; /* 1365x24 bits */ + case 7: + return 1920 * 3; /* 1920x24 bits */ default: BUG(); return 0; From 77ccbfbb07764841500addb570ad61b9868a964d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 24 Sep 2012 15:15:57 +0300 Subject: [PATCH 8/9] OMAPDSS: DSI: Add code to disable PHY DCC OMAP5 DSI PHY has DCC (Duty Cycle Corrector) block, and by default DCC is enabled and thus the PLL clock is divided by 2 to get the DSI DDR clk. This divider has been 4 for all previous OMAPs, and changing it needs some reorganization of the code. The DCC can be disabled, and in that case the divider is back to the old 4. This patch adds dss feature for the DCC, and adds code to always disable the DCC. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 7 +++++++ drivers/video/omap2/dss/dss_features.c | 1 + drivers/video/omap2/dss/dss_features.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0dc24f2689c..497b219e370 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2292,6 +2292,13 @@ static void dsi_cio_timings(struct platform_device *dsidev) r = FLD_MOD(r, tlpx_half, 22, 16); r = FLD_MOD(r, tclk_trail, 15, 8); r = FLD_MOD(r, tclk_zero, 7, 0); + + if (dss_has_feature(FEAT_DSI_PHY_DCC)) { + r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */ + r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */ + r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */ + } + dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 46855316d21..e650a4a6d00 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -521,6 +521,7 @@ static const enum dss_feat_id omap5_dss_feat_list[] = { FEAT_BURST_2D, FEAT_DSI_PLL_SELFREQDCO, FEAT_DSI_PLL_REFSEL, + FEAT_DSI_PHY_DCC, }; /* OMAP2 DSS Features */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 0020bf66f3f..aacad863fa2 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -67,6 +67,7 @@ enum dss_feat_id { FEAT_BURST_2D, FEAT_DSI_PLL_SELFREQDCO, FEAT_DSI_PLL_REFSEL, + FEAT_DSI_PHY_DCC, }; /* DSS register field id */ From 995885897ff0ef3dad12fcfbfd0c26e185bf4ac0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 22 Aug 2012 15:55:21 +0300 Subject: [PATCH 9/9] OMAPDSS: DSI: make OMAP2_DSS_DSI depend on ARCH_OMAP5 Change omapdss Kconfig file to make OMAP2_DSS_DSI depend on ARCH_OMAP5. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index b337a8469fd..80f5390aa13 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -84,7 +84,7 @@ config OMAP2_DSS_SDI config OMAP2_DSS_DSI bool "DSI support" - depends on ARCH_OMAP3 || ARCH_OMAP4 + depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5 default n help MIPI DSI (Display Serial Interface) support.