Commit 9eaaf207 authored by Tomi Valkeinen's avatar Tomi Valkeinen

OMAP: DSS2: DISPC: Fix minimum PCD value

The current driver had a hardcoded minimum value of 2 for pixel clock
divisor (PCD). This doesn't seem to be right.

OMAP4 TRM says that PCD can be 1 when not downscaling, and inverted
pixel clock (IPC) is off.

OMAP3 TRM says the same, but also in the register descriptions that PCD
value 1 is invalid.

OMAP2 TRM says PCD 2 is the minimum.

OMAP2 is still untested, but for both OMAP3 and OMAP4 PCD of 1 seems to
work fine.

This patch adds a new DSS feature, FEAT_PARAM_DSS_PCD, which is used to
find the minimum and maximum PCD. The minimum is set to 2 for OMAP2, and
1 for OMAP3/4.
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent d875f992
...@@ -2334,7 +2334,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, ...@@ -2334,7 +2334,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
u16 pck_div) u16 pck_div)
{ {
BUG_ON(lck_div < 1); BUG_ON(lck_div < 1);
BUG_ON(pck_div < 2); BUG_ON(pck_div < 1);
dispc_write_reg(DISPC_DIVISORo(channel), dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
...@@ -2721,11 +2721,17 @@ void dispc_mgr_set_pol_freq(enum omap_channel channel, ...@@ -2721,11 +2721,17 @@ void dispc_mgr_set_pol_freq(enum omap_channel channel,
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
struct dispc_clock_info *cinfo) struct dispc_clock_info *cinfo)
{ {
u16 pcd_min = is_tft ? 2 : 3; u16 pcd_min, pcd_max;
unsigned long best_pck; unsigned long best_pck;
u16 best_ld, cur_ld; u16 best_ld, cur_ld;
u16 best_pd, cur_pd; u16 best_pd, cur_pd;
pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
if (!is_tft)
pcd_min = 3;
best_pck = 0; best_pck = 0;
best_ld = 0; best_ld = 0;
best_pd = 0; best_pd = 0;
...@@ -2733,7 +2739,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, ...@@ -2733,7 +2739,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
unsigned long lck = fck / cur_ld; unsigned long lck = fck / cur_ld;
for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
unsigned long pck = lck / cur_pd; unsigned long pck = lck / cur_pd;
long old_delta = abs(best_pck - req_pck); long old_delta = abs(best_pck - req_pck);
long new_delta = abs(pck - req_pck); long new_delta = abs(pck - req_pck);
...@@ -2768,7 +2774,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, ...@@ -2768,7 +2774,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
{ {
if (cinfo->lck_div > 255 || cinfo->lck_div == 0) if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
return -EINVAL; return -EINVAL;
if (cinfo->pck_div < 2 || cinfo->pck_div > 255) if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
return -EINVAL; return -EINVAL;
cinfo->lck = dispc_fclk_rate / cinfo->lck_div; cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
......
...@@ -281,6 +281,7 @@ static const char * const omap4_dss_clk_source_names[] = { ...@@ -281,6 +281,7 @@ static const char * const omap4_dss_clk_source_names[] = {
static const struct dss_param_range omap2_dss_param_range[] = { static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
...@@ -291,6 +292,7 @@ static const struct dss_param_range omap2_dss_param_range[] = { ...@@ -291,6 +292,7 @@ static const struct dss_param_range omap2_dss_param_range[] = {
static const struct dss_param_range omap3_dss_param_range[] = { static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
...@@ -301,6 +303,7 @@ static const struct dss_param_range omap3_dss_param_range[] = { ...@@ -301,6 +303,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
static const struct dss_param_range omap4_dss_param_range[] = { static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
......
...@@ -77,6 +77,7 @@ enum dss_feat_reg_field { ...@@ -77,6 +77,7 @@ enum dss_feat_reg_field {
enum dss_range_param { enum dss_range_param {
FEAT_PARAM_DSS_FCK, FEAT_PARAM_DSS_FCK,
FEAT_PARAM_DSS_PCD,
FEAT_PARAM_DSIPLL_REGN, FEAT_PARAM_DSIPLL_REGN,
FEAT_PARAM_DSIPLL_REGM, FEAT_PARAM_DSIPLL_REGM,
FEAT_PARAM_DSIPLL_REGM_DISPC, FEAT_PARAM_DSIPLL_REGM_DISPC,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment