[PATCH 5/6] drm: rcar-du: Fix setting a reserved bit in DPLLCR
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Thu Jan 19 09:40:26 UTC 2023
Hi Tomi,
On Thu, Jan 19, 2023 at 11:17:58AM +0200, Tomi Valkeinen wrote:
> On 18/01/2023 23:38, Laurent Pinchart wrote:
> > On Tue, Jan 17, 2023 at 03:51:53PM +0200, Tomi Valkeinen wrote:
> >> On H3 ES1 two bits in DPLLCR are used to select the DU input dot clock
> >
> > s/ES1/ES1.x/
> >
> > Same below.
>
> Ok. But I do wonder, is there a difference? What's the case when ES1
> could be mistaken to mean something else?
It's just for consistency I suppose. No big deal.
> >> source. These are bits 20 and 21 for DU2, and bits 22 and 23 for DU1. On
> >> non-ES1, only the higher bits are used (bits 21 and 23), and the lower
> >> bits are reserved and should be set to 0 (or not set at all).
> >
> > How do you not set a bit ? :-)
>
> By leaving it to the value the register already has. But as we don't
> read the register as a base value here, I guess that comment is a bit
> misleading.
>
> >> The current code always sets the lower bits, even on non-ES1.
> >
> > I think that's harmless, and not worth making the driver more complex,
> > but I'll stop fighting.
> >
> >> For both DU1 and DU2, on all SoC versions, when writing zeroes to those
> >> bits the input clock is DCLKIN, and thus there's no difference between
> >> ES1 and non-ES1.
> >>
> >> For DU1, writing 0b10 to the bits (or only writing the higher bit)
> >> results in using PLL0 as the input clock, so in this case there's also
> >> no difference between ES1 and non-ES1.
> >>
> >> However, for DU2, writing 0b10 to the bits results in using PLL0 as the
> >> input clock on ES1, whereas on non-ES1 it results in using PLL1. On ES1
> >> you need to write 0b11 to select PLL1.
> >>
> >> The current code always writes 0b11 to PLCS0 field to select PLL1 on all
> >> SoC versions, which works but causes an illegal (in the sense of not
> >> allowed by the documentation) write to a reserved bit field.
> >>
> >> To remove the illegal bit write on PLSC0 we need to handle the input dot
> >> clock selection differently for ES1 and non-ES1.
> >>
> >> Add a new quirk, RCAR_DU_QUIRK_H3_ES1_PLL, for this, and a new
> >> rcar_du_device_info entry for the ES1 SoC. Using these, we can always
> >
> > The new entry was added in the previous patch already.
>
> Indeed.
>
> >> set the bit 21 on PLSC0 when choosing the PLL as the source clock, and
> >> additionally set the bit 20 when on ES1.
> >>
> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas at ideasonboard.com>
> >> ---
> >> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 12 ++++++++++--
> >> drivers/gpu/drm/rcar-du/rcar_du_drv.c | 3 ++-
> >> drivers/gpu/drm/rcar-du/rcar_du_drv.h | 1 +
> >> drivers/gpu/drm/rcar-du/rcar_du_regs.h | 3 ++-
> >> 4 files changed, 15 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >> index f2d3266509cc..8d660a6141bf 100644
> >> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >> @@ -245,12 +245,20 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
> >> | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
> >> | DPLLCR_STBY;
> >>
> >> - if (rcrtc->index == 1)
> >> + if (rcrtc->index == 1) {
> >> dpllcr |= DPLLCR_PLCS1
> >> | DPLLCR_INCS_DOTCLKIN1;
> >> - else
> >> + } else {
> >> dpllcr |= DPLLCR_PLCS0
> >> | DPLLCR_INCS_DOTCLKIN0;
> >> + /*
> >> + * On H3 ES1.x, in addition to setting bit 21 (PLCS0),
> >> + * also bit 20 has to be set to select PLL1 as the
> >> + * clock source.
> >
> > I'd add "On ES2 and newer, PLL1 is selected unconditionally.".
>
> It's not selected unconditionally, we need to set bit 21. And possibly
> we need to set bit 20 to 0, although it's not documented what bit 20
> would do when set to 1.
We currently set bit 20 to 1 and it works, so I concluded that bit 20 is
ignored. That's what I meant by PLL1 being selected automatically,
between PLL0 and PLL1. We still need to select PLL instead of DCLKIN
with bit 21.
> And is that "ES2.x"? =)
Good point :-)
> How about:
>
> * On ES2.x and newer, PLL1 is selected by setting bit
> * 21 (PLCS0) to 1 and keeping the (reserved) bit 20 as
> * 0. On H3 ES1.x, in addition to setting bit 21, also
> * bit 20 has to be set to select PLL1 as the clock source.
What I'd like to capture in the comment is that the clock topology is
bit 20
| bit 21
v |
|\ v
PLL0 --> |0| |\
PLL1 --> |1| --> |1| -->
|/ /-> |0|
| |/
DCLKIN ------/
on H3 ES1.x, while on newer revisions, bit 20 is ignored and the first
mux is hardcoded to PLL1.
> >> + */
> >> + if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PLL)
> >> + dpllcr |= DPLLCR_PLCS0_H3ES1X_PLL1_SEL;
> >> + }
> >>
> >> rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
> >>
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> >> index ba2e069fc0f7..d689f2510081 100644
> >> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
> >> @@ -394,7 +394,8 @@ static const struct rcar_du_device_info rcar_du_r8a7795_es1_info = {
> >> | RCAR_DU_FEATURE_VSP1_SOURCE
> >> | RCAR_DU_FEATURE_INTERLACED
> >> | RCAR_DU_FEATURE_TVM_SYNC,
> >> - .quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY,
> >> + .quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY
> >> + | RCAR_DU_QUIRK_H3_ES1_PLL,
> >> .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
> >> .routes = {
> >> /*
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> >> index df87ccab146f..acc3673fefe1 100644
> >> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> >> @@ -35,6 +35,7 @@ struct rcar_du_device;
> >>
> >> #define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */
> >> #define RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY BIT(1) /* H3 ES1 has pclk stability issue */
> >> +#define RCAR_DU_QUIRK_H3_ES1_PLL BIT(2) /* H3 ES1 PLL setup differs from non-ES1 */
> >>
> >> enum rcar_du_output {
> >> RCAR_DU_OUTPUT_DPAD0,
> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >> index c1bcb0e8b5b4..94d913f66c8f 100644
> >> --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
> >> @@ -288,7 +288,8 @@
> >> * isn't implemented by other SoC in the Gen3 family it can safely be set
> >> * unconditionally.
> >> */
> >
> > This comment should be dropped.
>
> Ah, true.
>
> >> -#define DPLLCR_PLCS0 (3 << 20)
> >> +#define DPLLCR_PLCS0 (1 << 21)
> >> +#define DPLLCR_PLCS0_H3ES1X_PLL1_SEL (1 << 20)
> >
> > Bit 21 selects between DCLKIN (when 0) and PLL (when 1). On ES1.x, bit
> > 20 selects between PLL0 (when 0) and PLL1 (when 1), while on ES2 and
> > newer, PLL1 is selected unconditionally. Could we name the two bits
> > accodingly ? Maybe
> >
> > #define DPLLCR_PLCS0_PLL (1 << 21)
> > #define DPLLCR_PLCS0_PLL1 (1 << 20)
>
> I'm fine with DPLLCR_PLCS0_PLL, but I do like to make it a bit more
> obvious that a bit is only for a particular ES/SoC version if it's
> simple to do. Especially here, as "DPLLCR_PLCS0_PLL1" sounds like you
> need to set it to use PLL1.
>
> Would you be ok with "DPLLCR_PLCS0_H3ES1X_PLL1"?
A bit long but I suppose I can live with that.
--
Regards,
Laurent Pinchart
More information about the dri-devel
mailing list