summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mgag200/mgag200_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/mgag200/mgag200_mode.c')
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c161
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
*/