Commit 9f1d036648c1c5ed81b0e98d7a06d55df972701e

Authored by Christopher Harvey
Committed by Dave Airlie
1 parent 3cdc0e8d61

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>

Showing 1 changed file with 24 additions and 3 deletions Side-by-side Diff

drivers/gpu/drm/mgag200/mgag200_mode.c
... ... @@ -654,12 +654,26 @@
654 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 + */
658 671 void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
659 672 {
660 673 struct mga_device *mdev = crtc->dev->dev_private;
661 674 u32 addr;
662 675 int count;
  676 + u8 crtcext0;
663 677  
664 678 while (RREG8(0x1fda) & 0x08);
665 679 while (!(RREG8(0x1fda) & 0x08));
666 680  
... ... @@ -667,10 +681,17 @@
667 681 count = RREG8(MGAREG_VCOUNT) + 2;
668 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 692 WREG_CRT(0x0d, (u8)(addr & 0xff));
672 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