[PATCH v4 1/5] fsl-diu-fb: fix issue with re-enabling DIU area descriptor
Grant Likely
grant.likely at secretlab.ca
Wed Jul 28 17:02:59 EST 2010
On Fri, Jul 23, 2010 at 8:00 AM, Anatolij Gustschin <agust at denx.de> wrote:
> 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 at denx.de>
> ---
> v4:
> - use workaround code as suggested by FSL technical support.
>
> v3:
> - no changes since v1
>
> drivers/video/fsl-diu-fb.c | 38 +++++++++++++++++++++++---------------
> 1 files changed, 23 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index 27455ce..9b8c991 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -317,6 +317,17 @@ static void fsl_diu_free(void *virt, size_t 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);
> +}
I'll apply this one, but it looks like a potential problem. What
happens if the write never succeeds? The kernel then gets stuck in a
forever busy loop. You should look at reworking it.
g.
> +
> static int fsl_diu_enable_panel(struct fb_info *info)
> {
> 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) {
> case 0: /* plane 0 */
> if (hw->desc[0] != ad->paddr)
> - out_be32(&hw->desc[0], ad->paddr);
> + wr_reg_wa(&hw->desc[0], ad->paddr);
> break;
> case 1: /* plane 1 AOI 0 */
> 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);
> else
> ad->next_ad = 0;
> - out_be32(&hw->desc[1], ad->paddr);
> + wr_reg_wa(&hw->desc[1], ad->paddr);
> }
> break;
> 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);
> else
> ad->next_ad = 0;
> - out_be32(&hw->desc[2], ad->paddr);
> + wr_reg_wa(&hw->desc[2], ad->paddr);
> }
> break;
> case 2: /* plane 1 AOI 1 */
> pmfbi = machine_data->fsl_diu_info[1]->par;
> ad->next_ad = 0;
> 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 */
> pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
> break;
> @@ -366,7 +377,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
> pmfbi = machine_data->fsl_diu_info[3]->par;
> ad->next_ad = 0;
> 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 */
> pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
> break;
> @@ -390,27 +401,24 @@ static int fsl_diu_disable_panel(struct fb_info *info)
> switch (mfbi->index) {
> case 0: /* plane 0 */
> if (hw->desc[0] != machine_data->dummy_ad->paddr)
> - out_be32(&hw->desc[0],
> - machine_data->dummy_ad->paddr);
> + wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
> break;
> case 1: /* plane 1 AOI 0 */
> cmfbi = machine_data->fsl_diu_info[2]->par;
> 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 */
> else /* AOI1 was closed */
> - out_be32(&hw->desc[1],
> - machine_data->dummy_ad->paddr);
> + wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
> /* close AOI 0 */
> break;
> case 3: /* plane 2 AOI 0 */
> cmfbi = machine_data->fsl_diu_info[4]->par;
> 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 */
> else /* AOI1 was closed */
> - out_be32(&hw->desc[2],
> - machine_data->dummy_ad->paddr);
> + wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
> /* close AOI 0 */
> break;
> 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 */
> pmfbi->ad->next_ad = 0;
> } 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 */
> break;
> 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 */
> pmfbi->ad->next_ad = 0;
> } 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 */
> break;
> default:
> --
> 1.7.0.4
>
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
More information about the devicetree-discuss
mailing list