powerpc/5121: fsl-diu-fb: fix issue with re-enabling DIU area descriptor

On MPC5121e Rev 2.0 re-configuring the DIU area descriptor
by writing new descriptor address doesn't always work.
As a result, DIU continues to display using old area descriptor
even if the new one has been written to the descriptor register of
the plane.

Add the code from Freescale MPC5121EADS BSP for writing descriptor
addresses properly. This fixes the problem for Rev 2.0 silicon.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
Anatolij Gustschin 2010-07-23 04:00:35 +00:00 committed by Grant Likely
parent 9e2089cbed
commit 0d9dab39fb

View File

@ -317,6 +317,17 @@ static void fsl_diu_free(void *virt, size_t size)
free_pages_exact(virt, size); free_pages_exact(virt, size);
} }
/*
* Workaround for failed writing desc register of planes.
* Needed with MPC5121 DIU rev 2.0 silicon.
*/
void wr_reg_wa(u32 *reg, u32 val)
{
do {
out_be32(reg, val);
} while (in_be32(reg) != val);
}
static int fsl_diu_enable_panel(struct fb_info *info) static int fsl_diu_enable_panel(struct fb_info *info)
{ {
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
@ -330,7 +341,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
switch (mfbi->index) { switch (mfbi->index) {
case 0: /* plane 0 */ case 0: /* plane 0 */
if (hw->desc[0] != ad->paddr) if (hw->desc[0] != ad->paddr)
out_be32(&hw->desc[0], ad->paddr); wr_reg_wa(&hw->desc[0], ad->paddr);
break; break;
case 1: /* plane 1 AOI 0 */ case 1: /* plane 1 AOI 0 */
cmfbi = machine_data->fsl_diu_info[2]->par; cmfbi = machine_data->fsl_diu_info[2]->par;
@ -340,7 +351,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
cpu_to_le32(cmfbi->ad->paddr); cpu_to_le32(cmfbi->ad->paddr);
else else
ad->next_ad = 0; ad->next_ad = 0;
out_be32(&hw->desc[1], ad->paddr); wr_reg_wa(&hw->desc[1], ad->paddr);
} }
break; break;
case 3: /* plane 2 AOI 0 */ case 3: /* plane 2 AOI 0 */
@ -351,14 +362,14 @@ static int fsl_diu_enable_panel(struct fb_info *info)
cpu_to_le32(cmfbi->ad->paddr); cpu_to_le32(cmfbi->ad->paddr);
else else
ad->next_ad = 0; ad->next_ad = 0;
out_be32(&hw->desc[2], ad->paddr); wr_reg_wa(&hw->desc[2], ad->paddr);
} }
break; break;
case 2: /* plane 1 AOI 1 */ case 2: /* plane 1 AOI 1 */
pmfbi = machine_data->fsl_diu_info[1]->par; pmfbi = machine_data->fsl_diu_info[1]->par;
ad->next_ad = 0; ad->next_ad = 0;
if (hw->desc[1] == machine_data->dummy_ad->paddr) if (hw->desc[1] == machine_data->dummy_ad->paddr)
out_be32(&hw->desc[1], ad->paddr); wr_reg_wa(&hw->desc[1], ad->paddr);
else /* AOI0 open */ else /* AOI0 open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
break; break;
@ -366,7 +377,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
pmfbi = machine_data->fsl_diu_info[3]->par; pmfbi = machine_data->fsl_diu_info[3]->par;
ad->next_ad = 0; ad->next_ad = 0;
if (hw->desc[2] == machine_data->dummy_ad->paddr) if (hw->desc[2] == machine_data->dummy_ad->paddr)
out_be32(&hw->desc[2], ad->paddr); wr_reg_wa(&hw->desc[2], ad->paddr);
else /* AOI0 was open */ else /* AOI0 was open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
break; break;
@ -390,27 +401,24 @@ static int fsl_diu_disable_panel(struct fb_info *info)
switch (mfbi->index) { switch (mfbi->index) {
case 0: /* plane 0 */ case 0: /* plane 0 */
if (hw->desc[0] != machine_data->dummy_ad->paddr) if (hw->desc[0] != machine_data->dummy_ad->paddr)
out_be32(&hw->desc[0], wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
machine_data->dummy_ad->paddr);
break; break;
case 1: /* plane 1 AOI 0 */ case 1: /* plane 1 AOI 0 */
cmfbi = machine_data->fsl_diu_info[2]->par; cmfbi = machine_data->fsl_diu_info[2]->par;
if (cmfbi->count > 0) /* AOI1 is open */ if (cmfbi->count > 0) /* AOI1 is open */
out_be32(&hw->desc[1], cmfbi->ad->paddr); wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
/* move AOI1 to the first */ /* move AOI1 to the first */
else /* AOI1 was closed */ else /* AOI1 was closed */
out_be32(&hw->desc[1], wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
machine_data->dummy_ad->paddr);
/* close AOI 0 */ /* close AOI 0 */
break; break;
case 3: /* plane 2 AOI 0 */ case 3: /* plane 2 AOI 0 */
cmfbi = machine_data->fsl_diu_info[4]->par; cmfbi = machine_data->fsl_diu_info[4]->par;
if (cmfbi->count > 0) /* AOI1 is open */ if (cmfbi->count > 0) /* AOI1 is open */
out_be32(&hw->desc[2], cmfbi->ad->paddr); wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
/* move AOI1 to the first */ /* move AOI1 to the first */
else /* AOI1 was closed */ else /* AOI1 was closed */
out_be32(&hw->desc[2], wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
machine_data->dummy_ad->paddr);
/* close AOI 0 */ /* close AOI 0 */
break; break;
case 2: /* plane 1 AOI 1 */ case 2: /* plane 1 AOI 1 */
@ -421,7 +429,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
/* AOI0 is open, must be the first */ /* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0; pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */ } else /* AOI1 is the first in the chain */
out_be32(&hw->desc[1], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
/* close AOI 1 */ /* close AOI 1 */
break; break;
case 4: /* plane 2 AOI 1 */ case 4: /* plane 2 AOI 1 */
@ -432,7 +440,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
/* AOI0 is open, must be the first */ /* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0; pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */ } else /* AOI1 is the first in the chain */
out_be32(&hw->desc[2], machine_data->dummy_ad->paddr); wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
/* close AOI 1 */ /* close AOI 1 */
break; break;
default: default: