Move the BMC-related code into its own file and wire it up with device
callbacks.

While programming a new display mode, G200EW3 and G200WB have to de-
synchronize with the BMC. Synchronization is done via VIDRST pins
and controlled via VRSTEN and HRSTEN bits. Move the BMC code behind
a serviceable interface and call it from the CRTC's enable and
disable functions.

Signed-off-by: Thomas Zimmermann <tzimmerm...@suse.de>
Reviewed-by: Jocelyn Falempe <jfale...@redhat.com>
Tested-by: Jocelyn Falempe <jfale...@redhat.com>
Acked-by: Sam Ravnborg <s...@ravnborg.org>
---
 drivers/gpu/drm/mgag200/Makefile          |   1 +
 drivers/gpu/drm/mgag200/mgag200_bmc.c     |  99 ++++++++++++++++++++
 drivers/gpu/drm/mgag200/mgag200_drv.h     |  15 +++
 drivers/gpu/drm/mgag200/mgag200_g200ew3.c |   2 +
 drivers/gpu/drm/mgag200/mgag200_g200wb.c  |   2 +
 drivers/gpu/drm/mgag200/mgag200_mode.c    | 107 ++--------------------
 6 files changed, 129 insertions(+), 97 deletions(-)
 create mode 100644 drivers/gpu/drm/mgag200/mgag200_bmc.c

diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
index 89558549c3af..94d465a2b753 100644
--- a/drivers/gpu/drm/mgag200/Makefile
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mgag200-y := \
+       mgag200_bmc.o \
        mgag200_drv.o \
        mgag200_g200.o \
        mgag200_g200eh.o \
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c 
b/drivers/gpu/drm/mgag200/mgag200_bmc.c
new file mode 100644
index 000000000000..2ba2e3c5086a
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/delay.h>
+
+#include "mgag200_drv.h"
+
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
+{
+       u8 tmp;
+       int iter_max;
+
+       /*
+        * 1 - The first step is to inform the BMC of an upcoming mode
+        * change. We are putting the misc<0> to output.
+        */
+
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x10;
+       WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
+
+       /* we are putting a 1 on the misc<0> line */
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x10;
+       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+
+       /*
+        * 2- Second step to mask any further scan request. This is
+        * done by asserting the remfreqmsk bit (XSPAREREG<7>)
+        */
+
+       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x80;
+       WREG_DAC(MGA1064_SPAREREG, tmp);
+
+       /*
+        * 3a- The third step is to verify if there is an active scan.
+        * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
+        */
+       iter_max = 300;
+       while (!(tmp & 0x1) && iter_max) {
+               WREG8(DAC_INDEX, MGA1064_SPAREREG);
+               tmp = RREG8(DAC_DATA);
+               udelay(1000);
+               iter_max--;
+       }
+
+       /*
+        * 3b- This step occurs only if the remove is actually
+        * scanning. We are waiting for the end of the frame which is
+        * a 1 on remvsyncsts (XSPAREREG<1>)
+        */
+       if (iter_max) {
+               iter_max = 300;
+               while ((tmp & 0x2) && iter_max) {
+                       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+                       tmp = RREG8(DAC_DATA);
+                       udelay(1000);
+                       iter_max--;
+               }
+       }
+}
+
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
+{
+       u8 tmp;
+
+       /* Ensure that the vrsten and hrsten are set */
+       WREG8(MGAREG_CRTCEXT_INDEX, 1);
+       tmp = RREG8(MGAREG_CRTCEXT_DATA);
+       WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
+
+       /* Assert rstlvl2 */
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x8;
+       WREG8(DAC_DATA, tmp);
+
+       udelay(10);
+
+       /* Deassert rstlvl2 */
+       tmp &= ~0x08;
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+       WREG8(DAC_DATA, tmp);
+
+       /* Remove mask of scan request */
+       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~0x80;
+       WREG8(DAC_DATA, tmp);
+
+       /* Put back a 0 on the misc<0> line */
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~0x10;
+       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+}
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h 
b/drivers/gpu/drm/mgag200/mgag200_drv.h
index db29eef8981b..e78c1b2f5c27 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -263,6 +263,17 @@ struct mgag200_device_info {
        }
 
 struct mgag200_device_funcs {
+       /*
+        * Disables an external reset source (i.e., BMC) before programming
+        * a new display mode.
+        */
+       void (*disable_vidrst)(struct mga_device *mdev);
+
+       /*
+        * Enables an external reset source (i.e., BMC) after programming
+        * a new display mode.
+        */
+       void (*enable_vidrst)(struct mga_device *mdev);
 };
 
 struct mga_device {
@@ -354,6 +365,10 @@ resource_size_t mgag200_device_probe_vram(struct 
mga_device *mdev);
 void mgag200_init_registers(struct mga_device *mdev);
 int mgag200_modeset_init(struct mga_device *mdev, resource_size_t 
vram_fb_available);
 
+                               /* mgag200_bmc.c */
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
+
                                /* mgag200_i2c.c */
 int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c 
b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
index 202db00bb62e..19a870120ebc 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
@@ -21,6 +21,8 @@ static const struct mgag200_device_info 
mgag200_g200ew3_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);
 
 static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
+       .disable_vidrst = mgag200_bmc_disable_vidrst,
+       .enable_vidrst = mgag200_bmc_enable_vidrst,
 };
 
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device 
*mdev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c 
b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
index 2b5dd0cc38e2..91d2848b4b06 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
@@ -36,6 +36,8 @@ static const struct mgag200_device_info 
mgag200_g200wb_device_info =
        MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false);
 
 static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
+       .disable_vidrst = mgag200_bmc_disable_vidrst,
+       .enable_vidrst = mgag200_bmc_enable_vidrst,
 };
 
 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const 
struct drm_driver *drv,
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 22f15d4b4ff0..655b053e1750 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -131,95 +131,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
        } while ((status & 0x01) && time_before(jiffies, timeout));
 }
 
-static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
-{
-       u8 tmp;
-       int iter_max;
-
-       /* 1- The first step is to warn the BMC of an upcoming mode change.
-        * We are putting the misc<0> to output.*/
-
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x10;
-       WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
-
-       /* we are putting a 1 on the misc<0> line */
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x10;
-       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-
-       /* 2- Second step to mask and further scan request
-        * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
-        */
-       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x80;
-       WREG_DAC(MGA1064_SPAREREG, tmp);
-
-       /* 3a- the third step is to verifu if there is an active scan
-        * We are searching for a 0 on remhsyncsts <XSPAREREG<0>)
-        */
-       iter_max = 300;
-       while (!(tmp & 0x1) && iter_max) {
-               WREG8(DAC_INDEX, MGA1064_SPAREREG);
-               tmp = RREG8(DAC_DATA);
-               udelay(1000);
-               iter_max--;
-       }
-
-       /* 3b- this step occurs only if the remove is actually scanning
-        * we are waiting for the end of the frame which is a 1 on
-        * remvsyncsts (XSPAREREG<1>)
-        */
-       if (iter_max) {
-               iter_max = 300;
-               while ((tmp & 0x2) && iter_max) {
-                       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-                       tmp = RREG8(DAC_DATA);
-                       udelay(1000);
-                       iter_max--;
-               }
-       }
-}
-
-static void mgag200_g200wb_release_bmc(struct mga_device *mdev)
-{
-       u8 tmp;
-
-       /* 1- The first step is to ensure that the vrsten and hrsten are set */
-       WREG8(MGAREG_CRTCEXT_INDEX, 1);
-       tmp = RREG8(MGAREG_CRTCEXT_DATA);
-       WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
-
-       /* 2- second step is to assert the rstlvl2 */
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x8;
-       WREG8(DAC_DATA, tmp);
-
-       /* wait 10 us */
-       udelay(10);
-
-       /* 3- deassert rstlvl2 */
-       tmp &= ~0x08;
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-       WREG8(DAC_DATA, tmp);
-
-       /* 4- remove mask of scan request */
-       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~0x80;
-       WREG8(DAC_DATA, tmp);
-
-       /* 5- put back a 0 on the misc<0> line */
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~0x10;
-       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-}
-
 /*
  * This is how the framebuffer base address is stored in g200 cards:
  *   * Assume @offset is the gpu_addr variable of the framebuffer object
@@ -802,14 +713,15 @@ static void mgag200_crtc_helper_atomic_enable(struct 
drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = to_mga_device(dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
        struct drm_crtc_state *crtc_state = crtc->state;
        struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
        struct mgag200_crtc_state *mgag200_crtc_state = 
to_mgag200_crtc_state(crtc_state);
        const struct drm_format_info *format = mgag200_crtc_state->format;
        struct mgag200_pll *pixpll = &mdev->pixpll;
 
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_hold_bmc(mdev);
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
 
        mgag200_set_format_regs(mdev, format);
        mgag200_set_mode_regs(mdev, adjusted_mode);
@@ -826,22 +738,23 @@ static void mgag200_crtc_helper_atomic_enable(struct 
drm_crtc *crtc,
 
        mgag200_enable_display(mdev);
 
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_release_bmc(mdev);
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
 }
 
 static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
                                               struct drm_atomic_state 
*old_state)
 {
        struct mga_device *mdev = to_mga_device(crtc->dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
 
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_hold_bmc(mdev);
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
 
        mgag200_disable_display(mdev);
 
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_release_bmc(mdev);
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
 }
 
 static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = {
-- 
2.37.1

Reply via email to