diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2022-07-28 14:40:59 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2022-07-29 16:01:47 +0200 |
commit | 8aeeb3144fe27b2b8aa30db262de2f654f2edb9a (patch) | |
tree | dd00892e470583818ec1c78890e6261466a3c09b /drivers/gpu/drm/mgag200/mgag200_mode.c | |
parent | drm/mgag200: Add per-device callbacks (diff) | |
download | linux-8aeeb3144fe27b2b8aa30db262de2f654f2edb9a.tar.xz linux-8aeeb3144fe27b2b8aa30db262de2f654f2edb9a.zip |
drm/mgag200: Provide per-device callbacks for BMC synchronization
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 <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Jocelyn Falempe <jfalempe@redhat.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-11-tzimmermann@suse.de
Diffstat (limited to '')
-rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_mode.c | 107 |
1 files changed, 10 insertions, 97 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 7536a9a41bd6..2b1e9f069366 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 = { |