Commit 9f1d036648c1c5ed81b0e98d7a06d55df972701e
Committed by
Dave Airlie
1 parent
3cdc0e8d61
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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 |