On 30.05.2016 18:00, Ulrich Hecht wrote:
> From: Koji Matsuoka <koji.matsuoka.xm at renesas.com>
>
> Signed-off-by: Koji Matsuoka <koji.matsuoka.xm at renesas.com>
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
>   drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 97 
> ++++++++++++++++++++++++++++++++-
>   drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  8 +++
>   drivers/gpu/drm/rcar-du/rcar_du_drv.c   |  1 +
>   drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  1 +
>   drivers/gpu/drm/rcar-du/rcar_du_plane.h |  7 ++-
>   drivers/gpu/drm/rcar-du/rcar_du_regs.h  | 19 +++++++
>   6 files changed, 131 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 
> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 0d8bdda..e10943b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -30,6 +30,12 @@
>   #include "rcar_du_regs.h"
>   #include "rcar_du_vsp.h"
>
> +#define PRODUCT_REG  0xfff00044
> +#define PRODUCT_H3_BIT       (0x4f << 8)
> +#define PRODUCT_MASK (0x7f << 8)
> +#define CUT_ES1              (0x00)
> +#define CUT_ES1_MASK (0x000000ff)


NACK for the hard coded register.

We've already discussed this in the thread

https://www.mail-archive.com/linux-renesas-soc at vger.kernel.org/msg04008.html

and found that this isn't ready this way:

https://www.mail-archive.com/linux-renesas-soc at vger.kernel.org/msg04079.html

Best regards

Dirk



>   static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
>   {
>       struct rcar_du_device *rcdu = rcrtc->group->dev;
> @@ -106,14 +112,74 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
>    * Hardware Setup
>    */
>
> +static void rcar_du_dpll_divider(struct dpll_info *dpll, unsigned int extclk,
> +                              unsigned int mode_clock)
> +{
> +     unsigned long dpllclk;
> +     unsigned long diff;
> +     unsigned long n, m, fdpll;
> +     bool match_flag = false;
> +     bool clk_diff_set = true;
> +
> +     for (n = 39; n < 120; n++) {
> +             for (m = 0; m < 4; m++) {
> +                     for (fdpll = 1; fdpll < 32; fdpll++) {
> +                             /* 1/2 (FRQSEL=1) for duty rate 50% */
> +                             dpllclk = extclk * (n + 1) / (m + 1)
> +                                              / (fdpll + 1) / 2;
> +                             if (dpllclk >= 400000000)
> +                                     continue;
> +
> +                             diff = abs((long)dpllclk - (long)mode_clock);
> +                             if (clk_diff_set ||
> +                                     ((diff == 0) || (dpll->diff > diff))) {
> +                                     dpll->diff = diff;
> +                                     dpll->n = n;
> +                                     dpll->m = m;
> +                                     dpll->fdpll = fdpll;
> +                                     dpll->dpllclk = dpllclk;
> +
> +                                     if (clk_diff_set)
> +                                             clk_diff_set = false;
> +
> +                                     if (diff == 0) {
> +                                             match_flag = true;
> +                                             break;
> +                                     }
> +                             }
> +                     }
> +                     if (match_flag)
> +                             break;
> +             }
> +             if (match_flag)
> +                     break;
> +     }
> +}
> +
>   static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
>   {
>       const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
> +     struct rcar_du_device *rcdu = rcrtc->group->dev;
>       unsigned long mode_clock = mode->clock * 1000;
>       unsigned long clk;
>       u32 value;
>       u32 escr;
>       u32 div;
> +     u32 dpll_reg = 0;
> +     struct dpll_info *dpll;
> +     void __iomem *product_reg;
> +     bool h3_es1_workaround = false;
> +
> +     dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
> +     if (dpll == NULL)
> +             return;
> +
> +     /* DU2 DPLL Clock Select bit workaround in R-Car H3(ES1.0) */
> +     product_reg = ioremap(PRODUCT_REG, 0x04);
> +     if (((readl(product_reg) & PRODUCT_MASK) == PRODUCT_H3_BIT)
> +             && ((readl(product_reg) & CUT_ES1_MASK) == CUT_ES1))
> +             h3_es1_workaround = true;
> +     iounmap(product_reg);
>
>       /* Compute the clock divisor and select the internal or external dot
>        * clock based on the requested frequency.
> @@ -130,6 +196,15 @@ static void rcar_du_crtc_set_display_timing(struct 
> rcar_du_crtc *rcrtc)
>               u32 extdiv;
>
>               extclk = clk_get_rate(rcrtc->extclock);
> +
> +             if (rcdu->info->dpll_ch & (0x01 << rcrtc->index)) {
> +                     rcar_du_dpll_divider(dpll, extclk, mode_clock);
> +                     extclk = dpll->dpllclk;
> +                     dev_dbg(rcrtc->group->dev->dev,
> +                             "dpllclk:%d, fdpll:%d, n:%d, m:%d, diff:%d\n",
> +                              dpll->dpllclk, dpll->fdpll, dpll->n, dpll->m,
> +                              dpll->diff);
> +             }
>               extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
>               extdiv = clamp(extdiv, 1U, 64U) - 1;
>
> @@ -140,7 +215,27 @@ static void rcar_du_crtc_set_display_timing(struct 
> rcar_du_crtc *rcrtc)
>                   abs((long)rate - (long)mode_clock)) {
>                       dev_dbg(rcrtc->group->dev->dev,
>                               "crtc%u: using external clock\n", rcrtc->index);
> -                     escr = extdiv | ESCR_DCLKSEL_DCLKIN;
> +                     if (rcdu->info->dpll_ch & (0x01 << rcrtc->index)) {
> +                             escr = ESCR_DCLKSEL_DCLKIN | 0x01;
> +                             dpll_reg =  DPLLCR_CODE | DPLLCR_M(dpll->m) |
> +                                     DPLLCR_FDPLL(dpll->fdpll) |
> +                                     DPLLCR_CLKE | DPLLCR_N(dpll->n) |
> +                                     DPLLCR_STBY;
> +
> +                             if (rcrtc->index == DU_CH_1)
> +                                     dpll_reg |= (DPLLCR_PLCS1 |
> +                                              DPLLCR_INCS_DPLL01_DOTCLKIN13);
> +                             if (rcrtc->index == DU_CH_2) {
> +                                     dpll_reg |= (DPLLCR_PLCS0 |
> +                                              DPLLCR_INCS_DPLL01_DOTCLKIN02);
> +                                     if (h3_es1_workaround)
> +                                             dpll_reg |=  (0x01 << 21);
> +                             }
> +
> +                             rcar_du_group_write(rcrtc->group, DPLLCR,
> +                                                               dpll_reg);
> +                     } else
> +                             escr = extdiv | ESCR_DCLKSEL_DCLKIN;
>               }
>       }
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h 
> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> index 459e539..9a56cc7 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
> @@ -54,6 +54,14 @@ struct rcar_du_crtc {
>       struct rcar_du_vsp *vsp;
>   };
>
> +struct dpll_info {
> +     unsigned int dpllclk;
> +     unsigned int diff;
> +     unsigned int fdpll;
> +     unsigned int n;
> +     unsigned int m;
> +};
> +
>   #define to_rcar_crtc(c)     container_of(c, struct rcar_du_crtc, crtc)
>
>   enum rcar_du_output {
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c 
> b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> index 0a93d2a..5ed0d61 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> @@ -165,6 +165,7 @@ static const struct rcar_du_device_info 
> rcar_du_r8a7795_info = {
>               },
>       },
>       .num_lvds = 1,
> +     .dpll_ch =  BIT(1) | BIT(2),
>   };
>
>   static const struct of_device_id rcar_du_of_table[] = {
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h 
> b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index d1d1d8d..790829b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -69,6 +69,7 @@ struct rcar_du_device_info {
>       unsigned int num_crtcs;
>       struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
>       unsigned int num_lvds;
> +     unsigned int dpll_ch;
>   };
>
>   #define RCAR_DU_MAX_CRTCS           4
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h 
> b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
> index b18b7b2..47fad23 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
> @@ -1,7 +1,7 @@
>   /*
>    * rcar_du_plane.h  --  R-Car Display Unit Planes
>    *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>    *
>    * Contact: Laurent Pinchart (laurent.pinchart at ideasonboard.com)
>    *
> @@ -34,6 +34,11 @@ enum rcar_du_plane_source {
>       RCAR_DU_PLANE_VSPD1,
>   };
>
> +#define DU_CH_0              0
> +#define DU_CH_1              1
> +#define DU_CH_2              2
> +#define DU_CH_3              3
> +
>   struct rcar_du_plane {
>       struct drm_plane plane;
>       struct rcar_du_group *group;
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h 
> b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> index fedb016..7a34bf3 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> @@ -277,6 +277,25 @@
>   #define DEFR10_TSEL_H3_TCON1        (0 << 1) /* DEFR102 register only 
> (DU2/DU3) */
>   #define DEFR10_DEFE10               (1 << 0)
>
> +#define DPLLCR                       0x20044
> +#define DPLLCR_CODE          (0x95 << 24)
> +#define DPLLCR_PLCS1         (1 << 23)
> +#define DPLLCR_PLCS0         (1 << 20)
> +#define DPLLCR_CLKE          (1 << 18)
> +#define DPLLCR_FDPLL(n)              ((n) << 12)     /* n=0 Setting 
> prohibited */
> +/* H'00 to H'26, H'78 to H'7F: Setting prohibited.*/
> +#define DPLLCR_N(n)          ((n) << 5)
> +#define DPLLCR_M(n)          ((n) << 3)
> +#define DPLLCR_STBY          (1 << 2)
> +#define DPLLCR_INCS_DPLL01_DOTCLKIN02        (0 << 0)
> +#define DPLLCR_INCS_DPLL01_DOTCLKIN13        (1 << 1)
> +
> +#define DPLLC2R                      0x20048
> +#define DPLLC2R_CODE         (0x95 << 24)
> +#define DPLLC2R_SELC         (1 << 12)
> +#define DPLLC2R_M(n)         ((n) << 8)
> +#define DPLLC2R_FDPLL(n)     ((n) << 0)      /* n=0 Setting prohibited */
> +
>   /* 
> -----------------------------------------------------------------------------
>    * Display Timing Generation Registers
>    */
>

Reply via email to