drm/mgag200: Select clock in PLL update functions
authorThomas Zimmermann <tzimmermann@suse.de>
Wed, 14 Jul 2021 14:22:28 +0000 (16:22 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Sun, 8 Aug 2021 18:13:10 +0000 (20:13 +0200)
Put the clock-selection code into each of the PLL-update functions to
make them select the correct pixel clock. Instead of copying the code,
introduce a new helper WREG_MISC_MASKED, which does masked writes into
<MISC>. Use it from each individual PLL update function.

The pixel clock for video output was not actually set before programming
the clock's values. It worked because the device had the correct clock
pre-set.

v2:
* don't duplicate <MISC> update code (Sam)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: db05f8d3dc87 ("drm/mgag200: Split MISC register update into PLL selection, SYNC and I/O")
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Emil Velikov <emil.velikov@collabora.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v5.9+
Link: https://patchwork.freedesktop.org/patch/msgid/20210714142240.21979-2-tzimmermann@suse.de
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_reg.h

index f7a0537c0d0ae1919dc1580e10ab2f850f5170c3..5302d6566d7c7e79ad44948eab72d68ad326b9d3 100644 (file)
 #define ATTR_INDEX 0x1fc0
 #define ATTR_DATA 0x1fc1
 
+#define WREG_MISC(v)                                           \
+       WREG8(MGA_MISC_OUT, v)
+
+#define RREG_MISC(v)                                           \
+       ((v) = RREG8(MGA_MISC_IN))
+
+#define WREG_MISC_MASKED(v, mask)                              \
+       do {                                                    \
+               u8 misc_;                                       \
+               u8 mask_ = (mask);                              \
+               RREG_MISC(misc_);                               \
+               misc_ &= ~mask_;                                \
+               misc_ |= ((v) & mask_);                         \
+               WREG_MISC(misc_);                               \
+       } while (0)
+
 #define WREG_ATTR(reg, v)                                      \
        do {                                                    \
                RREG8(0x1fda);                                  \
index 3b3059f471c2ff5d038ab1de86ba5c90699cea71..1bdf21474bcb29012dc458fe61df6486b5fa71d6 100644 (file)
@@ -174,6 +174,8 @@ static int mgag200_g200_set_plls(struct mga_device *mdev, long clock)
        drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
                    clock, f_vco, m, n, p, s);
 
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        WREG_DAC(MGA1064_PIX_PLLC_M, m);
        WREG_DAC(MGA1064_PIX_PLLC_N, n);
        WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3)));
@@ -289,6 +291,8 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
                return 1;
        }
 
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        WREG_DAC(MGA1064_PIX_PLLC_M, m);
        WREG_DAC(MGA1064_PIX_PLLC_N, n);
        WREG_DAC(MGA1064_PIX_PLLC_P, p);
@@ -385,6 +389,8 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                }
        }
 
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        for (i = 0; i <= 32 && pll_locked == false; i++) {
                if (i > 0) {
                        WREG8(MGAREG_CRTC_INDEX, 0x1e);
@@ -522,6 +528,8 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
                }
        }
 
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
@@ -654,6 +662,9 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
                        }
                }
        }
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        for (i = 0; i <= 32 && pll_locked == false; i++) {
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
@@ -754,6 +765,8 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
                }
        }
 
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
@@ -787,8 +800,6 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
 
 static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock)
 {
-       u8 misc;
-
        switch(mdev->type) {
        case G200_PCI:
        case G200_AGP:
@@ -808,11 +819,6 @@ static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock)
                return mga_g200er_set_plls(mdev, clock);
        }
 
-       misc = RREG8(MGA_MISC_IN);
-       misc &= ~MGAREG_MISC_CLK_SEL_MASK;
-       misc |= MGAREG_MISC_CLK_SEL_MGA_MSK;
-       WREG8(MGA_MISC_OUT, misc);
-
        return 0;
 }
 
index 977be0565c061c179ac63dc0f8d6a1722547c697..60e705283fe84625905d87aee57cbc52150d549e 100644 (file)
 
 #define MGAREG_MISC_IOADSEL    (0x1 << 0)
 #define MGAREG_MISC_RAMMAPEN   (0x1 << 1)
-#define MGAREG_MISC_CLK_SEL_MASK       GENMASK(3, 2)
-#define MGAREG_MISC_CLK_SEL_VGA25      (0x0 << 2)
-#define MGAREG_MISC_CLK_SEL_VGA28      (0x1 << 2)
-#define MGAREG_MISC_CLK_SEL_MGA_PIX    (0x2 << 2)
-#define MGAREG_MISC_CLK_SEL_MGA_MSK    (0x3 << 2)
+#define MGAREG_MISC_CLKSEL_MASK                GENMASK(3, 2)
+#define MGAREG_MISC_CLKSEL_VGA25       (0x0 << 2)
+#define MGAREG_MISC_CLKSEL_VGA28       (0x1 << 2)
+#define MGAREG_MISC_CLKSEL_MGA         (0x3 << 2)
 #define MGAREG_MISC_VIDEO_DIS  (0x1 << 4)
 #define MGAREG_MISC_HIGH_PG_SEL        (0x1 << 5)
 #define MGAREG_MISC_HSYNCPOL           BIT(6)