The DSI PLL parameters (regm, regn, regm_dispc, regm_dsi, fint) have different fields and also different Max values on OMAP3 and OMAP4. Use dss features to calculate the register fields and Max values based on current OMAP revision Also, introduce a new function in dss_features "dss_feat_get_param_range" which returns the maximum and minimum values supported by the parameter for the current OMAP revision. Signed-off-by: Archit Taneja <archit@xxxxxx> --- Note: Applies over: http://gitorious.org/linux-omap-dss2/linux/commits/master and the patch submitted on l-o: OMAP4: DSS2: Clock source changes for OMAP4 drivers/video/omap2/dss/dsi.c | 75 +++++++++++++++++++++++--------- drivers/video/omap2/dss/dss_features.c | 40 +++++++++++++++++ drivers/video/omap2/dss/dss_features.h | 9 ++++ 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index be7694f..e7d6169 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -185,13 +185,8 @@ struct dsi_reg { u16 idx; }; #define DSI_DT_RX_SHORT_READ_1 0x21 #define DSI_DT_RX_SHORT_READ_2 0x22 -#define FINT_MAX 2100000 -#define FINT_MIN 750000 -#define REGN_MAX (1 << 7) -#define REGM_MAX ((1 << 11) - 1) -#define REGM_DISPC_MAX (1 << 4) -#define REGM_DSI_MAX (1 << 4) #define LP_DIV_MAX ((1 << 13) - 1) +#define DSI_PARAM_MAX(start, end) ((1 << (start - end + 1)) - 1) enum fifo_size { DSI_FIFO_SIZE_0 = 0, @@ -277,6 +272,10 @@ static struct spinlock_t irq_stats_lock; struct dsi_irq_stats irq_stats; #endif + /* DSI PLL Parameter Ranges */ + int regm_max, regn_max; + int regm_dispc_max, regm_dsi_max; + int fint_min, fint_max; } dsi; #ifdef DEBUG @@ -801,16 +800,16 @@ static int dsi_pll_power(enum dsi_pll_power_state state) static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, struct dsi_clock_info *cinfo) { - if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) + if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) return -EINVAL; - if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) + if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) return -EINVAL; - if (cinfo->regm_dispc > REGM_DISPC_MAX) + if (cinfo->regm_dispc > dsi.regm_dispc_max) return -EINVAL; - if (cinfo->regm_dsi > REGM_DSI_MAX) + if (cinfo->regm_dsi > dsi.regm_dsi_max) return -EINVAL; if (cinfo->use_sys_clk) { @@ -829,7 +828,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); - if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) + if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) return -EINVAL; cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; @@ -899,17 +898,17 @@ retry: /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ - for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { + for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { if (cur.highfreq == 0) cur.fint = cur.clkin / cur.regn; else cur.fint = cur.clkin / (2 * cur.regn); - if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) + if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) continue; /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ - for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { + for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { unsigned long a, b; a = 2 * cur.regm * (cur.clkin/1000); @@ -921,8 +920,8 @@ retry: /* dsi_pll_hsdiv_dispc_clk(MHz) = * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ - for (cur.regm_dispc = 1; cur.regm_dispc < REGM_DISPC_MAX; - ++cur.regm_dispc) { + for (cur.regm_dispc = 1; cur.regm_dispc < + dsi.regm_dispc_max; ++cur.regm_dispc) { struct dispc_clock_info cur_dispc; cur.dsi_pll_hsdiv_dispc_clk = cur.clkin4ddr / cur.regm_dispc; @@ -994,6 +993,8 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) int r = 0; u32 l; int f; + u8 regn_start, regn_end, regm_start, regm_end; + u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; DSSDBGF(); @@ -1038,19 +1039,30 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), cinfo->dsi_pll_hsdiv_dsi_clk); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, + ®m_dispc_end); + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, + ®m_dsi_end); + REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ l = dsi_read_reg(DSI_PLL_CONFIGURATION1); l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ - l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ - l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ + /* DSI_PLL_REGN */ + l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); + /* DSI_PLL_REGM */ + l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); + /* DSI_CLOCK_DIV */ l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, - 22, 19); /* DSI_CLOCK_DIV */ + regm_dispc_start, regm_dispc_end); + /* DSIPROTO_CLOCK_DIV */ l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, - 26, 23); /* DSIPROTO_CLOCK_DIV */ + regm_dsi_start, regm_dsi_end); dsi_write_reg(DSI_PLL_CONFIGURATION1, l); - BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); + BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); if (cinfo->fint < 1000000) f = 0x3; else if (cinfo->fint < 1250000) @@ -3333,6 +3345,25 @@ void dsi_wait_pll_hsdiv_dsi_active(void) dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); } +static void dsi_calc_clock_param_ranges(void) +{ + u8 start, end; + + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &start, &end); + dsi.regm_max = DSI_PARAM_MAX(start, end); + + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &start, &end); + dsi.regn_max = DSI_PARAM_MAX(start, end); + + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &start, &end); + dsi.regm_dispc_max = DSI_PARAM_MAX(start, end); + + dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &start, &end); + dsi.regm_dsi_max = DSI_PARAM_MAX(start, end); + + dss_feat_get_param_range(FEAT_DSI_FINT, &dsi.fint_min, &dsi.fint_max); +} + static int dsi_init(struct platform_device *pdev) { u32 rev; @@ -3397,6 +3428,8 @@ static int dsi_init(struct platform_device *pdev) dsi.vc[i].vc_id = 0; } + dsi_calc_clock_param_ranges(); + enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 6eb6ec6..d458da0 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -34,6 +34,11 @@ struct dss_reg_field { u8 start, end; }; +struct dss_param_range { + enum dss_range_param param; + int min, max; +}; + struct omap_dss_features { const struct dss_reg_field *reg_fields; const int num_reg_fields; @@ -46,6 +51,7 @@ struct omap_dss_features { const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; const struct dss_clk_source_name *clksrc_names; + const struct dss_param_range *dss_params; }; /* This struct is assigned to one of the below during initialization */ @@ -60,6 +66,10 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = { { FEAT_REG_HORIZONTALACCU, 9, 0 }, { FEAT_REG_VERTICALACCU, 25, 16 }, { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, + { FEAT_REG_DSIPLL_REGM, 0, 0 }, + { FEAT_REG_DSIPLL_REGN, 0, 0 }, + { FEAT_REG_DSIPLL_REGM_DISPC, 0, 0 }, + { FEAT_REG_DSIPLL_REGM_DSI, 0, 0 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { @@ -71,6 +81,10 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = { { FEAT_REG_HORIZONTALACCU, 9, 0 }, { FEAT_REG_VERTICALACCU, 25, 16 }, { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, + { FEAT_REG_DSIPLL_REGM, 18, 8 }, + { FEAT_REG_DSIPLL_REGN, 7, 1 }, + { FEAT_REG_DSIPLL_REGM_DISPC, 22, 19 }, + { FEAT_REG_DSIPLL_REGM_DSI, 26, 23 }, }; static const struct dss_reg_field omap4_dss_reg_fields[] = { @@ -82,6 +96,10 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = { { FEAT_REG_HORIZONTALACCU, 10, 0 }, { FEAT_REG_VERTICALACCU, 26, 16 }, { FEAT_REG_DISPC_CLK_SWITCH, 9, 8 }, + { FEAT_REG_DSIPLL_REGM, 20, 9 }, + { FEAT_REG_DSIPLL_REGN, 8, 1 }, + { FEAT_REG_DSIPLL_REGM_DISPC, 25, 21 }, + { FEAT_REG_DSIPLL_REGM_DSI, 30, 26 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -180,6 +198,18 @@ static const struct dss_clk_source_name omap4_dss_clk_source_names[] = { { DSS_CLK_SRC_FCK, "DSS_FCLK" }, }; +static const struct dss_param_range omap2_dss_param_range[] = { + { FEAT_DSI_FINT, 0, 0 }, +}; + +static const struct dss_param_range omap3_dss_param_range[] = { + { FEAT_DSI_FINT, 750000, 2100000 }, +}; + +static const struct dss_param_range omap4_dss_param_range[] = { + { FEAT_DSI_FINT, 500000, 2500000 }, +}; + /* OMAP2 DSS Features */ static struct omap_dss_features omap2_dss_features = { .reg_fields = omap2_dss_reg_fields, @@ -196,6 +226,7 @@ static struct omap_dss_features omap2_dss_features = { .supported_displays = omap2_dss_supported_displays, .supported_color_modes = omap2_dss_supported_color_modes, .clksrc_names = omap2_dss_clk_source_names, + .dss_params = omap2_dss_param_range, }; /* OMAP3 DSS Features */ @@ -215,6 +246,7 @@ static struct omap_dss_features omap3430_dss_features = { .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, + .dss_params = omap3_dss_param_range, }; static struct omap_dss_features omap3630_dss_features = { @@ -234,6 +266,7 @@ static struct omap_dss_features omap3630_dss_features = { .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, + .dss_params = omap3_dss_param_range, }; /* OMAP4 DSS Features */ @@ -252,6 +285,7 @@ static struct omap_dss_features omap4_dss_features = { .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap4_dss_clk_source_names, + .dss_params = omap4_dss_param_range, }; /* Functions returning values related to a DSS feature */ @@ -293,6 +327,12 @@ const char *dss_feat_get_clk_source_name(enum dss_clk_source id) return omap_current_dss_features->clksrc_names[id].clksrc_name; } +void dss_feat_get_param_range(enum dss_range_param param, int *min, int *max) +{ + *min = omap_current_dss_features->dss_params[param].min; + *max = omap_current_dss_features->dss_params[param].max; +} + /* DSS has_feature check */ bool dss_has_feature(enum dss_feat_id id) { diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 3302247..78b51a9 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -52,6 +52,14 @@ enum dss_feat_reg_field { FEAT_REG_HORIZONTALACCU, FEAT_REG_VERTICALACCU, FEAT_REG_DISPC_CLK_SWITCH, + FEAT_REG_DSIPLL_REGM, + FEAT_REG_DSIPLL_REGN, + FEAT_REG_DSIPLL_REGM_DISPC, + FEAT_REG_DSIPLL_REGM_DSI, +}; + +enum dss_range_param { + FEAT_DSI_FINT, }; /* DSS Feature Functions */ @@ -63,6 +71,7 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, enum omap_color_mode color_mode); const char *dss_feat_get_clk_source_name(enum dss_clk_source id); +void dss_feat_get_param_range(enum dss_range_param param, int *min, int *max); bool dss_has_feature(enum dss_feat_id id); void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html