diff options
Diffstat (limited to 'drivers/gpu/drm/mgag200/mgag200_mode.c')
-rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_mode.c | 161 |
1 files changed, 77 insertions, 84 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 0f0d59938c3a..fb71658c3117 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -14,14 +14,16 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_damage_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_panic.h> #include <drm/drm_print.h> -#include <drm/drm_probe_helper.h> +#include "mgag200_ddc.h" #include "mgag200_drv.h" /* @@ -109,12 +111,12 @@ static inline void mga_wait_vsync(struct mga_device *mdev) unsigned int status = 0; do { - status = RREG32(MGAREG_Status); + status = RREG32(MGAREG_STATUS); } while ((status & 0x08) && time_before(jiffies, timeout)); timeout = jiffies + HZ/10; status = 0; do { - status = RREG32(MGAREG_Status); + status = RREG32(MGAREG_STATUS); } while (!(status & 0x08) && time_before(jiffies, timeout)); } @@ -123,7 +125,7 @@ static inline void mga_wait_busy(struct mga_device *mdev) unsigned long timeout = jiffies + HZ; unsigned int status = 0; do { - status = RREG8(MGAREG_Status + 2); + status = RREG8(MGAREG_STATUS + 2); } while ((status & 0x01) && time_before(jiffies, timeout)); } @@ -199,26 +201,32 @@ void mgag200_init_registers(struct mga_device *mdev) WREG8(MGA_MISC_OUT, misc); } -void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode) +void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode, + bool set_vidrst) { - const struct mgag200_device_info *info = mdev->info; - unsigned int hdisplay, hsyncstart, hsyncend, htotal; - unsigned int vdisplay, vsyncstart, vsyncend, vtotal; + unsigned int hdispend, hsyncstr, hsyncend, htotal, hblkstr, hblkend; + unsigned int vdispend, vsyncstr, vsyncend, vtotal, vblkstr, vblkend; + unsigned int linecomp; u8 misc, crtcext1, crtcext2, crtcext5; - hdisplay = mode->hdisplay / 8 - 1; - hsyncstart = mode->hsync_start / 8 - 1; - hsyncend = mode->hsync_end / 8 - 1; - htotal = mode->htotal / 8 - 1; - + hdispend = mode->crtc_hdisplay / 8 - 1; + hsyncstr = mode->crtc_hsync_start / 8 - 1; + hsyncend = mode->crtc_hsync_end / 8 - 1; + htotal = mode->crtc_htotal / 8 - 1; /* Work around hardware quirk */ if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04) htotal++; + hblkstr = mode->crtc_hblank_start / 8 - 1; + hblkend = htotal; - vdisplay = mode->vdisplay - 1; - vsyncstart = mode->vsync_start - 1; - vsyncend = mode->vsync_end - 1; - vtotal = mode->vtotal - 2; + vdispend = mode->crtc_vdisplay - 1; + vsyncstr = mode->crtc_vsync_start - 1; + vsyncend = mode->crtc_vsync_end - 1; + vtotal = mode->crtc_vtotal - 2; + vblkstr = mode->crtc_vblank_start; + vblkend = vtotal + 1; + + linecomp = vdispend; misc = RREG8(MGA_MISC_IN); @@ -233,45 +241,45 @@ void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mod misc &= ~MGAREG_MISC_VSYNCPOL; crtcext1 = (((htotal - 4) & 0x100) >> 8) | - ((hdisplay & 0x100) >> 7) | - ((hsyncstart & 0x100) >> 6) | - (htotal & 0x40); - if (info->has_vidrst) + ((hblkstr & 0x100) >> 7) | + ((hsyncstr & 0x100) >> 6) | + (hblkend & 0x40); + if (set_vidrst) crtcext1 |= MGAREG_CRTCEXT1_VRSTEN | MGAREG_CRTCEXT1_HRSTEN; crtcext2 = ((vtotal & 0xc00) >> 10) | - ((vdisplay & 0x400) >> 8) | - ((vdisplay & 0xc00) >> 7) | - ((vsyncstart & 0xc00) >> 5) | - ((vdisplay & 0x400) >> 3); + ((vdispend & 0x400) >> 8) | + ((vblkstr & 0xc00) >> 7) | + ((vsyncstr & 0xc00) >> 5) | + ((linecomp & 0x400) >> 3); crtcext5 = 0x00; - WREG_CRT(0, htotal - 4); - WREG_CRT(1, hdisplay); - WREG_CRT(2, hdisplay); - WREG_CRT(3, (htotal & 0x1F) | 0x80); - WREG_CRT(4, hsyncstart); - WREG_CRT(5, ((htotal & 0x20) << 2) | (hsyncend & 0x1F)); - WREG_CRT(6, vtotal & 0xFF); - WREG_CRT(7, ((vtotal & 0x100) >> 8) | - ((vdisplay & 0x100) >> 7) | - ((vsyncstart & 0x100) >> 6) | - ((vdisplay & 0x100) >> 5) | - ((vdisplay & 0x100) >> 4) | /* linecomp */ - ((vtotal & 0x200) >> 4) | - ((vdisplay & 0x200) >> 3) | - ((vsyncstart & 0x200) >> 2)); - WREG_CRT(9, ((vdisplay & 0x200) >> 4) | - ((vdisplay & 0x200) >> 3)); - WREG_CRT(16, vsyncstart & 0xFF); - WREG_CRT(17, (vsyncend & 0x0F) | 0x20); - WREG_CRT(18, vdisplay & 0xFF); - WREG_CRT(20, 0); - WREG_CRT(21, vdisplay & 0xFF); - WREG_CRT(22, (vtotal + 1) & 0xFF); - WREG_CRT(23, 0xc3); - WREG_CRT(24, vdisplay & 0xFF); + WREG_CRT(0x00, htotal - 4); + WREG_CRT(0x01, hdispend); + WREG_CRT(0x02, hblkstr); + WREG_CRT(0x03, (hblkend & 0x1f) | 0x80); + WREG_CRT(0x04, hsyncstr); + WREG_CRT(0x05, ((hblkend & 0x20) << 2) | (hsyncend & 0x1f)); + WREG_CRT(0x06, vtotal & 0xff); + WREG_CRT(0x07, ((vtotal & 0x100) >> 8) | + ((vdispend & 0x100) >> 7) | + ((vsyncstr & 0x100) >> 6) | + ((vblkstr & 0x100) >> 5) | + ((linecomp & 0x100) >> 4) | + ((vtotal & 0x200) >> 4) | + ((vdispend & 0x200) >> 3) | + ((vsyncstr & 0x200) >> 2)); + WREG_CRT(0x09, ((vblkstr & 0x200) >> 4) | + ((linecomp & 0x200) >> 3)); + WREG_CRT(0x10, vsyncstr & 0xff); + WREG_CRT(0x11, (vsyncend & 0x0f) | 0x20); + WREG_CRT(0x12, vdispend & 0xff); + WREG_CRT(0x14, 0); + WREG_CRT(0x15, vblkstr & 0xff); + WREG_CRT(0x16, vblkend & 0xff); + WREG_CRT(0x17, 0xc3); + WREG_CRT(0x18, linecomp & 0xff); WREG_ECRT(0x01, crtcext1); WREG_ECRT(0x02, crtcext2); @@ -538,6 +546,23 @@ void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, msleep(20); } +int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb) +{ + struct mga_device *mdev = to_mga_device(plane->dev); + struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram); + + if (plane->state && plane->state->fb) { + sb->format = plane->state->fb->format; + sb->width = plane->state->fb->width; + sb->height = plane->state->fb->height; + sb->pitch[0] = plane->state->fb->pitches[0]; + sb->map[0] = map; + return 0; + } + return -ENODEV; +} + /* * CRTC */ @@ -633,11 +658,8 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); const struct drm_format_info *format = mgag200_crtc_state->format; - if (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); - mgag200_set_format_regs(mdev, format); - mgag200_set_mode_regs(mdev, adjusted_mode); + mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); @@ -648,23 +670,13 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ mgag200_crtc_set_gamma_linear(mdev, format); mgag200_enable_display(mdev); - - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); } 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 (funcs->disable_vidrst) - funcs->disable_vidrst(mdev); mgag200_disable_display(mdev); - - if (funcs->enable_vidrst) - funcs->enable_vidrst(mdev); } void mgag200_crtc_reset(struct drm_crtc *crtc) @@ -698,6 +710,7 @@ struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc new_mgag200_crtc_state->format = mgag200_crtc_state->format; memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc, sizeof(new_mgag200_crtc_state->pixpllc)); + new_mgag200_crtc_state->set_vidrst = mgag200_crtc_state->set_vidrst; return &new_mgag200_crtc_state->base; } @@ -711,26 +724,6 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st } /* - * Connector - */ - -int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector) -{ - struct mga_device *mdev = to_mga_device(connector->dev); - int ret; - - /* - * Protect access to I/O registers from concurrent modesetting - * by acquiring the I/O-register lock. - */ - mutex_lock(&mdev->rmmio_lock); - ret = drm_connector_helper_get_modes_from_ddc(connector); - mutex_unlock(&mdev->rmmio_lock); - - return ret; -} - -/* * Mode config */ |