.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2010 Matt Turner. |
---|
3 | 4 | * Copyright 2012 Red Hat |
---|
4 | | - * |
---|
5 | | - * This file is subject to the terms and conditions of the GNU General |
---|
6 | | - * Public License version 2. See the file COPYING in the main |
---|
7 | | - * directory of this archive for more details. |
---|
8 | 5 | * |
---|
9 | 6 | * Authors: Matthew Garrett |
---|
10 | 7 | * Matt Turner |
---|
.. | .. |
---|
13 | 10 | |
---|
14 | 11 | #include <linux/delay.h> |
---|
15 | 12 | |
---|
16 | | -#include <drm/drmP.h> |
---|
| 13 | +#include <drm/drm_atomic_helper.h> |
---|
| 14 | +#include <drm/drm_atomic_state_helper.h> |
---|
17 | 15 | #include <drm/drm_crtc_helper.h> |
---|
| 16 | +#include <drm/drm_damage_helper.h> |
---|
| 17 | +#include <drm/drm_format_helper.h> |
---|
| 18 | +#include <drm/drm_fourcc.h> |
---|
| 19 | +#include <drm/drm_gem_framebuffer_helper.h> |
---|
18 | 20 | #include <drm/drm_plane_helper.h> |
---|
| 21 | +#include <drm/drm_print.h> |
---|
| 22 | +#include <drm/drm_probe_helper.h> |
---|
| 23 | +#include <drm/drm_simple_kms_helper.h> |
---|
19 | 24 | |
---|
20 | 25 | #include "mgag200_drv.h" |
---|
21 | 26 | |
---|
.. | .. |
---|
28 | 33 | static void mga_crtc_load_lut(struct drm_crtc *crtc) |
---|
29 | 34 | { |
---|
30 | 35 | struct drm_device *dev = crtc->dev; |
---|
31 | | - struct mga_device *mdev = dev->dev_private; |
---|
32 | | - struct drm_framebuffer *fb = crtc->primary->fb; |
---|
| 36 | + struct mga_device *mdev = to_mga_device(dev); |
---|
| 37 | + struct drm_framebuffer *fb; |
---|
33 | 38 | u16 *r_ptr, *g_ptr, *b_ptr; |
---|
34 | 39 | int i; |
---|
35 | 40 | |
---|
36 | 41 | if (!crtc->enabled) |
---|
37 | 42 | return; |
---|
| 43 | + |
---|
| 44 | + if (!mdev->display_pipe.plane.state) |
---|
| 45 | + return; |
---|
| 46 | + |
---|
| 47 | + fb = mdev->display_pipe.plane.state->fb; |
---|
38 | 48 | |
---|
39 | 49 | r_ptr = crtc->gamma_store; |
---|
40 | 50 | g_ptr = r_ptr + crtc->gamma_size; |
---|
.. | .. |
---|
98 | 108 | } while ((status & 0x01) && time_before(jiffies, timeout)); |
---|
99 | 109 | } |
---|
100 | 110 | |
---|
| 111 | +/* |
---|
| 112 | + * PLL setup |
---|
| 113 | + */ |
---|
| 114 | + |
---|
| 115 | +static int mgag200_g200_set_plls(struct mga_device *mdev, long clock) |
---|
| 116 | +{ |
---|
| 117 | + struct drm_device *dev = &mdev->base; |
---|
| 118 | + const int post_div_max = 7; |
---|
| 119 | + const int in_div_min = 1; |
---|
| 120 | + const int in_div_max = 6; |
---|
| 121 | + const int feed_div_min = 7; |
---|
| 122 | + const int feed_div_max = 127; |
---|
| 123 | + u8 testm, testn; |
---|
| 124 | + u8 n = 0, m = 0, p, s; |
---|
| 125 | + long f_vco; |
---|
| 126 | + long computed; |
---|
| 127 | + long delta, tmp_delta; |
---|
| 128 | + long ref_clk = mdev->model.g200.ref_clk; |
---|
| 129 | + long p_clk_min = mdev->model.g200.pclk_min; |
---|
| 130 | + long p_clk_max = mdev->model.g200.pclk_max; |
---|
| 131 | + |
---|
| 132 | + if (clock > p_clk_max) { |
---|
| 133 | + drm_err(dev, "Pixel Clock %ld too high\n", clock); |
---|
| 134 | + return 1; |
---|
| 135 | + } |
---|
| 136 | + |
---|
| 137 | + if (clock < p_clk_min >> 3) |
---|
| 138 | + clock = p_clk_min >> 3; |
---|
| 139 | + |
---|
| 140 | + f_vco = clock; |
---|
| 141 | + for (p = 0; |
---|
| 142 | + p <= post_div_max && f_vco < p_clk_min; |
---|
| 143 | + p = (p << 1) + 1, f_vco <<= 1) |
---|
| 144 | + ; |
---|
| 145 | + |
---|
| 146 | + delta = clock; |
---|
| 147 | + |
---|
| 148 | + for (testm = in_div_min; testm <= in_div_max; testm++) { |
---|
| 149 | + for (testn = feed_div_min; testn <= feed_div_max; testn++) { |
---|
| 150 | + computed = ref_clk * (testn + 1) / (testm + 1); |
---|
| 151 | + if (computed < f_vco) |
---|
| 152 | + tmp_delta = f_vco - computed; |
---|
| 153 | + else |
---|
| 154 | + tmp_delta = computed - f_vco; |
---|
| 155 | + if (tmp_delta < delta) { |
---|
| 156 | + delta = tmp_delta; |
---|
| 157 | + m = testm; |
---|
| 158 | + n = testn; |
---|
| 159 | + } |
---|
| 160 | + } |
---|
| 161 | + } |
---|
| 162 | + f_vco = ref_clk * (n + 1) / (m + 1); |
---|
| 163 | + if (f_vco < 100000) |
---|
| 164 | + s = 0; |
---|
| 165 | + else if (f_vco < 140000) |
---|
| 166 | + s = 1; |
---|
| 167 | + else if (f_vco < 180000) |
---|
| 168 | + s = 2; |
---|
| 169 | + else |
---|
| 170 | + s = 3; |
---|
| 171 | + |
---|
| 172 | + drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", |
---|
| 173 | + clock, f_vco, m, n, p, s); |
---|
| 174 | + |
---|
| 175 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
| 176 | + |
---|
| 177 | + WREG_DAC(MGA1064_PIX_PLLC_M, m); |
---|
| 178 | + WREG_DAC(MGA1064_PIX_PLLC_N, n); |
---|
| 179 | + WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3))); |
---|
| 180 | + |
---|
| 181 | + return 0; |
---|
| 182 | +} |
---|
| 183 | + |
---|
101 | 184 | #define P_ARRAY_SIZE 9 |
---|
102 | 185 | |
---|
103 | 186 | static int mga_g200se_set_plls(struct mga_device *mdev, long clock) |
---|
104 | 187 | { |
---|
| 188 | + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; |
---|
105 | 189 | unsigned int vcomax, vcomin, pllreffreq; |
---|
106 | 190 | unsigned int delta, tmpdelta, permitteddelta; |
---|
107 | 191 | unsigned int testp, testm, testn; |
---|
.. | .. |
---|
111 | 195 | unsigned int fvv; |
---|
112 | 196 | unsigned int i; |
---|
113 | 197 | |
---|
114 | | - if (mdev->unique_rev_id <= 0x03) { |
---|
| 198 | + if (unique_rev_id <= 0x03) { |
---|
115 | 199 | |
---|
116 | 200 | m = n = p = 0; |
---|
117 | 201 | vcomax = 320000; |
---|
.. | .. |
---|
205 | 289 | return 1; |
---|
206 | 290 | } |
---|
207 | 291 | |
---|
| 292 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
| 293 | + |
---|
208 | 294 | WREG_DAC(MGA1064_PIX_PLLC_M, m); |
---|
209 | 295 | WREG_DAC(MGA1064_PIX_PLLC_N, n); |
---|
210 | 296 | WREG_DAC(MGA1064_PIX_PLLC_P, p); |
---|
211 | 297 | |
---|
212 | | - if (mdev->unique_rev_id >= 0x04) { |
---|
| 298 | + if (unique_rev_id >= 0x04) { |
---|
213 | 299 | WREG_DAC(0x1a, 0x09); |
---|
214 | 300 | msleep(20); |
---|
215 | 301 | WREG_DAC(0x1a, 0x01); |
---|
.. | .. |
---|
300 | 386 | } |
---|
301 | 387 | } |
---|
302 | 388 | } |
---|
| 389 | + |
---|
| 390 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
303 | 391 | |
---|
304 | 392 | for (i = 0; i <= 32 && pll_locked == false; i++) { |
---|
305 | 393 | if (i > 0) { |
---|
.. | .. |
---|
438 | 526 | } |
---|
439 | 527 | } |
---|
440 | 528 | |
---|
| 529 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
| 530 | + |
---|
441 | 531 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
---|
442 | 532 | tmp = RREG8(DAC_DATA); |
---|
443 | 533 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
---|
.. | .. |
---|
570 | 660 | } |
---|
571 | 661 | } |
---|
572 | 662 | } |
---|
| 663 | + |
---|
| 664 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
| 665 | + |
---|
573 | 666 | for (i = 0; i <= 32 && pll_locked == false; i++) { |
---|
574 | 667 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
---|
575 | 668 | tmp = RREG8(DAC_DATA); |
---|
.. | .. |
---|
670 | 763 | } |
---|
671 | 764 | } |
---|
672 | 765 | |
---|
| 766 | + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); |
---|
| 767 | + |
---|
673 | 768 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
---|
674 | 769 | tmp = RREG8(DAC_DATA); |
---|
675 | 770 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
---|
.. | .. |
---|
701 | 796 | return 0; |
---|
702 | 797 | } |
---|
703 | 798 | |
---|
704 | | -static int mga_crtc_set_plls(struct mga_device *mdev, long clock) |
---|
| 799 | +static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock) |
---|
705 | 800 | { |
---|
706 | 801 | switch(mdev->type) { |
---|
| 802 | + case G200_PCI: |
---|
| 803 | + case G200_AGP: |
---|
| 804 | + return mgag200_g200_set_plls(mdev, clock); |
---|
707 | 805 | case G200_SE_A: |
---|
708 | 806 | case G200_SE_B: |
---|
709 | 807 | return mga_g200se_set_plls(mdev, clock); |
---|
.. | .. |
---|
723 | 821 | return mga_g200er_set_plls(mdev, clock); |
---|
724 | 822 | break; |
---|
725 | 823 | } |
---|
| 824 | + |
---|
726 | 825 | return 0; |
---|
727 | 826 | } |
---|
728 | 827 | |
---|
729 | | -static void mga_g200wb_prepare(struct drm_crtc *crtc) |
---|
| 828 | +static void mgag200_g200wb_hold_bmc(struct mga_device *mdev) |
---|
730 | 829 | { |
---|
731 | | - struct mga_device *mdev = crtc->dev->dev_private; |
---|
732 | 830 | u8 tmp; |
---|
733 | 831 | int iter_max; |
---|
734 | 832 | |
---|
.. | .. |
---|
780 | 878 | } |
---|
781 | 879 | } |
---|
782 | 880 | |
---|
783 | | -static void mga_g200wb_commit(struct drm_crtc *crtc) |
---|
| 881 | +static void mgag200_g200wb_release_bmc(struct mga_device *mdev) |
---|
784 | 882 | { |
---|
785 | 883 | u8 tmp; |
---|
786 | | - struct mga_device *mdev = crtc->dev->dev_private; |
---|
787 | 884 | |
---|
788 | 885 | /* 1- The first step is to ensure that the vrsten and hrsten are set */ |
---|
789 | 886 | WREG8(MGAREG_CRTCEXT_INDEX, 1); |
---|
.. | .. |
---|
818 | 915 | } |
---|
819 | 916 | |
---|
820 | 917 | /* |
---|
821 | | - This is how the framebuffer base address is stored in g200 cards: |
---|
822 | | - * Assume @offset is the gpu_addr variable of the framebuffer object |
---|
823 | | - * Then addr is the number of _pixels_ (not bytes) from the start of |
---|
824 | | - VRAM to the first pixel we want to display. (divided by 2 for 32bit |
---|
825 | | - framebuffers) |
---|
826 | | - * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers |
---|
827 | | - addr<20> -> CRTCEXT0<6> |
---|
828 | | - addr<19-16> -> CRTCEXT0<3-0> |
---|
829 | | - addr<15-8> -> CRTCC<7-0> |
---|
830 | | - addr<7-0> -> CRTCD<7-0> |
---|
831 | | - CRTCEXT0 has to be programmed last to trigger an update and make the |
---|
832 | | - new addr variable take effect. |
---|
| 918 | + * This is how the framebuffer base address is stored in g200 cards: |
---|
| 919 | + * * Assume @offset is the gpu_addr variable of the framebuffer object |
---|
| 920 | + * * Then addr is the number of _pixels_ (not bytes) from the start of |
---|
| 921 | + * VRAM to the first pixel we want to display. (divided by 2 for 32bit |
---|
| 922 | + * framebuffers) |
---|
| 923 | + * * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers |
---|
| 924 | + * addr<20> -> CRTCEXT0<6> |
---|
| 925 | + * addr<19-16> -> CRTCEXT0<3-0> |
---|
| 926 | + * addr<15-8> -> CRTCC<7-0> |
---|
| 927 | + * addr<7-0> -> CRTCD<7-0> |
---|
| 928 | + * |
---|
| 929 | + * CRTCEXT0 has to be programmed last to trigger an update and make the |
---|
| 930 | + * new addr variable take effect. |
---|
833 | 931 | */ |
---|
834 | | -static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) |
---|
| 932 | +static void mgag200_set_startadd(struct mga_device *mdev, |
---|
| 933 | + unsigned long offset) |
---|
835 | 934 | { |
---|
836 | | - struct mga_device *mdev = crtc->dev->dev_private; |
---|
837 | | - u32 addr; |
---|
838 | | - int count; |
---|
839 | | - u8 crtcext0; |
---|
| 935 | + struct drm_device *dev = &mdev->base; |
---|
| 936 | + u32 startadd; |
---|
| 937 | + u8 crtcc, crtcd, crtcext0; |
---|
840 | 938 | |
---|
841 | | - while (RREG8(0x1fda) & 0x08); |
---|
842 | | - while (!(RREG8(0x1fda) & 0x08)); |
---|
| 939 | + startadd = offset / 8; |
---|
843 | 940 | |
---|
844 | | - count = RREG8(MGAREG_VCOUNT) + 2; |
---|
845 | | - while (RREG8(MGAREG_VCOUNT) < count); |
---|
| 941 | + /* |
---|
| 942 | + * Can't store addresses any higher than that, but we also |
---|
| 943 | + * don't have more than 16 MiB of memory, so it should be fine. |
---|
| 944 | + */ |
---|
| 945 | + drm_WARN_ON(dev, startadd > 0x1fffff); |
---|
846 | 946 | |
---|
847 | | - WREG8(MGAREG_CRTCEXT_INDEX, 0); |
---|
848 | | - crtcext0 = RREG8(MGAREG_CRTCEXT_DATA); |
---|
849 | | - crtcext0 &= 0xB0; |
---|
850 | | - addr = offset / 8; |
---|
851 | | - /* Can't store addresses any higher than that... |
---|
852 | | - but we also don't have more than 16MB of memory, so it should be fine. */ |
---|
853 | | - WARN_ON(addr > 0x1fffff); |
---|
854 | | - crtcext0 |= (!!(addr & (1<<20)))<<6; |
---|
855 | | - WREG_CRT(0x0d, (u8)(addr & 0xff)); |
---|
856 | | - WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); |
---|
857 | | - WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0); |
---|
| 947 | + RREG_ECRT(0x00, crtcext0); |
---|
| 948 | + |
---|
| 949 | + crtcc = (startadd >> 8) & 0xff; |
---|
| 950 | + crtcd = startadd & 0xff; |
---|
| 951 | + crtcext0 &= 0xb0; |
---|
| 952 | + crtcext0 |= ((startadd >> 14) & BIT(6)) | |
---|
| 953 | + ((startadd >> 16) & 0x0f); |
---|
| 954 | + |
---|
| 955 | + WREG_CRT(0x0c, crtcc); |
---|
| 956 | + WREG_CRT(0x0d, crtcd); |
---|
| 957 | + WREG_ECRT(0x00, crtcext0); |
---|
858 | 958 | } |
---|
859 | 959 | |
---|
860 | | - |
---|
861 | | -/* ast is different - we will force move buffers out of VRAM */ |
---|
862 | | -static int mga_crtc_do_set_base(struct drm_crtc *crtc, |
---|
863 | | - struct drm_framebuffer *fb, |
---|
864 | | - int x, int y, int atomic) |
---|
| 960 | +static void mgag200_set_dac_regs(struct mga_device *mdev) |
---|
865 | 961 | { |
---|
866 | | - struct mga_device *mdev = crtc->dev->dev_private; |
---|
867 | | - struct drm_gem_object *obj; |
---|
868 | | - struct mga_framebuffer *mga_fb; |
---|
869 | | - struct mgag200_bo *bo; |
---|
870 | | - int ret; |
---|
871 | | - u64 gpu_addr; |
---|
872 | | - |
---|
873 | | - /* push the previous fb to system ram */ |
---|
874 | | - if (!atomic && fb) { |
---|
875 | | - mga_fb = to_mga_framebuffer(fb); |
---|
876 | | - obj = mga_fb->obj; |
---|
877 | | - bo = gem_to_mga_bo(obj); |
---|
878 | | - ret = mgag200_bo_reserve(bo, false); |
---|
879 | | - if (ret) |
---|
880 | | - return ret; |
---|
881 | | - mgag200_bo_push_sysram(bo); |
---|
882 | | - mgag200_bo_unreserve(bo); |
---|
883 | | - } |
---|
884 | | - |
---|
885 | | - mga_fb = to_mga_framebuffer(crtc->primary->fb); |
---|
886 | | - obj = mga_fb->obj; |
---|
887 | | - bo = gem_to_mga_bo(obj); |
---|
888 | | - |
---|
889 | | - ret = mgag200_bo_reserve(bo, false); |
---|
890 | | - if (ret) |
---|
891 | | - return ret; |
---|
892 | | - |
---|
893 | | - ret = mgag200_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); |
---|
894 | | - if (ret) { |
---|
895 | | - mgag200_bo_unreserve(bo); |
---|
896 | | - return ret; |
---|
897 | | - } |
---|
898 | | - |
---|
899 | | - if (&mdev->mfbdev->mfb == mga_fb) { |
---|
900 | | - /* if pushing console in kmap it */ |
---|
901 | | - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); |
---|
902 | | - if (ret) |
---|
903 | | - DRM_ERROR("failed to kmap fbcon\n"); |
---|
904 | | - |
---|
905 | | - } |
---|
906 | | - mgag200_bo_unreserve(bo); |
---|
907 | | - |
---|
908 | | - mga_set_start_address(crtc, (u32)gpu_addr); |
---|
909 | | - |
---|
910 | | - return 0; |
---|
911 | | -} |
---|
912 | | - |
---|
913 | | -static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
---|
914 | | - struct drm_framebuffer *old_fb) |
---|
915 | | -{ |
---|
916 | | - return mga_crtc_do_set_base(crtc, old_fb, x, y, 0); |
---|
917 | | -} |
---|
918 | | - |
---|
919 | | -static int mga_crtc_mode_set(struct drm_crtc *crtc, |
---|
920 | | - struct drm_display_mode *mode, |
---|
921 | | - struct drm_display_mode *adjusted_mode, |
---|
922 | | - int x, int y, struct drm_framebuffer *old_fb) |
---|
923 | | -{ |
---|
924 | | - struct drm_device *dev = crtc->dev; |
---|
925 | | - struct mga_device *mdev = dev->dev_private; |
---|
926 | | - const struct drm_framebuffer *fb = crtc->primary->fb; |
---|
927 | | - int hdisplay, hsyncstart, hsyncend, htotal; |
---|
928 | | - int vdisplay, vsyncstart, vsyncend, vtotal; |
---|
929 | | - int pitch; |
---|
930 | | - int option = 0, option2 = 0; |
---|
931 | | - int i; |
---|
932 | | - unsigned char misc = 0; |
---|
933 | | - unsigned char ext_vga[6]; |
---|
934 | | - u8 bppshift; |
---|
935 | | - |
---|
936 | | - static unsigned char dacvalue[] = { |
---|
| 962 | + size_t i; |
---|
| 963 | + u8 dacvalue[] = { |
---|
937 | 964 | /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, |
---|
938 | 965 | /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, |
---|
939 | 966 | /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, |
---|
.. | .. |
---|
946 | 973 | /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 |
---|
947 | 974 | }; |
---|
948 | 975 | |
---|
949 | | - bppshift = mdev->bpp_shifts[fb->format->cpp[0] - 1]; |
---|
950 | | - |
---|
951 | 976 | switch (mdev->type) { |
---|
| 977 | + case G200_PCI: |
---|
| 978 | + case G200_AGP: |
---|
| 979 | + dacvalue[MGA1064_SYS_PLL_M] = 0x04; |
---|
| 980 | + dacvalue[MGA1064_SYS_PLL_N] = 0x2D; |
---|
| 981 | + dacvalue[MGA1064_SYS_PLL_P] = 0x19; |
---|
| 982 | + break; |
---|
952 | 983 | case G200_SE_A: |
---|
953 | 984 | case G200_SE_B: |
---|
954 | 985 | dacvalue[MGA1064_VREF_CTL] = 0x03; |
---|
.. | .. |
---|
956 | 987 | dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN | |
---|
957 | 988 | MGA1064_MISC_CTL_VGA8 | |
---|
958 | 989 | MGA1064_MISC_CTL_DAC_RAM_CS; |
---|
959 | | - if (mdev->has_sdram) |
---|
960 | | - option = 0x40049120; |
---|
961 | | - else |
---|
962 | | - option = 0x4004d120; |
---|
963 | | - option2 = 0x00008000; |
---|
964 | 990 | break; |
---|
965 | 991 | case G200_WB: |
---|
966 | 992 | case G200_EW3: |
---|
967 | 993 | dacvalue[MGA1064_VREF_CTL] = 0x07; |
---|
968 | | - option = 0x41049120; |
---|
969 | | - option2 = 0x0000b000; |
---|
970 | 994 | break; |
---|
971 | 995 | case G200_EV: |
---|
972 | 996 | dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL; |
---|
973 | 997 | dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | |
---|
974 | 998 | MGA1064_MISC_CTL_DAC_RAM_CS; |
---|
975 | | - option = 0x00000120; |
---|
976 | | - option2 = 0x0000b000; |
---|
977 | 999 | break; |
---|
978 | 1000 | case G200_EH: |
---|
979 | 1001 | case G200_EH3: |
---|
980 | 1002 | dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | |
---|
981 | 1003 | MGA1064_MISC_CTL_DAC_RAM_CS; |
---|
982 | | - option = 0x00000120; |
---|
983 | | - option2 = 0x0000b000; |
---|
984 | 1004 | break; |
---|
985 | 1005 | case G200_ER: |
---|
986 | 1006 | break; |
---|
987 | 1007 | } |
---|
988 | 1008 | |
---|
989 | | - switch (fb->format->cpp[0] * 8) { |
---|
990 | | - case 8: |
---|
991 | | - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits; |
---|
992 | | - break; |
---|
993 | | - case 16: |
---|
994 | | - if (fb->format->depth == 15) |
---|
995 | | - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits; |
---|
996 | | - else |
---|
997 | | - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits; |
---|
998 | | - break; |
---|
999 | | - case 24: |
---|
1000 | | - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_24bits; |
---|
1001 | | - break; |
---|
1002 | | - case 32: |
---|
1003 | | - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_32_24bits; |
---|
1004 | | - break; |
---|
1005 | | - } |
---|
1006 | | - |
---|
1007 | | - if (mode->flags & DRM_MODE_FLAG_NHSYNC) |
---|
1008 | | - misc |= 0x40; |
---|
1009 | | - if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
---|
1010 | | - misc |= 0x80; |
---|
1011 | | - |
---|
1012 | | - |
---|
1013 | | - for (i = 0; i < sizeof(dacvalue); i++) { |
---|
| 1009 | + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { |
---|
1014 | 1010 | if ((i <= 0x17) || |
---|
1015 | 1011 | (i == 0x1b) || |
---|
1016 | 1012 | (i == 0x1c) || |
---|
.. | .. |
---|
1033 | 1029 | |
---|
1034 | 1030 | if (mdev->type == G200_ER) |
---|
1035 | 1031 | WREG_DAC(0x90, 0); |
---|
| 1032 | +} |
---|
1036 | 1033 | |
---|
1037 | | - if (option) |
---|
1038 | | - pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option); |
---|
1039 | | - if (option2) |
---|
1040 | | - pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2); |
---|
| 1034 | +static void mgag200_init_regs(struct mga_device *mdev) |
---|
| 1035 | +{ |
---|
| 1036 | + u8 crtc11, misc; |
---|
1041 | 1037 | |
---|
1042 | | - WREG_SEQ(2, 0xf); |
---|
1043 | | - WREG_SEQ(3, 0); |
---|
1044 | | - WREG_SEQ(4, 0xe); |
---|
| 1038 | + mgag200_set_dac_regs(mdev); |
---|
1045 | 1039 | |
---|
1046 | | - pitch = fb->pitches[0] / fb->format->cpp[0]; |
---|
1047 | | - if (fb->format->cpp[0] * 8 == 24) |
---|
1048 | | - pitch = (pitch * 3) >> (4 - bppshift); |
---|
1049 | | - else |
---|
1050 | | - pitch = pitch >> (4 - bppshift); |
---|
| 1040 | + WREG_SEQ(2, 0x0f); |
---|
| 1041 | + WREG_SEQ(3, 0x00); |
---|
| 1042 | + WREG_SEQ(4, 0x0e); |
---|
| 1043 | + |
---|
| 1044 | + WREG_CRT(10, 0); |
---|
| 1045 | + WREG_CRT(11, 0); |
---|
| 1046 | + WREG_CRT(12, 0); |
---|
| 1047 | + WREG_CRT(13, 0); |
---|
| 1048 | + WREG_CRT(14, 0); |
---|
| 1049 | + WREG_CRT(15, 0); |
---|
| 1050 | + |
---|
| 1051 | + RREG_CRT(0x11, crtc11); |
---|
| 1052 | + crtc11 &= ~(MGAREG_CRTC11_CRTCPROTECT | |
---|
| 1053 | + MGAREG_CRTC11_VINTEN | |
---|
| 1054 | + MGAREG_CRTC11_VINTCLR); |
---|
| 1055 | + WREG_CRT(0x11, crtc11); |
---|
| 1056 | + |
---|
| 1057 | + if (mdev->type == G200_ER) |
---|
| 1058 | + WREG_ECRT(0x24, 0x5); |
---|
| 1059 | + |
---|
| 1060 | + if (mdev->type == G200_EW3) |
---|
| 1061 | + WREG_ECRT(0x34, 0x5); |
---|
| 1062 | + |
---|
| 1063 | + misc = RREG8(MGA_MISC_IN); |
---|
| 1064 | + misc |= MGAREG_MISC_IOADSEL; |
---|
| 1065 | + WREG8(MGA_MISC_OUT, misc); |
---|
| 1066 | +} |
---|
| 1067 | + |
---|
| 1068 | +static void mgag200_set_mode_regs(struct mga_device *mdev, |
---|
| 1069 | + const struct drm_display_mode *mode) |
---|
| 1070 | +{ |
---|
| 1071 | + unsigned int hdisplay, hsyncstart, hsyncend, htotal; |
---|
| 1072 | + unsigned int vdisplay, vsyncstart, vsyncend, vtotal; |
---|
| 1073 | + u8 misc, crtcext1, crtcext2, crtcext5; |
---|
1051 | 1074 | |
---|
1052 | 1075 | hdisplay = mode->hdisplay / 8 - 1; |
---|
1053 | 1076 | hsyncstart = mode->hsync_start / 8 - 1; |
---|
.. | .. |
---|
1063 | 1086 | vsyncend = mode->vsync_end - 1; |
---|
1064 | 1087 | vtotal = mode->vtotal - 2; |
---|
1065 | 1088 | |
---|
1066 | | - WREG_GFX(0, 0); |
---|
1067 | | - WREG_GFX(1, 0); |
---|
1068 | | - WREG_GFX(2, 0); |
---|
1069 | | - WREG_GFX(3, 0); |
---|
1070 | | - WREG_GFX(4, 0); |
---|
1071 | | - WREG_GFX(5, 0x40); |
---|
1072 | | - WREG_GFX(6, 0x5); |
---|
1073 | | - WREG_GFX(7, 0xf); |
---|
1074 | | - WREG_GFX(8, 0xf); |
---|
| 1089 | + misc = RREG8(MGA_MISC_IN); |
---|
| 1090 | + |
---|
| 1091 | + if (mode->flags & DRM_MODE_FLAG_NHSYNC) |
---|
| 1092 | + misc |= MGAREG_MISC_HSYNCPOL; |
---|
| 1093 | + else |
---|
| 1094 | + misc &= ~MGAREG_MISC_HSYNCPOL; |
---|
| 1095 | + |
---|
| 1096 | + if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
---|
| 1097 | + misc |= MGAREG_MISC_VSYNCPOL; |
---|
| 1098 | + else |
---|
| 1099 | + misc &= ~MGAREG_MISC_VSYNCPOL; |
---|
| 1100 | + |
---|
| 1101 | + crtcext1 = (((htotal - 4) & 0x100) >> 8) | |
---|
| 1102 | + ((hdisplay & 0x100) >> 7) | |
---|
| 1103 | + ((hsyncstart & 0x100) >> 6) | |
---|
| 1104 | + (htotal & 0x40); |
---|
| 1105 | + if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
| 1106 | + crtcext1 |= BIT(7) | /* vrsten */ |
---|
| 1107 | + BIT(3); /* hrsten */ |
---|
| 1108 | + |
---|
| 1109 | + crtcext2 = ((vtotal & 0xc00) >> 10) | |
---|
| 1110 | + ((vdisplay & 0x400) >> 8) | |
---|
| 1111 | + ((vdisplay & 0xc00) >> 7) | |
---|
| 1112 | + ((vsyncstart & 0xc00) >> 5) | |
---|
| 1113 | + ((vdisplay & 0x400) >> 3); |
---|
| 1114 | + crtcext5 = 0x00; |
---|
1075 | 1115 | |
---|
1076 | 1116 | WREG_CRT(0, htotal - 4); |
---|
1077 | 1117 | WREG_CRT(1, hdisplay); |
---|
.. | .. |
---|
1085 | 1125 | ((vsyncstart & 0x100) >> 6) | |
---|
1086 | 1126 | ((vdisplay & 0x100) >> 5) | |
---|
1087 | 1127 | ((vdisplay & 0x100) >> 4) | /* linecomp */ |
---|
1088 | | - ((vtotal & 0x200) >> 4)| |
---|
| 1128 | + ((vtotal & 0x200) >> 4) | |
---|
1089 | 1129 | ((vdisplay & 0x200) >> 3) | |
---|
1090 | 1130 | ((vsyncstart & 0x200) >> 2)); |
---|
1091 | 1131 | WREG_CRT(9, ((vdisplay & 0x200) >> 4) | |
---|
1092 | 1132 | ((vdisplay & 0x200) >> 3)); |
---|
1093 | | - WREG_CRT(10, 0); |
---|
1094 | | - WREG_CRT(11, 0); |
---|
1095 | | - WREG_CRT(12, 0); |
---|
1096 | | - WREG_CRT(13, 0); |
---|
1097 | | - WREG_CRT(14, 0); |
---|
1098 | | - WREG_CRT(15, 0); |
---|
1099 | 1133 | WREG_CRT(16, vsyncstart & 0xFF); |
---|
1100 | 1134 | WREG_CRT(17, (vsyncend & 0x0F) | 0x20); |
---|
1101 | 1135 | WREG_CRT(18, vdisplay & 0xFF); |
---|
1102 | | - WREG_CRT(19, pitch & 0xFF); |
---|
1103 | 1136 | WREG_CRT(20, 0); |
---|
1104 | 1137 | WREG_CRT(21, vdisplay & 0xFF); |
---|
1105 | 1138 | WREG_CRT(22, (vtotal + 1) & 0xFF); |
---|
1106 | 1139 | WREG_CRT(23, 0xc3); |
---|
1107 | 1140 | WREG_CRT(24, vdisplay & 0xFF); |
---|
1108 | 1141 | |
---|
1109 | | - ext_vga[0] = 0; |
---|
1110 | | - ext_vga[5] = 0; |
---|
| 1142 | + WREG_ECRT(0x01, crtcext1); |
---|
| 1143 | + WREG_ECRT(0x02, crtcext2); |
---|
| 1144 | + WREG_ECRT(0x05, crtcext5); |
---|
1111 | 1145 | |
---|
1112 | | - /* TODO interlace */ |
---|
| 1146 | + WREG8(MGA_MISC_OUT, misc); |
---|
| 1147 | +} |
---|
1113 | 1148 | |
---|
1114 | | - ext_vga[0] |= (pitch & 0x300) >> 4; |
---|
1115 | | - ext_vga[1] = (((htotal - 4) & 0x100) >> 8) | |
---|
1116 | | - ((hdisplay & 0x100) >> 7) | |
---|
1117 | | - ((hsyncstart & 0x100) >> 6) | |
---|
1118 | | - (htotal & 0x40); |
---|
1119 | | - ext_vga[2] = ((vtotal & 0xc00) >> 10) | |
---|
1120 | | - ((vdisplay & 0x400) >> 8) | |
---|
1121 | | - ((vdisplay & 0xc00) >> 7) | |
---|
1122 | | - ((vsyncstart & 0xc00) >> 5) | |
---|
1123 | | - ((vdisplay & 0x400) >> 3); |
---|
| 1149 | +static u8 mgag200_get_bpp_shift(struct mga_device *mdev, |
---|
| 1150 | + const struct drm_format_info *format) |
---|
| 1151 | +{ |
---|
| 1152 | + return mdev->bpp_shifts[format->cpp[0] - 1]; |
---|
| 1153 | +} |
---|
| 1154 | + |
---|
| 1155 | +/* |
---|
| 1156 | + * Calculates the HW offset value from the framebuffer's pitch. The |
---|
| 1157 | + * offset is a multiple of the pixel size and depends on the display |
---|
| 1158 | + * format. |
---|
| 1159 | + */ |
---|
| 1160 | +static u32 mgag200_calculate_offset(struct mga_device *mdev, |
---|
| 1161 | + const struct drm_framebuffer *fb) |
---|
| 1162 | +{ |
---|
| 1163 | + u32 offset = fb->pitches[0] / fb->format->cpp[0]; |
---|
| 1164 | + u8 bppshift = mgag200_get_bpp_shift(mdev, fb->format); |
---|
| 1165 | + |
---|
1124 | 1166 | if (fb->format->cpp[0] * 8 == 24) |
---|
1125 | | - ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80; |
---|
| 1167 | + offset = (offset * 3) >> (4 - bppshift); |
---|
1126 | 1168 | else |
---|
1127 | | - ext_vga[3] = ((1 << bppshift) - 1) | 0x80; |
---|
1128 | | - ext_vga[4] = 0; |
---|
1129 | | - if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
1130 | | - ext_vga[1] |= 0x88; |
---|
| 1169 | + offset = offset >> (4 - bppshift); |
---|
1131 | 1170 | |
---|
1132 | | - /* Set pixel clocks */ |
---|
1133 | | - misc = 0x2d; |
---|
1134 | | - WREG8(MGA_MISC_OUT, misc); |
---|
1135 | | - |
---|
1136 | | - mga_crtc_set_plls(mdev, mode->clock); |
---|
1137 | | - |
---|
1138 | | - for (i = 0; i < 6; i++) { |
---|
1139 | | - WREG_ECRT(i, ext_vga[i]); |
---|
1140 | | - } |
---|
1141 | | - |
---|
1142 | | - if (mdev->type == G200_ER) |
---|
1143 | | - WREG_ECRT(0x24, 0x5); |
---|
1144 | | - |
---|
1145 | | - if (mdev->type == G200_EW3) |
---|
1146 | | - WREG_ECRT(0x34, 0x5); |
---|
1147 | | - |
---|
1148 | | - if (mdev->type == G200_EV) { |
---|
1149 | | - WREG_ECRT(6, 0); |
---|
1150 | | - } |
---|
1151 | | - |
---|
1152 | | - WREG_ECRT(0, ext_vga[0]); |
---|
1153 | | - /* Enable mga pixel clock */ |
---|
1154 | | - misc = 0x2d; |
---|
1155 | | - |
---|
1156 | | - WREG8(MGA_MISC_OUT, misc); |
---|
1157 | | - |
---|
1158 | | - if (adjusted_mode) |
---|
1159 | | - memcpy(&mdev->mode, mode, sizeof(struct drm_display_mode)); |
---|
1160 | | - |
---|
1161 | | - mga_crtc_do_set_base(crtc, old_fb, x, y, 0); |
---|
1162 | | - |
---|
1163 | | - /* reset tagfifo */ |
---|
1164 | | - if (mdev->type == G200_ER) { |
---|
1165 | | - u32 mem_ctl = RREG32(MGAREG_MEMCTL); |
---|
1166 | | - u8 seq1; |
---|
1167 | | - |
---|
1168 | | - /* screen off */ |
---|
1169 | | - WREG8(MGAREG_SEQ_INDEX, 0x01); |
---|
1170 | | - seq1 = RREG8(MGAREG_SEQ_DATA) | 0x20; |
---|
1171 | | - WREG8(MGAREG_SEQ_DATA, seq1); |
---|
1172 | | - |
---|
1173 | | - WREG32(MGAREG_MEMCTL, mem_ctl | 0x00200000); |
---|
1174 | | - udelay(1000); |
---|
1175 | | - WREG32(MGAREG_MEMCTL, mem_ctl & ~0x00200000); |
---|
1176 | | - |
---|
1177 | | - WREG8(MGAREG_SEQ_DATA, seq1 & ~0x20); |
---|
1178 | | - } |
---|
1179 | | - |
---|
1180 | | - |
---|
1181 | | - if (IS_G200_SE(mdev)) { |
---|
1182 | | - if (mdev->unique_rev_id >= 0x04) { |
---|
1183 | | - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); |
---|
1184 | | - WREG8(MGAREG_CRTCEXT_DATA, 0); |
---|
1185 | | - } else if (mdev->unique_rev_id >= 0x02) { |
---|
1186 | | - u8 hi_pri_lvl; |
---|
1187 | | - u32 bpp; |
---|
1188 | | - u32 mb; |
---|
1189 | | - |
---|
1190 | | - if (fb->format->cpp[0] * 8 > 16) |
---|
1191 | | - bpp = 32; |
---|
1192 | | - else if (fb->format->cpp[0] * 8 > 8) |
---|
1193 | | - bpp = 16; |
---|
1194 | | - else |
---|
1195 | | - bpp = 8; |
---|
1196 | | - |
---|
1197 | | - mb = (mode->clock * bpp) / 1000; |
---|
1198 | | - if (mb > 3100) |
---|
1199 | | - hi_pri_lvl = 0; |
---|
1200 | | - else if (mb > 2600) |
---|
1201 | | - hi_pri_lvl = 1; |
---|
1202 | | - else if (mb > 1900) |
---|
1203 | | - hi_pri_lvl = 2; |
---|
1204 | | - else if (mb > 1160) |
---|
1205 | | - hi_pri_lvl = 3; |
---|
1206 | | - else if (mb > 440) |
---|
1207 | | - hi_pri_lvl = 4; |
---|
1208 | | - else |
---|
1209 | | - hi_pri_lvl = 5; |
---|
1210 | | - |
---|
1211 | | - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); |
---|
1212 | | - WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); |
---|
1213 | | - } else { |
---|
1214 | | - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); |
---|
1215 | | - if (mdev->unique_rev_id >= 0x01) |
---|
1216 | | - WREG8(MGAREG_CRTCEXT_DATA, 0x03); |
---|
1217 | | - else |
---|
1218 | | - WREG8(MGAREG_CRTCEXT_DATA, 0x04); |
---|
1219 | | - } |
---|
1220 | | - } |
---|
1221 | | - return 0; |
---|
| 1171 | + return offset; |
---|
1222 | 1172 | } |
---|
1223 | 1173 | |
---|
1224 | | -#if 0 /* code from mjg to attempt D3 on crtc dpms off - revisit later */ |
---|
1225 | | -static int mga_suspend(struct drm_crtc *crtc) |
---|
| 1174 | +static void mgag200_set_offset(struct mga_device *mdev, |
---|
| 1175 | + const struct drm_framebuffer *fb) |
---|
1226 | 1176 | { |
---|
1227 | | - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); |
---|
1228 | | - struct drm_device *dev = crtc->dev; |
---|
1229 | | - struct mga_device *mdev = dev->dev_private; |
---|
1230 | | - struct pci_dev *pdev = dev->pdev; |
---|
1231 | | - int option; |
---|
| 1177 | + u8 crtc13, crtcext0; |
---|
| 1178 | + u32 offset = mgag200_calculate_offset(mdev, fb); |
---|
1232 | 1179 | |
---|
1233 | | - if (mdev->suspended) |
---|
1234 | | - return 0; |
---|
| 1180 | + RREG_ECRT(0, crtcext0); |
---|
1235 | 1181 | |
---|
1236 | | - WREG_SEQ(1, 0x20); |
---|
1237 | | - WREG_ECRT(1, 0x30); |
---|
1238 | | - /* Disable the pixel clock */ |
---|
1239 | | - WREG_DAC(0x1a, 0x05); |
---|
1240 | | - /* Power down the DAC */ |
---|
1241 | | - WREG_DAC(0x1e, 0x18); |
---|
1242 | | - /* Power down the pixel PLL */ |
---|
1243 | | - WREG_DAC(0x1a, 0x0d); |
---|
| 1182 | + crtc13 = offset & 0xff; |
---|
1244 | 1183 | |
---|
1245 | | - /* Disable PLLs and clocks */ |
---|
1246 | | - pci_read_config_dword(pdev, PCI_MGA_OPTION, &option); |
---|
1247 | | - option &= ~(0x1F8024); |
---|
1248 | | - pci_write_config_dword(pdev, PCI_MGA_OPTION, option); |
---|
1249 | | - pci_set_power_state(pdev, PCI_D3hot); |
---|
1250 | | - pci_disable_device(pdev); |
---|
| 1184 | + crtcext0 &= ~MGAREG_CRTCEXT0_OFFSET_MASK; |
---|
| 1185 | + crtcext0 |= (offset >> 4) & MGAREG_CRTCEXT0_OFFSET_MASK; |
---|
1251 | 1186 | |
---|
1252 | | - mdev->suspended = true; |
---|
1253 | | - |
---|
1254 | | - return 0; |
---|
| 1187 | + WREG_CRT(0x13, crtc13); |
---|
| 1188 | + WREG_ECRT(0x00, crtcext0); |
---|
1255 | 1189 | } |
---|
1256 | 1190 | |
---|
1257 | | -static int mga_resume(struct drm_crtc *crtc) |
---|
| 1191 | +static void mgag200_set_format_regs(struct mga_device *mdev, |
---|
| 1192 | + const struct drm_framebuffer *fb) |
---|
1258 | 1193 | { |
---|
1259 | | - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); |
---|
1260 | | - struct drm_device *dev = crtc->dev; |
---|
1261 | | - struct mga_device *mdev = dev->dev_private; |
---|
1262 | | - struct pci_dev *pdev = dev->pdev; |
---|
1263 | | - int option; |
---|
| 1194 | + struct drm_device *dev = &mdev->base; |
---|
| 1195 | + const struct drm_format_info *format = fb->format; |
---|
| 1196 | + unsigned int bpp, bppshift, scale; |
---|
| 1197 | + u8 crtcext3, xmulctrl; |
---|
1264 | 1198 | |
---|
1265 | | - if (!mdev->suspended) |
---|
1266 | | - return 0; |
---|
| 1199 | + bpp = format->cpp[0] * 8; |
---|
1267 | 1200 | |
---|
1268 | | - pci_set_power_state(pdev, PCI_D0); |
---|
1269 | | - pci_enable_device(pdev); |
---|
1270 | | - |
---|
1271 | | - /* Disable sysclk */ |
---|
1272 | | - pci_read_config_dword(pdev, PCI_MGA_OPTION, &option); |
---|
1273 | | - option &= ~(0x4); |
---|
1274 | | - pci_write_config_dword(pdev, PCI_MGA_OPTION, option); |
---|
1275 | | - |
---|
1276 | | - mdev->suspended = false; |
---|
1277 | | - |
---|
1278 | | - return 0; |
---|
1279 | | -} |
---|
1280 | | - |
---|
1281 | | -#endif |
---|
1282 | | - |
---|
1283 | | -static void mga_crtc_dpms(struct drm_crtc *crtc, int mode) |
---|
1284 | | -{ |
---|
1285 | | - struct drm_device *dev = crtc->dev; |
---|
1286 | | - struct mga_device *mdev = dev->dev_private; |
---|
1287 | | - u8 seq1 = 0, crtcext1 = 0; |
---|
1288 | | - |
---|
1289 | | - switch (mode) { |
---|
1290 | | - case DRM_MODE_DPMS_ON: |
---|
1291 | | - seq1 = 0; |
---|
1292 | | - crtcext1 = 0; |
---|
1293 | | - mga_crtc_load_lut(crtc); |
---|
| 1201 | + bppshift = mgag200_get_bpp_shift(mdev, format); |
---|
| 1202 | + switch (bpp) { |
---|
| 1203 | + case 24: |
---|
| 1204 | + scale = ((1 << bppshift) * 3) - 1; |
---|
1294 | 1205 | break; |
---|
1295 | | - case DRM_MODE_DPMS_STANDBY: |
---|
1296 | | - seq1 = 0x20; |
---|
1297 | | - crtcext1 = 0x10; |
---|
1298 | | - break; |
---|
1299 | | - case DRM_MODE_DPMS_SUSPEND: |
---|
1300 | | - seq1 = 0x20; |
---|
1301 | | - crtcext1 = 0x20; |
---|
1302 | | - break; |
---|
1303 | | - case DRM_MODE_DPMS_OFF: |
---|
1304 | | - seq1 = 0x20; |
---|
1305 | | - crtcext1 = 0x30; |
---|
| 1206 | + default: |
---|
| 1207 | + scale = (1 << bppshift) - 1; |
---|
1306 | 1208 | break; |
---|
1307 | 1209 | } |
---|
1308 | 1210 | |
---|
1309 | | -#if 0 |
---|
1310 | | - if (mode == DRM_MODE_DPMS_OFF) { |
---|
1311 | | - mga_suspend(crtc); |
---|
| 1211 | + RREG_ECRT(3, crtcext3); |
---|
| 1212 | + |
---|
| 1213 | + switch (bpp) { |
---|
| 1214 | + case 8: |
---|
| 1215 | + xmulctrl = MGA1064_MUL_CTL_8bits; |
---|
| 1216 | + break; |
---|
| 1217 | + case 16: |
---|
| 1218 | + if (format->depth == 15) |
---|
| 1219 | + xmulctrl = MGA1064_MUL_CTL_15bits; |
---|
| 1220 | + else |
---|
| 1221 | + xmulctrl = MGA1064_MUL_CTL_16bits; |
---|
| 1222 | + break; |
---|
| 1223 | + case 24: |
---|
| 1224 | + xmulctrl = MGA1064_MUL_CTL_24bits; |
---|
| 1225 | + break; |
---|
| 1226 | + case 32: |
---|
| 1227 | + xmulctrl = MGA1064_MUL_CTL_32_24bits; |
---|
| 1228 | + break; |
---|
| 1229 | + default: |
---|
| 1230 | + /* BUG: We should have caught this problem already. */ |
---|
| 1231 | + drm_WARN_ON(dev, "invalid format depth\n"); |
---|
| 1232 | + return; |
---|
1312 | 1233 | } |
---|
1313 | | -#endif |
---|
1314 | | - WREG8(MGAREG_SEQ_INDEX, 0x01); |
---|
1315 | | - seq1 |= RREG8(MGAREG_SEQ_DATA) & ~0x20; |
---|
| 1234 | + |
---|
| 1235 | + crtcext3 &= ~GENMASK(2, 0); |
---|
| 1236 | + crtcext3 |= scale; |
---|
| 1237 | + |
---|
| 1238 | + WREG_DAC(MGA1064_MUL_CTL, xmulctrl); |
---|
| 1239 | + |
---|
| 1240 | + WREG_GFX(0, 0x00); |
---|
| 1241 | + WREG_GFX(1, 0x00); |
---|
| 1242 | + WREG_GFX(2, 0x00); |
---|
| 1243 | + WREG_GFX(3, 0x00); |
---|
| 1244 | + WREG_GFX(4, 0x00); |
---|
| 1245 | + WREG_GFX(5, 0x40); |
---|
| 1246 | + /* GCTL6 should be 0x05, but we configure memmapsl to 0xb8000 (text mode), |
---|
| 1247 | + * so that it doesn't hang when running kexec/kdump on G200_SE rev42. |
---|
| 1248 | + */ |
---|
| 1249 | + WREG_GFX(6, 0x0d); |
---|
| 1250 | + WREG_GFX(7, 0x0f); |
---|
| 1251 | + WREG_GFX(8, 0x0f); |
---|
| 1252 | + |
---|
| 1253 | + WREG_ECRT(3, crtcext3); |
---|
| 1254 | +} |
---|
| 1255 | + |
---|
| 1256 | +static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) |
---|
| 1257 | +{ |
---|
| 1258 | + static uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */ |
---|
| 1259 | + u32 memctl; |
---|
| 1260 | + |
---|
| 1261 | + memctl = RREG32(MGAREG_MEMCTL); |
---|
| 1262 | + |
---|
| 1263 | + memctl |= RESET_FLAG; |
---|
| 1264 | + WREG32(MGAREG_MEMCTL, memctl); |
---|
| 1265 | + |
---|
| 1266 | + udelay(1000); |
---|
| 1267 | + |
---|
| 1268 | + memctl &= ~RESET_FLAG; |
---|
| 1269 | + WREG32(MGAREG_MEMCTL, memctl); |
---|
| 1270 | +} |
---|
| 1271 | + |
---|
| 1272 | +static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, |
---|
| 1273 | + const struct drm_display_mode *mode, |
---|
| 1274 | + const struct drm_framebuffer *fb) |
---|
| 1275 | +{ |
---|
| 1276 | + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; |
---|
| 1277 | + unsigned int hiprilvl; |
---|
| 1278 | + u8 crtcext6; |
---|
| 1279 | + |
---|
| 1280 | + if (unique_rev_id >= 0x04) { |
---|
| 1281 | + hiprilvl = 0; |
---|
| 1282 | + } else if (unique_rev_id >= 0x02) { |
---|
| 1283 | + unsigned int bpp; |
---|
| 1284 | + unsigned long mb; |
---|
| 1285 | + |
---|
| 1286 | + if (fb->format->cpp[0] * 8 > 16) |
---|
| 1287 | + bpp = 32; |
---|
| 1288 | + else if (fb->format->cpp[0] * 8 > 8) |
---|
| 1289 | + bpp = 16; |
---|
| 1290 | + else |
---|
| 1291 | + bpp = 8; |
---|
| 1292 | + |
---|
| 1293 | + mb = (mode->clock * bpp) / 1000; |
---|
| 1294 | + if (mb > 3100) |
---|
| 1295 | + hiprilvl = 0; |
---|
| 1296 | + else if (mb > 2600) |
---|
| 1297 | + hiprilvl = 1; |
---|
| 1298 | + else if (mb > 1900) |
---|
| 1299 | + hiprilvl = 2; |
---|
| 1300 | + else if (mb > 1160) |
---|
| 1301 | + hiprilvl = 3; |
---|
| 1302 | + else if (mb > 440) |
---|
| 1303 | + hiprilvl = 4; |
---|
| 1304 | + else |
---|
| 1305 | + hiprilvl = 5; |
---|
| 1306 | + |
---|
| 1307 | + } else if (unique_rev_id >= 0x01) { |
---|
| 1308 | + hiprilvl = 3; |
---|
| 1309 | + } else { |
---|
| 1310 | + hiprilvl = 4; |
---|
| 1311 | + } |
---|
| 1312 | + |
---|
| 1313 | + crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */ |
---|
| 1314 | + |
---|
| 1315 | + WREG_ECRT(0x06, crtcext6); |
---|
| 1316 | +} |
---|
| 1317 | + |
---|
| 1318 | +static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) |
---|
| 1319 | +{ |
---|
| 1320 | + WREG_ECRT(0x06, 0x00); |
---|
| 1321 | +} |
---|
| 1322 | + |
---|
| 1323 | +static void mgag200_enable_display(struct mga_device *mdev) |
---|
| 1324 | +{ |
---|
| 1325 | + u8 seq0, seq1, crtcext1; |
---|
| 1326 | + |
---|
| 1327 | + RREG_SEQ(0x00, seq0); |
---|
| 1328 | + seq0 |= MGAREG_SEQ0_SYNCRST | |
---|
| 1329 | + MGAREG_SEQ0_ASYNCRST; |
---|
| 1330 | + WREG_SEQ(0x00, seq0); |
---|
| 1331 | + |
---|
| 1332 | + /* |
---|
| 1333 | + * TODO: replace busy waiting with vblank IRQ; put |
---|
| 1334 | + * msleep(50) before changing SCROFF |
---|
| 1335 | + */ |
---|
1316 | 1336 | mga_wait_vsync(mdev); |
---|
1317 | 1337 | mga_wait_busy(mdev); |
---|
1318 | | - WREG8(MGAREG_SEQ_DATA, seq1); |
---|
| 1338 | + |
---|
| 1339 | + RREG_SEQ(0x01, seq1); |
---|
| 1340 | + seq1 &= ~MGAREG_SEQ1_SCROFF; |
---|
| 1341 | + WREG_SEQ(0x01, seq1); |
---|
| 1342 | + |
---|
1319 | 1343 | msleep(20); |
---|
1320 | | - WREG8(MGAREG_CRTCEXT_INDEX, 0x01); |
---|
1321 | | - crtcext1 |= RREG8(MGAREG_CRTCEXT_DATA) & ~0x30; |
---|
1322 | | - WREG8(MGAREG_CRTCEXT_DATA, crtcext1); |
---|
1323 | 1344 | |
---|
1324 | | -#if 0 |
---|
1325 | | - if (mode == DRM_MODE_DPMS_ON && mdev->suspended == true) { |
---|
1326 | | - mga_resume(crtc); |
---|
1327 | | - drm_helper_resume_force_mode(dev); |
---|
1328 | | - } |
---|
1329 | | -#endif |
---|
| 1345 | + RREG_ECRT(0x01, crtcext1); |
---|
| 1346 | + crtcext1 &= ~MGAREG_CRTCEXT1_VSYNCOFF; |
---|
| 1347 | + crtcext1 &= ~MGAREG_CRTCEXT1_HSYNCOFF; |
---|
| 1348 | + WREG_ECRT(0x01, crtcext1); |
---|
| 1349 | +} |
---|
| 1350 | + |
---|
| 1351 | +static void mgag200_disable_display(struct mga_device *mdev) |
---|
| 1352 | +{ |
---|
| 1353 | + u8 seq0, seq1, crtcext1; |
---|
| 1354 | + |
---|
| 1355 | + RREG_SEQ(0x00, seq0); |
---|
| 1356 | + seq0 &= ~MGAREG_SEQ0_SYNCRST; |
---|
| 1357 | + WREG_SEQ(0x00, seq0); |
---|
| 1358 | + |
---|
| 1359 | + /* |
---|
| 1360 | + * TODO: replace busy waiting with vblank IRQ; put |
---|
| 1361 | + * msleep(50) before changing SCROFF |
---|
| 1362 | + */ |
---|
| 1363 | + mga_wait_vsync(mdev); |
---|
| 1364 | + mga_wait_busy(mdev); |
---|
| 1365 | + |
---|
| 1366 | + RREG_SEQ(0x01, seq1); |
---|
| 1367 | + seq1 |= MGAREG_SEQ1_SCROFF; |
---|
| 1368 | + WREG_SEQ(0x01, seq1); |
---|
| 1369 | + |
---|
| 1370 | + msleep(20); |
---|
| 1371 | + |
---|
| 1372 | + RREG_ECRT(0x01, crtcext1); |
---|
| 1373 | + crtcext1 |= MGAREG_CRTCEXT1_VSYNCOFF | |
---|
| 1374 | + MGAREG_CRTCEXT1_HSYNCOFF; |
---|
| 1375 | + WREG_ECRT(0x01, crtcext1); |
---|
1330 | 1376 | } |
---|
1331 | 1377 | |
---|
1332 | 1378 | /* |
---|
1333 | | - * This is called before a mode is programmed. A typical use might be to |
---|
1334 | | - * enable DPMS during the programming to avoid seeing intermediate stages, |
---|
1335 | | - * but that's not relevant to us |
---|
| 1379 | + * Connector |
---|
1336 | 1380 | */ |
---|
1337 | | -static void mga_crtc_prepare(struct drm_crtc *crtc) |
---|
1338 | | -{ |
---|
1339 | | - struct drm_device *dev = crtc->dev; |
---|
1340 | | - struct mga_device *mdev = dev->dev_private; |
---|
1341 | | - u8 tmp; |
---|
1342 | | - |
---|
1343 | | - /* mga_resume(crtc);*/ |
---|
1344 | | - |
---|
1345 | | - WREG8(MGAREG_CRTC_INDEX, 0x11); |
---|
1346 | | - tmp = RREG8(MGAREG_CRTC_DATA); |
---|
1347 | | - WREG_CRT(0x11, tmp | 0x80); |
---|
1348 | | - |
---|
1349 | | - if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) { |
---|
1350 | | - WREG_SEQ(0, 1); |
---|
1351 | | - msleep(50); |
---|
1352 | | - WREG_SEQ(1, 0x20); |
---|
1353 | | - msleep(20); |
---|
1354 | | - } else { |
---|
1355 | | - WREG8(MGAREG_SEQ_INDEX, 0x1); |
---|
1356 | | - tmp = RREG8(MGAREG_SEQ_DATA); |
---|
1357 | | - |
---|
1358 | | - /* start sync reset */ |
---|
1359 | | - WREG_SEQ(0, 1); |
---|
1360 | | - WREG_SEQ(1, tmp | 0x20); |
---|
1361 | | - } |
---|
1362 | | - |
---|
1363 | | - if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
1364 | | - mga_g200wb_prepare(crtc); |
---|
1365 | | - |
---|
1366 | | - WREG_CRT(17, 0); |
---|
1367 | | -} |
---|
1368 | | - |
---|
1369 | | -/* |
---|
1370 | | - * This is called after a mode is programmed. It should reverse anything done |
---|
1371 | | - * by the prepare function |
---|
1372 | | - */ |
---|
1373 | | -static void mga_crtc_commit(struct drm_crtc *crtc) |
---|
1374 | | -{ |
---|
1375 | | - struct drm_device *dev = crtc->dev; |
---|
1376 | | - struct mga_device *mdev = dev->dev_private; |
---|
1377 | | - const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
---|
1378 | | - u8 tmp; |
---|
1379 | | - |
---|
1380 | | - if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
1381 | | - mga_g200wb_commit(crtc); |
---|
1382 | | - |
---|
1383 | | - if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) { |
---|
1384 | | - msleep(50); |
---|
1385 | | - WREG_SEQ(1, 0x0); |
---|
1386 | | - msleep(20); |
---|
1387 | | - WREG_SEQ(0, 0x3); |
---|
1388 | | - } else { |
---|
1389 | | - WREG8(MGAREG_SEQ_INDEX, 0x1); |
---|
1390 | | - tmp = RREG8(MGAREG_SEQ_DATA); |
---|
1391 | | - |
---|
1392 | | - tmp &= ~0x20; |
---|
1393 | | - WREG_SEQ(0x1, tmp); |
---|
1394 | | - WREG_SEQ(0, 3); |
---|
1395 | | - } |
---|
1396 | | - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); |
---|
1397 | | -} |
---|
1398 | | - |
---|
1399 | | -/* |
---|
1400 | | - * The core can pass us a set of gamma values to program. We actually only |
---|
1401 | | - * use this for 8-bit mode so can't perform smooth fades on deeper modes, |
---|
1402 | | - * but it's a requirement that we provide the function |
---|
1403 | | - */ |
---|
1404 | | -static int mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
---|
1405 | | - u16 *blue, uint32_t size, |
---|
1406 | | - struct drm_modeset_acquire_ctx *ctx) |
---|
1407 | | -{ |
---|
1408 | | - mga_crtc_load_lut(crtc); |
---|
1409 | | - |
---|
1410 | | - return 0; |
---|
1411 | | -} |
---|
1412 | | - |
---|
1413 | | -/* Simple cleanup function */ |
---|
1414 | | -static void mga_crtc_destroy(struct drm_crtc *crtc) |
---|
1415 | | -{ |
---|
1416 | | - struct mga_crtc *mga_crtc = to_mga_crtc(crtc); |
---|
1417 | | - |
---|
1418 | | - drm_crtc_cleanup(crtc); |
---|
1419 | | - kfree(mga_crtc); |
---|
1420 | | -} |
---|
1421 | | - |
---|
1422 | | -static void mga_crtc_disable(struct drm_crtc *crtc) |
---|
1423 | | -{ |
---|
1424 | | - int ret; |
---|
1425 | | - DRM_DEBUG_KMS("\n"); |
---|
1426 | | - mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
---|
1427 | | - if (crtc->primary->fb) { |
---|
1428 | | - struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb); |
---|
1429 | | - struct drm_gem_object *obj = mga_fb->obj; |
---|
1430 | | - struct mgag200_bo *bo = gem_to_mga_bo(obj); |
---|
1431 | | - ret = mgag200_bo_reserve(bo, false); |
---|
1432 | | - if (ret) |
---|
1433 | | - return; |
---|
1434 | | - mgag200_bo_push_sysram(bo); |
---|
1435 | | - mgag200_bo_unreserve(bo); |
---|
1436 | | - } |
---|
1437 | | - crtc->primary->fb = NULL; |
---|
1438 | | -} |
---|
1439 | | - |
---|
1440 | | -/* These provide the minimum set of functions required to handle a CRTC */ |
---|
1441 | | -static const struct drm_crtc_funcs mga_crtc_funcs = { |
---|
1442 | | - .cursor_set = mga_crtc_cursor_set, |
---|
1443 | | - .cursor_move = mga_crtc_cursor_move, |
---|
1444 | | - .gamma_set = mga_crtc_gamma_set, |
---|
1445 | | - .set_config = drm_crtc_helper_set_config, |
---|
1446 | | - .destroy = mga_crtc_destroy, |
---|
1447 | | -}; |
---|
1448 | | - |
---|
1449 | | -static const struct drm_crtc_helper_funcs mga_helper_funcs = { |
---|
1450 | | - .disable = mga_crtc_disable, |
---|
1451 | | - .dpms = mga_crtc_dpms, |
---|
1452 | | - .mode_set = mga_crtc_mode_set, |
---|
1453 | | - .mode_set_base = mga_crtc_mode_set_base, |
---|
1454 | | - .prepare = mga_crtc_prepare, |
---|
1455 | | - .commit = mga_crtc_commit, |
---|
1456 | | -}; |
---|
1457 | | - |
---|
1458 | | -/* CRTC setup */ |
---|
1459 | | -static void mga_crtc_init(struct mga_device *mdev) |
---|
1460 | | -{ |
---|
1461 | | - struct mga_crtc *mga_crtc; |
---|
1462 | | - |
---|
1463 | | - mga_crtc = kzalloc(sizeof(struct mga_crtc) + |
---|
1464 | | - (MGAG200FB_CONN_LIMIT * sizeof(struct drm_connector *)), |
---|
1465 | | - GFP_KERNEL); |
---|
1466 | | - |
---|
1467 | | - if (mga_crtc == NULL) |
---|
1468 | | - return; |
---|
1469 | | - |
---|
1470 | | - drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs); |
---|
1471 | | - |
---|
1472 | | - drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE); |
---|
1473 | | - mdev->mode_info.crtc = mga_crtc; |
---|
1474 | | - |
---|
1475 | | - drm_crtc_helper_add(&mga_crtc->base, &mga_helper_funcs); |
---|
1476 | | -} |
---|
1477 | | - |
---|
1478 | | -/* |
---|
1479 | | - * The encoder comes after the CRTC in the output pipeline, but before |
---|
1480 | | - * the connector. It's responsible for ensuring that the digital |
---|
1481 | | - * stream is appropriately converted into the output format. Setup is |
---|
1482 | | - * very simple in this case - all we have to do is inform qemu of the |
---|
1483 | | - * colour depth in order to ensure that it displays appropriately |
---|
1484 | | - */ |
---|
1485 | | - |
---|
1486 | | -/* |
---|
1487 | | - * These functions are analagous to those in the CRTC code, but are intended |
---|
1488 | | - * to handle any encoder-specific limitations |
---|
1489 | | - */ |
---|
1490 | | -static void mga_encoder_mode_set(struct drm_encoder *encoder, |
---|
1491 | | - struct drm_display_mode *mode, |
---|
1492 | | - struct drm_display_mode *adjusted_mode) |
---|
1493 | | -{ |
---|
1494 | | - |
---|
1495 | | -} |
---|
1496 | | - |
---|
1497 | | -static void mga_encoder_dpms(struct drm_encoder *encoder, int state) |
---|
1498 | | -{ |
---|
1499 | | - return; |
---|
1500 | | -} |
---|
1501 | | - |
---|
1502 | | -static void mga_encoder_prepare(struct drm_encoder *encoder) |
---|
1503 | | -{ |
---|
1504 | | -} |
---|
1505 | | - |
---|
1506 | | -static void mga_encoder_commit(struct drm_encoder *encoder) |
---|
1507 | | -{ |
---|
1508 | | -} |
---|
1509 | | - |
---|
1510 | | -static void mga_encoder_destroy(struct drm_encoder *encoder) |
---|
1511 | | -{ |
---|
1512 | | - struct mga_encoder *mga_encoder = to_mga_encoder(encoder); |
---|
1513 | | - drm_encoder_cleanup(encoder); |
---|
1514 | | - kfree(mga_encoder); |
---|
1515 | | -} |
---|
1516 | | - |
---|
1517 | | -static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = { |
---|
1518 | | - .dpms = mga_encoder_dpms, |
---|
1519 | | - .mode_set = mga_encoder_mode_set, |
---|
1520 | | - .prepare = mga_encoder_prepare, |
---|
1521 | | - .commit = mga_encoder_commit, |
---|
1522 | | -}; |
---|
1523 | | - |
---|
1524 | | -static const struct drm_encoder_funcs mga_encoder_encoder_funcs = { |
---|
1525 | | - .destroy = mga_encoder_destroy, |
---|
1526 | | -}; |
---|
1527 | | - |
---|
1528 | | -static struct drm_encoder *mga_encoder_init(struct drm_device *dev) |
---|
1529 | | -{ |
---|
1530 | | - struct drm_encoder *encoder; |
---|
1531 | | - struct mga_encoder *mga_encoder; |
---|
1532 | | - |
---|
1533 | | - mga_encoder = kzalloc(sizeof(struct mga_encoder), GFP_KERNEL); |
---|
1534 | | - if (!mga_encoder) |
---|
1535 | | - return NULL; |
---|
1536 | | - |
---|
1537 | | - encoder = &mga_encoder->base; |
---|
1538 | | - encoder->possible_crtcs = 0x1; |
---|
1539 | | - |
---|
1540 | | - drm_encoder_init(dev, encoder, &mga_encoder_encoder_funcs, |
---|
1541 | | - DRM_MODE_ENCODER_DAC, NULL); |
---|
1542 | | - drm_encoder_helper_add(encoder, &mga_encoder_helper_funcs); |
---|
1543 | | - |
---|
1544 | | - return encoder; |
---|
1545 | | -} |
---|
1546 | | - |
---|
1547 | 1381 | |
---|
1548 | 1382 | static int mga_vga_get_modes(struct drm_connector *connector) |
---|
1549 | 1383 | { |
---|
.. | .. |
---|
1590 | 1424 | struct drm_display_mode *mode) |
---|
1591 | 1425 | { |
---|
1592 | 1426 | struct drm_device *dev = connector->dev; |
---|
1593 | | - struct mga_device *mdev = (struct mga_device*)dev->dev_private; |
---|
| 1427 | + struct mga_device *mdev = to_mga_device(dev); |
---|
1594 | 1428 | int bpp = 32; |
---|
1595 | 1429 | |
---|
1596 | 1430 | if (IS_G200_SE(mdev)) { |
---|
1597 | | - if (mdev->unique_rev_id == 0x01) { |
---|
| 1431 | + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; |
---|
| 1432 | + |
---|
| 1433 | + if (unique_rev_id == 0x01) { |
---|
1598 | 1434 | if (mode->hdisplay > 1600) |
---|
1599 | 1435 | return MODE_VIRTUAL_X; |
---|
1600 | 1436 | if (mode->vdisplay > 1200) |
---|
.. | .. |
---|
1602 | 1438 | if (mga_vga_calculate_mode_bandwidth(mode, bpp) |
---|
1603 | 1439 | > (24400 * 1024)) |
---|
1604 | 1440 | return MODE_BANDWIDTH; |
---|
1605 | | - } else if (mdev->unique_rev_id == 0x02) { |
---|
| 1441 | + } else if (unique_rev_id == 0x02) { |
---|
1606 | 1442 | if (mode->hdisplay > 1920) |
---|
1607 | 1443 | return MODE_VIRTUAL_X; |
---|
1608 | 1444 | if (mode->vdisplay > 1200) |
---|
.. | .. |
---|
1655 | 1491 | bpp = connector->cmdline_mode.bpp; |
---|
1656 | 1492 | } |
---|
1657 | 1493 | |
---|
1658 | | - if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) { |
---|
| 1494 | + if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->vram_fb_available) { |
---|
1659 | 1495 | if (connector->cmdline_mode.specified) |
---|
1660 | 1496 | connector->cmdline_mode.specified = false; |
---|
1661 | 1497 | return MODE_BAD; |
---|
.. | .. |
---|
1664 | 1500 | return MODE_OK; |
---|
1665 | 1501 | } |
---|
1666 | 1502 | |
---|
1667 | | -static struct drm_encoder *mga_connector_best_encoder(struct drm_connector |
---|
1668 | | - *connector) |
---|
1669 | | -{ |
---|
1670 | | - int enc_id = connector->encoder_ids[0]; |
---|
1671 | | - /* pick the encoder ids */ |
---|
1672 | | - if (enc_id) |
---|
1673 | | - return drm_encoder_find(connector->dev, NULL, enc_id); |
---|
1674 | | - return NULL; |
---|
1675 | | -} |
---|
1676 | | - |
---|
1677 | 1503 | static void mga_connector_destroy(struct drm_connector *connector) |
---|
1678 | 1504 | { |
---|
1679 | 1505 | struct mga_connector *mga_connector = to_mga_connector(connector); |
---|
1680 | 1506 | mgag200_i2c_destroy(mga_connector->i2c); |
---|
1681 | 1507 | drm_connector_cleanup(connector); |
---|
1682 | | - kfree(connector); |
---|
1683 | 1508 | } |
---|
1684 | 1509 | |
---|
1685 | 1510 | static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = { |
---|
1686 | | - .get_modes = mga_vga_get_modes, |
---|
| 1511 | + .get_modes = mga_vga_get_modes, |
---|
1687 | 1512 | .mode_valid = mga_vga_mode_valid, |
---|
1688 | | - .best_encoder = mga_connector_best_encoder, |
---|
1689 | 1513 | }; |
---|
1690 | 1514 | |
---|
1691 | 1515 | static const struct drm_connector_funcs mga_vga_connector_funcs = { |
---|
1692 | | - .dpms = drm_helper_connector_dpms, |
---|
1693 | | - .fill_modes = drm_helper_probe_single_connector_modes, |
---|
1694 | | - .destroy = mga_connector_destroy, |
---|
| 1516 | + .reset = drm_atomic_helper_connector_reset, |
---|
| 1517 | + .fill_modes = drm_helper_probe_single_connector_modes, |
---|
| 1518 | + .destroy = mga_connector_destroy, |
---|
| 1519 | + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
---|
| 1520 | + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
---|
1695 | 1521 | }; |
---|
1696 | 1522 | |
---|
1697 | | -static struct drm_connector *mga_vga_init(struct drm_device *dev) |
---|
| 1523 | +static int mgag200_vga_connector_init(struct mga_device *mdev) |
---|
1698 | 1524 | { |
---|
1699 | | - struct drm_connector *connector; |
---|
1700 | | - struct mga_connector *mga_connector; |
---|
1701 | | - |
---|
1702 | | - mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL); |
---|
1703 | | - if (!mga_connector) |
---|
1704 | | - return NULL; |
---|
1705 | | - |
---|
1706 | | - connector = &mga_connector->base; |
---|
1707 | | - |
---|
1708 | | - drm_connector_init(dev, connector, |
---|
1709 | | - &mga_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
---|
1710 | | - |
---|
1711 | | - drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); |
---|
1712 | | - |
---|
1713 | | - drm_connector_register(connector); |
---|
1714 | | - |
---|
1715 | | - mga_connector->i2c = mgag200_i2c_create(dev); |
---|
1716 | | - if (!mga_connector->i2c) |
---|
1717 | | - DRM_ERROR("failed to add ddc bus\n"); |
---|
1718 | | - |
---|
1719 | | - return connector; |
---|
1720 | | -} |
---|
1721 | | - |
---|
1722 | | - |
---|
1723 | | -int mgag200_modeset_init(struct mga_device *mdev) |
---|
1724 | | -{ |
---|
1725 | | - struct drm_encoder *encoder; |
---|
1726 | | - struct drm_connector *connector; |
---|
| 1525 | + struct drm_device *dev = &mdev->base; |
---|
| 1526 | + struct mga_connector *mconnector = &mdev->connector; |
---|
| 1527 | + struct drm_connector *connector = &mconnector->base; |
---|
| 1528 | + struct mga_i2c_chan *i2c; |
---|
1727 | 1529 | int ret; |
---|
1728 | 1530 | |
---|
1729 | | - mdev->mode_info.mode_config_initialized = true; |
---|
| 1531 | + i2c = mgag200_i2c_create(dev); |
---|
| 1532 | + if (!i2c) |
---|
| 1533 | + drm_warn(dev, "failed to add DDC bus\n"); |
---|
1730 | 1534 | |
---|
1731 | | - mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; |
---|
1732 | | - mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; |
---|
| 1535 | + ret = drm_connector_init_with_ddc(dev, connector, |
---|
| 1536 | + &mga_vga_connector_funcs, |
---|
| 1537 | + DRM_MODE_CONNECTOR_VGA, |
---|
| 1538 | + &i2c->adapter); |
---|
| 1539 | + if (ret) |
---|
| 1540 | + goto err_mgag200_i2c_destroy; |
---|
| 1541 | + drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); |
---|
1733 | 1542 | |
---|
1734 | | - mdev->dev->mode_config.fb_base = mdev->mc.vram_base; |
---|
| 1543 | + mconnector->i2c = i2c; |
---|
1735 | 1544 | |
---|
1736 | | - mga_crtc_init(mdev); |
---|
| 1545 | + return 0; |
---|
1737 | 1546 | |
---|
1738 | | - encoder = mga_encoder_init(mdev->dev); |
---|
1739 | | - if (!encoder) { |
---|
1740 | | - DRM_ERROR("mga_encoder_init failed\n"); |
---|
1741 | | - return -1; |
---|
1742 | | - } |
---|
| 1547 | +err_mgag200_i2c_destroy: |
---|
| 1548 | + mgag200_i2c_destroy(i2c); |
---|
| 1549 | + return ret; |
---|
| 1550 | +} |
---|
1743 | 1551 | |
---|
1744 | | - connector = mga_vga_init(mdev->dev); |
---|
1745 | | - if (!connector) { |
---|
1746 | | - DRM_ERROR("mga_vga_init failed\n"); |
---|
1747 | | - return -1; |
---|
1748 | | - } |
---|
| 1552 | +/* |
---|
| 1553 | + * Simple Display Pipe |
---|
| 1554 | + */ |
---|
1749 | 1555 | |
---|
1750 | | - drm_connector_attach_encoder(connector, encoder); |
---|
| 1556 | +static enum drm_mode_status |
---|
| 1557 | +mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, |
---|
| 1558 | + const struct drm_display_mode *mode) |
---|
| 1559 | +{ |
---|
| 1560 | + return MODE_OK; |
---|
| 1561 | +} |
---|
1751 | 1562 | |
---|
1752 | | - ret = mgag200_fbdev_init(mdev); |
---|
1753 | | - if (ret) { |
---|
1754 | | - DRM_ERROR("mga_fbdev_init failed\n"); |
---|
1755 | | - return ret; |
---|
1756 | | - } |
---|
| 1563 | +static void |
---|
| 1564 | +mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb, |
---|
| 1565 | + struct drm_rect *clip) |
---|
| 1566 | +{ |
---|
| 1567 | + struct drm_device *dev = &mdev->base; |
---|
| 1568 | + void *vmap; |
---|
| 1569 | + |
---|
| 1570 | + vmap = drm_gem_shmem_vmap(fb->obj[0]); |
---|
| 1571 | + if (drm_WARN_ON(dev, !vmap)) |
---|
| 1572 | + return; /* BUG: SHMEM BO should always be vmapped */ |
---|
| 1573 | + |
---|
| 1574 | + drm_fb_memcpy_dstclip(mdev->vram, vmap, fb, clip); |
---|
| 1575 | + |
---|
| 1576 | + drm_gem_shmem_vunmap(fb->obj[0], vmap); |
---|
| 1577 | + |
---|
| 1578 | + /* Always scanout image at VRAM offset 0 */ |
---|
| 1579 | + mgag200_set_startadd(mdev, (u32)0); |
---|
| 1580 | + mgag200_set_offset(mdev, fb); |
---|
| 1581 | +} |
---|
| 1582 | + |
---|
| 1583 | +static void |
---|
| 1584 | +mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, |
---|
| 1585 | + struct drm_crtc_state *crtc_state, |
---|
| 1586 | + struct drm_plane_state *plane_state) |
---|
| 1587 | +{ |
---|
| 1588 | + struct drm_crtc *crtc = &pipe->crtc; |
---|
| 1589 | + struct drm_device *dev = crtc->dev; |
---|
| 1590 | + struct mga_device *mdev = to_mga_device(dev); |
---|
| 1591 | + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; |
---|
| 1592 | + struct drm_framebuffer *fb = plane_state->fb; |
---|
| 1593 | + struct drm_rect fullscreen = { |
---|
| 1594 | + .x1 = 0, |
---|
| 1595 | + .x2 = fb->width, |
---|
| 1596 | + .y1 = 0, |
---|
| 1597 | + .y2 = fb->height, |
---|
| 1598 | + }; |
---|
| 1599 | + |
---|
| 1600 | + if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
| 1601 | + mgag200_g200wb_hold_bmc(mdev); |
---|
| 1602 | + |
---|
| 1603 | + mgag200_set_format_regs(mdev, fb); |
---|
| 1604 | + mgag200_set_mode_regs(mdev, adjusted_mode); |
---|
| 1605 | + mgag200_crtc_set_plls(mdev, adjusted_mode->clock); |
---|
| 1606 | + |
---|
| 1607 | + if (mdev->type == G200_ER) |
---|
| 1608 | + mgag200_g200er_reset_tagfifo(mdev); |
---|
| 1609 | + |
---|
| 1610 | + if (IS_G200_SE(mdev)) |
---|
| 1611 | + mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, fb); |
---|
| 1612 | + else if (mdev->type == G200_EV) |
---|
| 1613 | + mgag200_g200ev_set_hiprilvl(mdev); |
---|
| 1614 | + |
---|
| 1615 | + if (mdev->type == G200_WB || mdev->type == G200_EW3) |
---|
| 1616 | + mgag200_g200wb_release_bmc(mdev); |
---|
| 1617 | + |
---|
| 1618 | + mga_crtc_load_lut(crtc); |
---|
| 1619 | + mgag200_enable_display(mdev); |
---|
| 1620 | + |
---|
| 1621 | + mgag200_handle_damage(mdev, fb, &fullscreen); |
---|
| 1622 | +} |
---|
| 1623 | + |
---|
| 1624 | +static void |
---|
| 1625 | +mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) |
---|
| 1626 | +{ |
---|
| 1627 | + struct drm_crtc *crtc = &pipe->crtc; |
---|
| 1628 | + struct mga_device *mdev = to_mga_device(crtc->dev); |
---|
| 1629 | + |
---|
| 1630 | + mgag200_disable_display(mdev); |
---|
| 1631 | +} |
---|
| 1632 | + |
---|
| 1633 | +static int |
---|
| 1634 | +mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe, |
---|
| 1635 | + struct drm_plane_state *plane_state, |
---|
| 1636 | + struct drm_crtc_state *crtc_state) |
---|
| 1637 | +{ |
---|
| 1638 | + struct drm_plane *plane = plane_state->plane; |
---|
| 1639 | + struct drm_framebuffer *new_fb = plane_state->fb; |
---|
| 1640 | + struct drm_framebuffer *fb = NULL; |
---|
| 1641 | + |
---|
| 1642 | + if (!new_fb) |
---|
| 1643 | + return 0; |
---|
| 1644 | + |
---|
| 1645 | + if (plane->state) |
---|
| 1646 | + fb = plane->state->fb; |
---|
| 1647 | + |
---|
| 1648 | + if (!fb || (fb->format != new_fb->format)) |
---|
| 1649 | + crtc_state->mode_changed = true; /* update PLL settings */ |
---|
1757 | 1650 | |
---|
1758 | 1651 | return 0; |
---|
1759 | 1652 | } |
---|
1760 | 1653 | |
---|
1761 | | -void mgag200_modeset_fini(struct mga_device *mdev) |
---|
| 1654 | +static void |
---|
| 1655 | +mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, |
---|
| 1656 | + struct drm_plane_state *old_state) |
---|
1762 | 1657 | { |
---|
| 1658 | + struct drm_plane *plane = &pipe->plane; |
---|
| 1659 | + struct drm_device *dev = plane->dev; |
---|
| 1660 | + struct mga_device *mdev = to_mga_device(dev); |
---|
| 1661 | + struct drm_plane_state *state = plane->state; |
---|
| 1662 | + struct drm_framebuffer *fb = state->fb; |
---|
| 1663 | + struct drm_rect damage; |
---|
1763 | 1664 | |
---|
| 1665 | + if (!fb) |
---|
| 1666 | + return; |
---|
| 1667 | + |
---|
| 1668 | + if (drm_atomic_helper_damage_merged(old_state, state, &damage)) |
---|
| 1669 | + mgag200_handle_damage(mdev, fb, &damage); |
---|
| 1670 | +} |
---|
| 1671 | + |
---|
| 1672 | +static const struct drm_simple_display_pipe_funcs |
---|
| 1673 | +mgag200_simple_display_pipe_funcs = { |
---|
| 1674 | + .mode_valid = mgag200_simple_display_pipe_mode_valid, |
---|
| 1675 | + .enable = mgag200_simple_display_pipe_enable, |
---|
| 1676 | + .disable = mgag200_simple_display_pipe_disable, |
---|
| 1677 | + .check = mgag200_simple_display_pipe_check, |
---|
| 1678 | + .update = mgag200_simple_display_pipe_update, |
---|
| 1679 | + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, |
---|
| 1680 | +}; |
---|
| 1681 | + |
---|
| 1682 | +static const uint32_t mgag200_simple_display_pipe_formats[] = { |
---|
| 1683 | + DRM_FORMAT_XRGB8888, |
---|
| 1684 | + DRM_FORMAT_RGB565, |
---|
| 1685 | + DRM_FORMAT_RGB888, |
---|
| 1686 | +}; |
---|
| 1687 | + |
---|
| 1688 | +static const uint64_t mgag200_simple_display_pipe_fmtmods[] = { |
---|
| 1689 | + DRM_FORMAT_MOD_LINEAR, |
---|
| 1690 | + DRM_FORMAT_MOD_INVALID |
---|
| 1691 | +}; |
---|
| 1692 | + |
---|
| 1693 | +/* |
---|
| 1694 | + * Mode config |
---|
| 1695 | + */ |
---|
| 1696 | + |
---|
| 1697 | +static const struct drm_mode_config_funcs mgag200_mode_config_funcs = { |
---|
| 1698 | + .fb_create = drm_gem_fb_create_with_dirty, |
---|
| 1699 | + .atomic_check = drm_atomic_helper_check, |
---|
| 1700 | + .atomic_commit = drm_atomic_helper_commit, |
---|
| 1701 | +}; |
---|
| 1702 | + |
---|
| 1703 | +static unsigned int mgag200_preferred_depth(struct mga_device *mdev) |
---|
| 1704 | +{ |
---|
| 1705 | + if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024)) |
---|
| 1706 | + return 16; |
---|
| 1707 | + else |
---|
| 1708 | + return 32; |
---|
| 1709 | +} |
---|
| 1710 | + |
---|
| 1711 | +int mgag200_modeset_init(struct mga_device *mdev) |
---|
| 1712 | +{ |
---|
| 1713 | + struct drm_device *dev = &mdev->base; |
---|
| 1714 | + struct drm_connector *connector = &mdev->connector.base; |
---|
| 1715 | + struct drm_simple_display_pipe *pipe = &mdev->display_pipe; |
---|
| 1716 | + size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats); |
---|
| 1717 | + int ret; |
---|
| 1718 | + |
---|
| 1719 | + mdev->bpp_shifts[0] = 0; |
---|
| 1720 | + mdev->bpp_shifts[1] = 1; |
---|
| 1721 | + mdev->bpp_shifts[2] = 0; |
---|
| 1722 | + mdev->bpp_shifts[3] = 2; |
---|
| 1723 | + |
---|
| 1724 | + mgag200_init_regs(mdev); |
---|
| 1725 | + |
---|
| 1726 | + ret = drmm_mode_config_init(dev); |
---|
| 1727 | + if (ret) { |
---|
| 1728 | + drm_err(dev, "drmm_mode_config_init() failed, error %d\n", |
---|
| 1729 | + ret); |
---|
| 1730 | + return ret; |
---|
| 1731 | + } |
---|
| 1732 | + |
---|
| 1733 | + dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; |
---|
| 1734 | + dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; |
---|
| 1735 | + |
---|
| 1736 | + dev->mode_config.preferred_depth = mgag200_preferred_depth(mdev); |
---|
| 1737 | + |
---|
| 1738 | + dev->mode_config.fb_base = mdev->mc.vram_base; |
---|
| 1739 | + |
---|
| 1740 | + dev->mode_config.funcs = &mgag200_mode_config_funcs; |
---|
| 1741 | + |
---|
| 1742 | + ret = mgag200_vga_connector_init(mdev); |
---|
| 1743 | + if (ret) { |
---|
| 1744 | + drm_err(dev, |
---|
| 1745 | + "mgag200_vga_connector_init() failed, error %d\n", |
---|
| 1746 | + ret); |
---|
| 1747 | + return ret; |
---|
| 1748 | + } |
---|
| 1749 | + |
---|
| 1750 | + ret = drm_simple_display_pipe_init(dev, pipe, |
---|
| 1751 | + &mgag200_simple_display_pipe_funcs, |
---|
| 1752 | + mgag200_simple_display_pipe_formats, |
---|
| 1753 | + format_count, |
---|
| 1754 | + mgag200_simple_display_pipe_fmtmods, |
---|
| 1755 | + connector); |
---|
| 1756 | + if (ret) { |
---|
| 1757 | + drm_err(dev, |
---|
| 1758 | + "drm_simple_display_pipe_init() failed, error %d\n", |
---|
| 1759 | + ret); |
---|
| 1760 | + return ret; |
---|
| 1761 | + } |
---|
| 1762 | + |
---|
| 1763 | + /* FIXME: legacy gamma tables; convert to CRTC state */ |
---|
| 1764 | + drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE); |
---|
| 1765 | + |
---|
| 1766 | + drm_mode_config_reset(dev); |
---|
| 1767 | + |
---|
| 1768 | + return 0; |
---|
1764 | 1769 | } |
---|