aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Harvey <charvey@matrox.com>2013-05-08 15:10:38 -0400
committerDave Airlie <airlied@redhat.com>2013-05-12 22:17:32 -0400
commit9f1d036648c1c5ed81b0e98d7a06d55df972701e (patch)
tree78600dce323c045b93d35d1e3d18799d992df65d
parent3cdc0e8d6142aaf3eb84a53eab6de1160da290a3 (diff)
drm/mgag200: Fix framebuffer base address programming
Higher bits of the base address of framebuffers weren't being programmed properly. This caused framebuffers that didn't happen to be allocated at a low enough address to not be displayed properly. Signed-off-by: Christopher Harvey <charvey@matrox.com> Signed-off-by: Mathieu Larouche <mathieu.larouche@matrox.com> Acked-by: Julia Lemire <jlemire@matrox.com> Tested-by: Julia Lemire <jlemire@matrox.com> Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 0326989a6aec..e8e20c653b1d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -654,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
654 WREG_DAC(MGA1064_GEN_IO_DATA, tmp); 654 WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
655} 655}
656 656
657 657/*
658 This is how the framebuffer base address is stored in g200 cards:
659 * Assume @offset is the gpu_addr variable of the framebuffer object
660 * Then addr is the number of _pixels_ (not bytes) from the start of
661 VRAM to the first pixel we want to display. (divided by 2 for 32bit
662 framebuffers)
663 * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers
664 addr<20> -> CRTCEXT0<6>
665 addr<19-16> -> CRTCEXT0<3-0>
666 addr<15-8> -> CRTCC<7-0>
667 addr<7-0> -> CRTCD<7-0>
668 CRTCEXT0 has to be programmed last to trigger an update and make the
669 new addr variable take effect.
670 */
658void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) 671void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
659{ 672{
660 struct mga_device *mdev = crtc->dev->dev_private; 673 struct mga_device *mdev = crtc->dev->dev_private;
661 u32 addr; 674 u32 addr;
662 int count; 675 int count;
676 u8 crtcext0;
663 677
664 while (RREG8(0x1fda) & 0x08); 678 while (RREG8(0x1fda) & 0x08);
665 while (!(RREG8(0x1fda) & 0x08)); 679 while (!(RREG8(0x1fda) & 0x08));
@@ -667,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
667 count = RREG8(MGAREG_VCOUNT) + 2; 681 count = RREG8(MGAREG_VCOUNT) + 2;
668 while (RREG8(MGAREG_VCOUNT) < count); 682 while (RREG8(MGAREG_VCOUNT) < count);
669 683
670 addr = offset >> 2; 684 WREG8(MGAREG_CRTCEXT_INDEX, 0);
685 crtcext0 = RREG8(MGAREG_CRTCEXT_DATA);
686 crtcext0 &= 0xB0;
687 addr = offset / 8;
688 /* Can't store addresses any higher than that...
689 but we also don't have more than 16MB of memory, so it should be fine. */
690 WARN_ON(addr > 0x1fffff);
691 crtcext0 |= (!!(addr & (1<<20)))<<6;
671 WREG_CRT(0x0d, (u8)(addr & 0xff)); 692 WREG_CRT(0x0d, (u8)(addr & 0xff));
672 WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); 693 WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff);
673 WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf); 694 WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);
674} 695}
675 696
676 697