[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