Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/mgag200: Provide per-device callbacks for PIXPLLC

Move the PIXPLLC code into per-model source files and wire it up
with per-model callbacks. No functional changes.

The PIXPLLC pixel-clock is part of the CRTC, but really separate
hardware that varies with each model of the G200. Move the PIXPLLC
code for each model into the per-model source file and call it from
CRTC helpers via device functions.

This allows to remove struct mgag200_pll and the related code. The
new callbacks behave like the CRTC's atomic_check and atomic_enable
functions.

v3:
* clean up style

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Tested-by: Jocelyn Falempe <jfalempe@redhat.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-12-tzimmermann@suse.de

+1026 -1029
+1 -2
drivers/gpu/drm/mgag200/Makefile
··· 11 11 mgag200_g200se.o \ 12 12 mgag200_g200wb.o \ 13 13 mgag200_i2c.o \ 14 - mgag200_mode.o \ 15 - mgag200_pll.o 14 + mgag200_mode.o 16 15 17 16 obj-$(CONFIG_DRM_MGAG200) += mgag200.o
+16 -16
drivers/gpu/drm/mgag200/mgag200_drv.h
··· 156 156 #define MGAG200_MAX_FB_WIDTH 4096 157 157 158 158 struct mga_device; 159 - struct mgag200_pll; 160 159 161 160 /* 162 161 * Stores parameters for programming the PLLs ··· 172 173 unsigned int n; 173 174 unsigned int p; 174 175 unsigned int s; 175 - }; 176 - 177 - struct mgag200_pll_funcs { 178 - int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc); 179 - void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc); 180 - }; 181 - 182 - struct mgag200_pll { 183 - struct mga_device *mdev; 184 - 185 - const struct mgag200_pll_funcs *funcs; 186 176 }; 187 177 188 178 struct mgag200_crtc_state { ··· 262 274 * a new display mode. 263 275 */ 264 276 void (*enable_vidrst)(struct mga_device *mdev); 277 + 278 + /* 279 + * Validate that the given state can be programmed into PIXPLLC. On 280 + * success, the calculated parameters should be stored in the CRTC's 281 + * state in struct @mgag200_crtc_state.pixpllc. 282 + */ 283 + int (*pixpllc_atomic_check)(struct drm_crtc *crtc, struct drm_atomic_state *new_state); 284 + 285 + /* 286 + * Program PIXPLLC from the CRTC state. The parameters should have been 287 + * stored in struct @mgag200_crtc_state.pixpllc by the corresponding 288 + * implementation of @pixpllc_atomic_check. 289 + */ 290 + void (*pixpllc_atomic_update)(struct drm_crtc *crtc, struct drm_atomic_state *old_state); 265 291 }; 266 292 267 293 struct mga_device { ··· 294 292 295 293 enum mga_type type; 296 294 297 - struct mgag200_pll pixpll; 298 295 struct drm_plane primary_plane; 299 296 struct drm_crtc crtc; 300 297 struct drm_encoder encoder; ··· 347 346 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 348 347 enum mga_type type); 349 348 void mgag200_g200wb_init_registers(struct mga_device *mdev); 349 + void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); 350 350 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 351 351 enum mga_type type); 352 352 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 353 353 enum mga_type type); 354 354 void mgag200_g200eh_init_registers(struct mga_device *mdev); 355 + void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state); 355 356 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv, 356 357 enum mga_type type); 357 358 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv, ··· 374 371 375 372 /* mgag200_i2c.c */ 376 373 int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c); 377 - 378 - /* mgag200_pll.c */ 379 - int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev); 380 374 381 375 #endif /* __MGAG200_DRV_H__ */
+109
drivers/gpu/drm/mgag200/mgag200_g200.c
··· 3 3 #include <linux/pci.h> 4 4 #include <linux/vmalloc.h> 5 5 6 + #include <drm/drm_atomic.h> 6 7 #include <drm/drm_drv.h> 7 8 8 9 #include "mgag200_drv.h" ··· 52 51 } 53 52 54 53 mgag200_init_registers(mdev); 54 + } 55 + 56 + /* 57 + * PIXPLLC 58 + */ 59 + 60 + static int mgag200_g200_pixpllc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state) 61 + { 62 + static const int post_div_max = 7; 63 + static const int in_div_min = 1; 64 + static const int in_div_max = 6; 65 + static const int feed_div_min = 7; 66 + static const int feed_div_max = 127; 67 + 68 + struct drm_device *dev = crtc->dev; 69 + struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev); 70 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 71 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 72 + long clock = new_crtc_state->mode.clock; 73 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 74 + u8 testp, testm, testn; 75 + u8 n = 0, m = 0, p, s; 76 + long f_vco; 77 + long computed; 78 + long delta, tmp_delta; 79 + long ref_clk = g200->ref_clk; 80 + long p_clk_min = g200->pclk_min; 81 + long p_clk_max = g200->pclk_max; 82 + 83 + if (clock > p_clk_max) { 84 + drm_err(dev, "Pixel Clock %ld too high\n", clock); 85 + return -EINVAL; 86 + } 87 + 88 + if (clock < p_clk_min >> 3) 89 + clock = p_clk_min >> 3; 90 + 91 + f_vco = clock; 92 + for (testp = 0; 93 + testp <= post_div_max && f_vco < p_clk_min; 94 + testp = (testp << 1) + 1, f_vco <<= 1) 95 + ; 96 + p = testp + 1; 97 + 98 + delta = clock; 99 + 100 + for (testm = in_div_min; testm <= in_div_max; testm++) { 101 + for (testn = feed_div_min; testn <= feed_div_max; testn++) { 102 + computed = ref_clk * (testn + 1) / (testm + 1); 103 + if (computed < f_vco) 104 + tmp_delta = f_vco - computed; 105 + else 106 + tmp_delta = computed - f_vco; 107 + if (tmp_delta < delta) { 108 + delta = tmp_delta; 109 + m = testm + 1; 110 + n = testn + 1; 111 + } 112 + } 113 + } 114 + f_vco = ref_clk * n / m; 115 + if (f_vco < 100000) 116 + s = 0; 117 + else if (f_vco < 140000) 118 + s = 1; 119 + else if (f_vco < 180000) 120 + s = 2; 121 + else 122 + s = 3; 123 + 124 + drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", 125 + clock, f_vco, m, n, p, s); 126 + 127 + pixpllc->m = m; 128 + pixpllc->n = n; 129 + pixpllc->p = p; 130 + pixpllc->s = s; 131 + 132 + return 0; 133 + } 134 + 135 + static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc, 136 + struct drm_atomic_state *old_state) 137 + { 138 + struct drm_device *dev = crtc->dev; 139 + struct mga_device *mdev = to_mga_device(dev); 140 + struct drm_crtc_state *crtc_state = crtc->state; 141 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 142 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 143 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 144 + u8 xpixpllcm, xpixpllcn, xpixpllcp; 145 + 146 + pixpllcm = pixpllc->m - 1; 147 + pixpllcn = pixpllc->n - 1; 148 + pixpllcp = pixpllc->p - 1; 149 + pixpllcs = pixpllc->s; 150 + 151 + xpixpllcm = pixpllcm; 152 + xpixpllcn = pixpllcn; 153 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 154 + 155 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 156 + 157 + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 158 + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 159 + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 55 160 } 56 161 57 162 /* ··· 291 184 } 292 185 293 186 static const struct mgag200_device_funcs mgag200_g200_device_funcs = { 187 + .pixpllc_atomic_check = mgag200_g200_pixpllc_atomic_check, 188 + .pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update, 294 189 }; 295 190 296 191 struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+131
drivers/gpu/drm/mgag200/mgag200_g200eh.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 3 + #include <linux/delay.h> 3 4 #include <linux/pci.h> 4 5 6 + #include <drm/drm_atomic.h> 5 7 #include <drm/drm_drv.h> 6 8 7 9 #include "mgag200_drv.h" ··· 33 31 } 34 32 35 33 /* 34 + * PIXPLLC 35 + */ 36 + 37 + static int mgag200_g200eh_pixpllc_atomic_check(struct drm_crtc *crtc, 38 + struct drm_atomic_state *new_state) 39 + { 40 + static const unsigned int vcomax = 800000; 41 + static const unsigned int vcomin = 400000; 42 + static const unsigned int pllreffreq = 33333; 43 + 44 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 45 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 46 + long clock = new_crtc_state->mode.clock; 47 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 48 + unsigned int delta, tmpdelta; 49 + unsigned int testp, testm, testn; 50 + unsigned int p, m, n, s; 51 + unsigned int computed; 52 + 53 + m = n = p = s = 0; 54 + delta = 0xffffffff; 55 + 56 + for (testp = 16; testp > 0; testp >>= 1) { 57 + if (clock * testp > vcomax) 58 + continue; 59 + if (clock * testp < vcomin) 60 + continue; 61 + 62 + for (testm = 1; testm < 33; testm++) { 63 + for (testn = 17; testn < 257; testn++) { 64 + computed = (pllreffreq * testn) / (testm * testp); 65 + if (computed > clock) 66 + tmpdelta = computed - clock; 67 + else 68 + tmpdelta = clock - computed; 69 + if (tmpdelta < delta) { 70 + delta = tmpdelta; 71 + n = testn; 72 + m = testm; 73 + p = testp; 74 + } 75 + } 76 + } 77 + } 78 + 79 + pixpllc->m = m; 80 + pixpllc->n = n; 81 + pixpllc->p = p; 82 + pixpllc->s = s; 83 + 84 + return 0; 85 + } 86 + 87 + void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, 88 + struct drm_atomic_state *old_state) 89 + { 90 + struct drm_device *dev = crtc->dev; 91 + struct mga_device *mdev = to_mga_device(dev); 92 + struct drm_crtc_state *crtc_state = crtc->state; 93 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 94 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 95 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 96 + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 97 + int i, j, tmpcount, vcount; 98 + bool pll_locked = false; 99 + 100 + pixpllcm = pixpllc->m - 1; 101 + pixpllcn = pixpllc->n - 1; 102 + pixpllcp = pixpllc->p - 1; 103 + pixpllcs = pixpllc->s; 104 + 105 + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; 106 + xpixpllcn = pixpllcn; 107 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 108 + 109 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 110 + 111 + for (i = 0; i <= 32 && pll_locked == false; i++) { 112 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 113 + tmp = RREG8(DAC_DATA); 114 + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 115 + WREG8(DAC_DATA, tmp); 116 + 117 + tmp = RREG8(MGAREG_MEM_MISC_READ); 118 + tmp |= 0x3 << 2; 119 + WREG8(MGAREG_MEM_MISC_WRITE, tmp); 120 + 121 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 122 + tmp = RREG8(DAC_DATA); 123 + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 124 + WREG8(DAC_DATA, tmp); 125 + 126 + udelay(500); 127 + 128 + WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm); 129 + WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn); 130 + WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp); 131 + 132 + udelay(500); 133 + 134 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 135 + tmp = RREG8(DAC_DATA); 136 + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 137 + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 138 + WREG8(DAC_DATA, tmp); 139 + 140 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 141 + tmp = RREG8(DAC_DATA); 142 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 143 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 144 + WREG8(DAC_DATA, tmp); 145 + 146 + vcount = RREG8(MGAREG_VCOUNT); 147 + 148 + for (j = 0; j < 30 && pll_locked == false; j++) { 149 + tmpcount = RREG8(MGAREG_VCOUNT); 150 + if (tmpcount < vcount) 151 + vcount = 0; 152 + if ((tmpcount - vcount) > 2) 153 + pll_locked = true; 154 + else 155 + udelay(5); 156 + } 157 + } 158 + } 159 + 160 + /* 36 161 * DRM device 37 162 */ 38 163 ··· 167 38 MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false); 168 39 169 40 static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = { 41 + .pixpllc_atomic_check = mgag200_g200eh_pixpllc_atomic_check, 42 + .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, 170 43 }; 171 44 172 45 struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+59
drivers/gpu/drm/mgag200/mgag200_g200eh3.c
··· 2 2 3 3 #include <linux/pci.h> 4 4 5 + #include <drm/drm_atomic.h> 5 6 #include <drm/drm_drv.h> 6 7 7 8 #include "mgag200_drv.h" 9 + 10 + /* 11 + * PIXPLLC 12 + */ 13 + 14 + static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc, 15 + struct drm_atomic_state *new_state) 16 + { 17 + static const unsigned int vcomax = 3000000; 18 + static const unsigned int vcomin = 1500000; 19 + static const unsigned int pllreffreq = 25000; 20 + 21 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 22 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 23 + long clock = new_crtc_state->mode.clock; 24 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 25 + unsigned int delta, tmpdelta; 26 + unsigned int testp, testm, testn; 27 + unsigned int p, m, n, s; 28 + unsigned int computed; 29 + 30 + m = n = p = s = 0; 31 + delta = 0xffffffff; 32 + testp = 0; 33 + 34 + for (testm = 150; testm >= 6; testm--) { 35 + if (clock * testm > vcomax) 36 + continue; 37 + if (clock * testm < vcomin) 38 + continue; 39 + for (testn = 120; testn >= 60; testn--) { 40 + computed = (pllreffreq * testn) / testm; 41 + if (computed > clock) 42 + tmpdelta = computed - clock; 43 + else 44 + tmpdelta = clock - computed; 45 + if (tmpdelta < delta) { 46 + delta = tmpdelta; 47 + n = testn + 1; 48 + m = testm + 1; 49 + p = testp + 1; 50 + } 51 + if (delta == 0) 52 + break; 53 + } 54 + if (delta == 0) 55 + break; 56 + } 57 + 58 + pixpllc->m = m; 59 + pixpllc->n = n; 60 + pixpllc->p = p; 61 + pixpllc->s = s; 62 + 63 + return 0; 64 + } 8 65 9 66 /* 10 67 * DRM device ··· 71 14 MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false); 72 15 73 16 static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = { 17 + .pixpllc_atomic_check = mgag200_g200eh3_pixpllc_atomic_check, 18 + .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, // same as G200EH 74 19 }; 75 20 76 21 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
+120
drivers/gpu/drm/mgag200/mgag200_g200er.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 3 + #include <linux/delay.h> 3 4 #include <linux/pci.h> 4 5 6 + #include <drm/drm_atomic.h> 5 7 #include <drm/drm_drv.h> 6 8 7 9 #include "mgag200_drv.h" ··· 34 32 } 35 33 36 34 /* 35 + * PIXPLLC 36 + */ 37 + 38 + static int mgag200_g200er_pixpllc_atomic_check(struct drm_crtc *crtc, 39 + struct drm_atomic_state *new_state) 40 + { 41 + static const unsigned int vcomax = 1488000; 42 + static const unsigned int vcomin = 1056000; 43 + static const unsigned int pllreffreq = 48000; 44 + static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; 45 + 46 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 47 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 48 + long clock = new_crtc_state->mode.clock; 49 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 50 + unsigned int delta, tmpdelta; 51 + int testr, testn, testm, testo; 52 + unsigned int p, m, n, s; 53 + unsigned int computed, vco; 54 + 55 + m = n = p = s = 0; 56 + delta = 0xffffffff; 57 + 58 + for (testr = 0; testr < 4; testr++) { 59 + if (delta == 0) 60 + break; 61 + for (testn = 5; testn < 129; testn++) { 62 + if (delta == 0) 63 + break; 64 + for (testm = 3; testm >= 0; testm--) { 65 + if (delta == 0) 66 + break; 67 + for (testo = 5; testo < 33; testo++) { 68 + vco = pllreffreq * (testn + 1) / 69 + (testr + 1); 70 + if (vco < vcomin) 71 + continue; 72 + if (vco > vcomax) 73 + continue; 74 + computed = vco / (m_div_val[testm] * (testo + 1)); 75 + if (computed > clock) 76 + tmpdelta = computed - clock; 77 + else 78 + tmpdelta = clock - computed; 79 + if (tmpdelta < delta) { 80 + delta = tmpdelta; 81 + m = (testm | (testo << 3)) + 1; 82 + n = testn + 1; 83 + p = testr + 1; 84 + s = testr; 85 + } 86 + } 87 + } 88 + } 89 + } 90 + 91 + pixpllc->m = m; 92 + pixpllc->n = n; 93 + pixpllc->p = p; 94 + pixpllc->s = s; 95 + 96 + return 0; 97 + } 98 + 99 + static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc, 100 + struct drm_atomic_state *old_state) 101 + { 102 + struct drm_device *dev = crtc->dev; 103 + struct mga_device *mdev = to_mga_device(dev); 104 + struct drm_crtc_state *crtc_state = crtc->state; 105 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 106 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 107 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 108 + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 109 + 110 + pixpllcm = pixpllc->m - 1; 111 + pixpllcn = pixpllc->n - 1; 112 + pixpllcp = pixpllc->p - 1; 113 + pixpllcs = pixpllc->s; 114 + 115 + xpixpllcm = pixpllcm; 116 + xpixpllcn = pixpllcn; 117 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 118 + 119 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 120 + 121 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 122 + tmp = RREG8(DAC_DATA); 123 + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 124 + WREG8(DAC_DATA, tmp); 125 + 126 + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 127 + tmp = RREG8(DAC_DATA); 128 + tmp |= MGA1064_REMHEADCTL_CLKDIS; 129 + WREG8(DAC_DATA, tmp); 130 + 131 + tmp = RREG8(MGAREG_MEM_MISC_READ); 132 + tmp |= (0x3<<2) | 0xc0; 133 + WREG8(MGAREG_MEM_MISC_WRITE, tmp); 134 + 135 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 136 + tmp = RREG8(DAC_DATA); 137 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 138 + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 139 + WREG8(DAC_DATA, tmp); 140 + 141 + udelay(500); 142 + 143 + WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); 144 + WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); 145 + WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); 146 + 147 + udelay(50); 148 + } 149 + 150 + /* 37 151 * DRM device 38 152 */ 39 153 ··· 157 39 MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false); 158 40 159 41 static const struct mgag200_device_funcs mgag200_g200er_device_funcs = { 42 + .pixpllc_atomic_check = mgag200_g200er_pixpllc_atomic_check, 43 + .pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update, 160 44 }; 161 45 162 46 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+132
drivers/gpu/drm/mgag200/mgag200_g200ev.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 3 + #include <linux/delay.h> 3 4 #include <linux/pci.h> 4 5 6 + #include <drm/drm_atomic.h> 5 7 #include <drm/drm_drv.h> 6 8 7 9 #include "mgag200_drv.h" ··· 34 32 } 35 33 36 34 /* 35 + * PIXPLLC 36 + */ 37 + 38 + static int mgag200_g200ev_pixpllc_atomic_check(struct drm_crtc *crtc, 39 + struct drm_atomic_state *new_state) 40 + { 41 + static const unsigned int vcomax = 550000; 42 + static const unsigned int vcomin = 150000; 43 + static const unsigned int pllreffreq = 50000; 44 + 45 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 46 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 47 + long clock = new_crtc_state->mode.clock; 48 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 49 + unsigned int delta, tmpdelta; 50 + unsigned int testp, testm, testn; 51 + unsigned int p, m, n, s; 52 + unsigned int computed; 53 + 54 + m = n = p = s = 0; 55 + delta = 0xffffffff; 56 + 57 + for (testp = 16; testp > 0; testp--) { 58 + if (clock * testp > vcomax) 59 + continue; 60 + if (clock * testp < vcomin) 61 + continue; 62 + 63 + for (testn = 1; testn < 257; testn++) { 64 + for (testm = 1; testm < 17; testm++) { 65 + computed = (pllreffreq * testn) / 66 + (testm * testp); 67 + if (computed > clock) 68 + tmpdelta = computed - clock; 69 + else 70 + tmpdelta = clock - computed; 71 + if (tmpdelta < delta) { 72 + delta = tmpdelta; 73 + n = testn; 74 + m = testm; 75 + p = testp; 76 + } 77 + } 78 + } 79 + } 80 + 81 + pixpllc->m = m; 82 + pixpllc->n = n; 83 + pixpllc->p = p; 84 + pixpllc->s = s; 85 + 86 + return 0; 87 + } 88 + 89 + static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc, 90 + struct drm_atomic_state *old_state) 91 + { 92 + struct drm_device *dev = crtc->dev; 93 + struct mga_device *mdev = to_mga_device(dev); 94 + struct drm_crtc_state *crtc_state = crtc->state; 95 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 96 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 97 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 98 + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 99 + 100 + pixpllcm = pixpllc->m - 1; 101 + pixpllcn = pixpllc->n - 1; 102 + pixpllcp = pixpllc->p - 1; 103 + pixpllcs = pixpllc->s; 104 + 105 + xpixpllcm = pixpllcm; 106 + xpixpllcn = pixpllcn; 107 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 108 + 109 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 110 + 111 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 112 + tmp = RREG8(DAC_DATA); 113 + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 114 + WREG8(DAC_DATA, tmp); 115 + 116 + tmp = RREG8(MGAREG_MEM_MISC_READ); 117 + tmp |= 0x3 << 2; 118 + WREG8(MGAREG_MEM_MISC_WRITE, tmp); 119 + 120 + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); 121 + tmp = RREG8(DAC_DATA); 122 + WREG8(DAC_DATA, tmp & ~0x40); 123 + 124 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 125 + tmp = RREG8(DAC_DATA); 126 + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 127 + WREG8(DAC_DATA, tmp); 128 + 129 + WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm); 130 + WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn); 131 + WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp); 132 + 133 + udelay(50); 134 + 135 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 136 + tmp = RREG8(DAC_DATA); 137 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 138 + WREG8(DAC_DATA, tmp); 139 + 140 + udelay(500); 141 + 142 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 143 + tmp = RREG8(DAC_DATA); 144 + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 145 + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 146 + WREG8(DAC_DATA, tmp); 147 + 148 + WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); 149 + tmp = RREG8(DAC_DATA); 150 + WREG8(DAC_DATA, tmp | 0x40); 151 + 152 + tmp = RREG8(MGAREG_MEM_MISC_READ); 153 + tmp |= (0x3 << 2); 154 + WREG8(MGAREG_MEM_MISC_WRITE, tmp); 155 + 156 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 157 + tmp = RREG8(DAC_DATA); 158 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 159 + WREG8(DAC_DATA, tmp); 160 + } 161 + 162 + /* 37 163 * DRM device 38 164 */ 39 165 ··· 169 39 MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false); 170 40 171 41 static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = { 42 + .pixpllc_atomic_check = mgag200_g200ev_pixpllc_atomic_check, 43 + .pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update, 172 44 }; 173 45 174 46 struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+61
drivers/gpu/drm/mgag200/mgag200_g200ew3.c
··· 2 2 3 3 #include <linux/pci.h> 4 4 5 + #include <drm/drm_atomic.h> 5 6 #include <drm/drm_drv.h> 6 7 7 8 #include "mgag200_drv.h" ··· 15 14 } 16 15 17 16 /* 17 + * PIXPLLC 18 + */ 19 + 20 + static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc, 21 + struct drm_atomic_state *new_state) 22 + { 23 + static const unsigned int vcomax = 800000; 24 + static const unsigned int vcomin = 400000; 25 + static const unsigned int pllreffreq = 25000; 26 + 27 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 28 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 29 + long clock = new_crtc_state->mode.clock; 30 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 31 + unsigned int delta, tmpdelta; 32 + unsigned int testp, testm, testn, testp2; 33 + unsigned int p, m, n, s; 34 + unsigned int computed; 35 + 36 + m = n = p = s = 0; 37 + delta = 0xffffffff; 38 + 39 + for (testp = 1; testp < 8; testp++) { 40 + for (testp2 = 1; testp2 < 8; testp2++) { 41 + if (testp < testp2) 42 + continue; 43 + if ((clock * testp * testp2) > vcomax) 44 + continue; 45 + if ((clock * testp * testp2) < vcomin) 46 + continue; 47 + for (testm = 1; testm < 26; testm++) { 48 + for (testn = 32; testn < 2048 ; testn++) { 49 + computed = (pllreffreq * testn) / (testm * testp * testp2); 50 + if (computed > clock) 51 + tmpdelta = computed - clock; 52 + else 53 + tmpdelta = clock - computed; 54 + if (tmpdelta < delta) { 55 + delta = tmpdelta; 56 + m = testm + 1; 57 + n = testn + 1; 58 + p = testp + 1; 59 + s = testp2; 60 + } 61 + } 62 + } 63 + } 64 + } 65 + 66 + pixpllc->m = m; 67 + pixpllc->n = n; 68 + pixpllc->p = p; 69 + pixpllc->s = s; 70 + 71 + return 0; 72 + } 73 + 74 + /* 18 75 * DRM device 19 76 */ 20 77 ··· 82 23 static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = { 83 24 .disable_vidrst = mgag200_bmc_disable_vidrst, 84 25 .enable_vidrst = mgag200_bmc_enable_vidrst, 26 + .pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check, 27 + .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB 85 28 }; 86 29 87 30 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
+209 -2
drivers/gpu/drm/mgag200/mgag200_g200se.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 3 + #include <linux/delay.h> 3 4 #include <linux/pci.h> 4 5 6 + #include <drm/drm_atomic.h> 5 7 #include <drm/drm_drv.h> 6 8 7 9 #include "mgag200_drv.h" ··· 59 57 } 60 58 61 59 /* 60 + * PIXPLLC 61 + */ 62 + 63 + static int mgag200_g200se_00_pixpllc_atomic_check(struct drm_crtc *crtc, 64 + struct drm_atomic_state *new_state) 65 + { 66 + static const unsigned int vcomax = 320000; 67 + static const unsigned int vcomin = 160000; 68 + static const unsigned int pllreffreq = 25000; 69 + 70 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 71 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 72 + long clock = new_crtc_state->mode.clock; 73 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 74 + unsigned int delta, tmpdelta, permitteddelta; 75 + unsigned int testp, testm, testn; 76 + unsigned int p, m, n, s; 77 + unsigned int computed; 78 + 79 + m = n = p = s = 0; 80 + delta = 0xffffffff; 81 + permitteddelta = clock * 5 / 1000; 82 + 83 + for (testp = 8; testp > 0; testp /= 2) { 84 + if (clock * testp > vcomax) 85 + continue; 86 + if (clock * testp < vcomin) 87 + continue; 88 + 89 + for (testn = 17; testn < 256; testn++) { 90 + for (testm = 1; testm < 32; testm++) { 91 + computed = (pllreffreq * testn) / (testm * testp); 92 + if (computed > clock) 93 + tmpdelta = computed - clock; 94 + else 95 + tmpdelta = clock - computed; 96 + if (tmpdelta < delta) { 97 + delta = tmpdelta; 98 + m = testm; 99 + n = testn; 100 + p = testp; 101 + } 102 + } 103 + } 104 + } 105 + 106 + if (delta > permitteddelta) { 107 + pr_warn("PLL delta too large\n"); 108 + return -EINVAL; 109 + } 110 + 111 + pixpllc->m = m; 112 + pixpllc->n = n; 113 + pixpllc->p = p; 114 + pixpllc->s = s; 115 + 116 + return 0; 117 + } 118 + 119 + static void mgag200_g200se_00_pixpllc_atomic_update(struct drm_crtc *crtc, 120 + struct drm_atomic_state *old_state) 121 + { 122 + struct drm_device *dev = crtc->dev; 123 + struct mga_device *mdev = to_mga_device(dev); 124 + struct drm_crtc_state *crtc_state = crtc->state; 125 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 126 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 127 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 128 + u8 xpixpllcm, xpixpllcn, xpixpllcp; 129 + 130 + pixpllcm = pixpllc->m - 1; 131 + pixpllcn = pixpllc->n - 1; 132 + pixpllcp = pixpllc->p - 1; 133 + pixpllcs = pixpllc->s; 134 + 135 + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); 136 + xpixpllcn = pixpllcn; 137 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 138 + 139 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 140 + 141 + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 142 + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 143 + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 144 + } 145 + 146 + static int mgag200_g200se_04_pixpllc_atomic_check(struct drm_crtc *crtc, 147 + struct drm_atomic_state *new_state) 148 + { 149 + static const unsigned int vcomax = 1600000; 150 + static const unsigned int vcomin = 800000; 151 + static const unsigned int pllreffreq = 25000; 152 + static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; 153 + 154 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 155 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 156 + long clock = new_crtc_state->mode.clock; 157 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 158 + unsigned int delta, tmpdelta, permitteddelta; 159 + unsigned int testp, testm, testn; 160 + unsigned int p, m, n, s; 161 + unsigned int computed; 162 + unsigned int fvv; 163 + unsigned int i; 164 + 165 + m = n = p = s = 0; 166 + delta = 0xffffffff; 167 + 168 + if (clock < 25000) 169 + clock = 25000; 170 + clock = clock * 2; 171 + 172 + /* Permited delta is 0.5% as VESA Specification */ 173 + permitteddelta = clock * 5 / 1000; 174 + 175 + for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) { 176 + testp = pvalues_e4[i]; 177 + 178 + if ((clock * testp) > vcomax) 179 + continue; 180 + if ((clock * testp) < vcomin) 181 + continue; 182 + 183 + for (testn = 50; testn <= 256; testn++) { 184 + for (testm = 1; testm <= 32; testm++) { 185 + computed = (pllreffreq * testn) / (testm * testp); 186 + if (computed > clock) 187 + tmpdelta = computed - clock; 188 + else 189 + tmpdelta = clock - computed; 190 + 191 + if (tmpdelta < delta) { 192 + delta = tmpdelta; 193 + m = testm; 194 + n = testn; 195 + p = testp; 196 + } 197 + } 198 + } 199 + } 200 + 201 + fvv = pllreffreq * n / m; 202 + fvv = (fvv - 800000) / 50000; 203 + if (fvv > 15) 204 + fvv = 15; 205 + s = fvv << 1; 206 + 207 + if (delta > permitteddelta) { 208 + pr_warn("PLL delta too large\n"); 209 + return -EINVAL; 210 + } 211 + 212 + pixpllc->m = m; 213 + pixpllc->n = n; 214 + pixpllc->p = p; 215 + pixpllc->s = s; 216 + 217 + return 0; 218 + } 219 + 220 + static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc, 221 + struct drm_atomic_state *old_state) 222 + { 223 + struct drm_device *dev = crtc->dev; 224 + struct mga_device *mdev = to_mga_device(dev); 225 + struct drm_crtc_state *crtc_state = crtc->state; 226 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 227 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 228 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 229 + u8 xpixpllcm, xpixpllcn, xpixpllcp; 230 + 231 + pixpllcm = pixpllc->m - 1; 232 + pixpllcn = pixpllc->n - 1; 233 + pixpllcp = pixpllc->p - 1; 234 + pixpllcs = pixpllc->s; 235 + 236 + xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); 237 + xpixpllcn = pixpllcn; 238 + xpixpllcp = (pixpllcs << 3) | pixpllcp; 239 + 240 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 241 + 242 + WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 243 + WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 244 + WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 245 + 246 + WREG_DAC(0x1a, 0x09); 247 + msleep(20); 248 + WREG_DAC(0x1a, 0x01); 249 + } 250 + 251 + /* 62 252 * DRM device 63 253 */ 64 254 ··· 287 93 return 0; 288 94 } 289 95 290 - static const struct mgag200_device_funcs mgag200_g200se_device_funcs = { 96 + static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = { 97 + .pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check, 98 + .pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update, 99 + }; 100 + 101 + static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = { 102 + .pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check, 103 + .pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update, 291 104 }; 292 105 293 106 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv, ··· 302 101 { 303 102 struct mgag200_g200se_device *g200se; 304 103 const struct mgag200_device_info *info; 104 + const struct mgag200_device_funcs *funcs; 305 105 struct mga_device *mdev; 306 106 struct drm_device *dev; 307 107 resource_size_t vram_available; ··· 349 147 return ERR_PTR(-EINVAL); 350 148 } 351 149 352 - ret = mgag200_device_init(mdev, type, info, &mgag200_g200se_device_funcs); 150 + if (g200se->unique_rev_id >= 0x04) 151 + funcs = &mgag200_g200se_04_device_funcs; 152 + else 153 + funcs = &mgag200_g200se_00_device_funcs; 154 + 155 + ret = mgag200_device_init(mdev, type, info, funcs); 353 156 if (ret) 354 157 return ERR_PTR(ret); 355 158
+180
drivers/gpu/drm/mgag200/mgag200_g200wb.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 3 + #include <linux/delay.h> 3 4 #include <linux/pci.h> 4 5 6 + #include <drm/drm_atomic.h> 5 7 #include <drm/drm_drv.h> 6 8 7 9 #include "mgag200_drv.h" ··· 31 29 } 32 30 33 31 /* 32 + * PIXPLLC 33 + */ 34 + 35 + static int mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc *crtc, 36 + struct drm_atomic_state *new_state) 37 + { 38 + static const unsigned int vcomax = 550000; 39 + static const unsigned int vcomin = 150000; 40 + static const unsigned int pllreffreq = 48000; 41 + 42 + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 43 + struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 44 + long clock = new_crtc_state->mode.clock; 45 + struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 46 + unsigned int delta, tmpdelta; 47 + unsigned int testp, testm, testn; 48 + unsigned int p, m, n, s; 49 + unsigned int computed; 50 + 51 + m = n = p = s = 0; 52 + delta = 0xffffffff; 53 + 54 + for (testp = 1; testp < 9; testp++) { 55 + if (clock * testp > vcomax) 56 + continue; 57 + if (clock * testp < vcomin) 58 + continue; 59 + 60 + for (testm = 1; testm < 17; testm++) { 61 + for (testn = 1; testn < 151; testn++) { 62 + computed = (pllreffreq * testn) / (testm * testp); 63 + if (computed > clock) 64 + tmpdelta = computed - clock; 65 + else 66 + tmpdelta = clock - computed; 67 + if (tmpdelta < delta) { 68 + delta = tmpdelta; 69 + n = testn; 70 + m = testm; 71 + p = testp; 72 + s = 0; 73 + } 74 + } 75 + } 76 + } 77 + 78 + pixpllc->m = m; 79 + pixpllc->n = n; 80 + pixpllc->p = p; 81 + pixpllc->s = s; 82 + 83 + return 0; 84 + } 85 + 86 + void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, 87 + struct drm_atomic_state *old_state) 88 + { 89 + struct drm_device *dev = crtc->dev; 90 + struct mga_device *mdev = to_mga_device(dev); 91 + struct drm_crtc_state *crtc_state = crtc->state; 92 + struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 93 + struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 94 + bool pll_locked = false; 95 + unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 96 + u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 97 + int i, j, tmpcount, vcount; 98 + 99 + pixpllcm = pixpllc->m - 1; 100 + pixpllcn = pixpllc->n - 1; 101 + pixpllcp = pixpllc->p - 1; 102 + pixpllcs = pixpllc->s; 103 + 104 + xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; 105 + xpixpllcn = pixpllcn; 106 + xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp; 107 + 108 + WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 109 + 110 + for (i = 0; i <= 32 && pll_locked == false; i++) { 111 + if (i > 0) { 112 + WREG8(MGAREG_CRTC_INDEX, 0x1e); 113 + tmp = RREG8(MGAREG_CRTC_DATA); 114 + if (tmp < 0xff) 115 + WREG8(MGAREG_CRTC_DATA, tmp+1); 116 + } 117 + 118 + /* set pixclkdis to 1 */ 119 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 120 + tmp = RREG8(DAC_DATA); 121 + tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 122 + WREG8(DAC_DATA, tmp); 123 + 124 + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 125 + tmp = RREG8(DAC_DATA); 126 + tmp |= MGA1064_REMHEADCTL_CLKDIS; 127 + WREG8(DAC_DATA, tmp); 128 + 129 + /* select PLL Set C */ 130 + tmp = RREG8(MGAREG_MEM_MISC_READ); 131 + tmp |= 0x3 << 2; 132 + WREG8(MGAREG_MEM_MISC_WRITE, tmp); 133 + 134 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 135 + tmp = RREG8(DAC_DATA); 136 + tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; 137 + WREG8(DAC_DATA, tmp); 138 + 139 + udelay(500); 140 + 141 + /* reset the PLL */ 142 + WREG8(DAC_INDEX, MGA1064_VREF_CTL); 143 + tmp = RREG8(DAC_DATA); 144 + tmp &= ~0x04; 145 + WREG8(DAC_DATA, tmp); 146 + 147 + udelay(50); 148 + 149 + /* program pixel pll register */ 150 + WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn); 151 + WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm); 152 + WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp); 153 + 154 + udelay(50); 155 + 156 + /* turn pll on */ 157 + WREG8(DAC_INDEX, MGA1064_VREF_CTL); 158 + tmp = RREG8(DAC_DATA); 159 + tmp |= 0x04; 160 + WREG_DAC(MGA1064_VREF_CTL, tmp); 161 + 162 + udelay(500); 163 + 164 + /* select the pixel pll */ 165 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 166 + tmp = RREG8(DAC_DATA); 167 + tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 168 + tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 169 + WREG8(DAC_DATA, tmp); 170 + 171 + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 172 + tmp = RREG8(DAC_DATA); 173 + tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; 174 + tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; 175 + WREG8(DAC_DATA, tmp); 176 + 177 + /* reset dotclock rate bit */ 178 + WREG8(MGAREG_SEQ_INDEX, 1); 179 + tmp = RREG8(MGAREG_SEQ_DATA); 180 + tmp &= ~0x8; 181 + WREG8(MGAREG_SEQ_DATA, tmp); 182 + 183 + WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 184 + tmp = RREG8(DAC_DATA); 185 + tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 186 + WREG8(DAC_DATA, tmp); 187 + 188 + vcount = RREG8(MGAREG_VCOUNT); 189 + 190 + for (j = 0; j < 30 && pll_locked == false; j++) { 191 + tmpcount = RREG8(MGAREG_VCOUNT); 192 + if (tmpcount < vcount) 193 + vcount = 0; 194 + if ((tmpcount - vcount) > 2) 195 + pll_locked = true; 196 + else 197 + udelay(5); 198 + } 199 + } 200 + 201 + WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 202 + tmp = RREG8(DAC_DATA); 203 + tmp &= ~MGA1064_REMHEADCTL_CLKDIS; 204 + WREG_DAC(MGA1064_REMHEADCTL, tmp); 205 + } 206 + 207 + /* 34 208 * DRM device 35 209 */ 36 210 ··· 216 38 static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = { 217 39 .disable_vidrst = mgag200_bmc_disable_vidrst, 218 40 .enable_vidrst = mgag200_bmc_enable_vidrst, 41 + .pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check, 42 + .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, 219 43 }; 220 44 221 45 struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
+8 -12
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 660 660 { 661 661 struct drm_device *dev = crtc->dev; 662 662 struct mga_device *mdev = to_mga_device(dev); 663 + const struct mgag200_device_funcs *funcs = mdev->funcs; 663 664 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 664 - struct mgag200_pll *pixpll = &mdev->pixpll; 665 - struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 666 665 struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut; 667 666 int ret; 668 667 ··· 673 674 return 0; 674 675 675 676 if (new_crtc_state->mode_changed) { 676 - ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock, 677 - &mgag200_crtc_state->pixpllc); 678 - if (ret) 679 - return ret; 677 + if (funcs->pixpllc_atomic_check) { 678 + ret = funcs->pixpllc_atomic_check(crtc, new_state); 679 + if (ret) 680 + return ret; 681 + } 680 682 } 681 683 682 684 if (new_crtc_state->color_mgmt_changed && new_gamma_lut) { ··· 718 718 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; 719 719 struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 720 720 const struct drm_format_info *format = mgag200_crtc_state->format; 721 - struct mgag200_pll *pixpll = &mdev->pixpll; 722 721 723 722 if (funcs->disable_vidrst) 724 723 funcs->disable_vidrst(mdev); ··· 725 726 mgag200_set_format_regs(mdev, format); 726 727 mgag200_set_mode_regs(mdev, adjusted_mode); 727 728 728 - pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc); 729 + if (funcs->pixpllc_atomic_update) 730 + funcs->pixpllc_atomic_update(crtc, old_state); 729 731 730 732 if (mdev->type == G200_ER) 731 733 mgag200_g200er_reset_tagfifo(mdev); ··· 975 975 struct mga_i2c_chan *i2c = &mdev->i2c; 976 976 struct drm_connector *connector = &mdev->connector; 977 977 int ret; 978 - 979 - ret = mgag200_pixpll_init(&mdev->pixpll, mdev); 980 - if (ret) 981 - return ret; 982 978 983 979 ret = drm_universal_plane_init(dev, primary_plane, 0, 984 980 &mgag200_primary_plane_funcs,
-997
drivers/gpu/drm/mgag200/mgag200_pll.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - 3 - #include <linux/delay.h> 4 - 5 - #include "mgag200_drv.h" 6 - 7 - /* 8 - * G200 9 - */ 10 - 11 - static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock, 12 - struct mgag200_pll_values *pixpllc) 13 - { 14 - struct mga_device *mdev = pixpll->mdev; 15 - struct drm_device *dev = &mdev->base; 16 - struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev); 17 - const int post_div_max = 7; 18 - const int in_div_min = 1; 19 - const int in_div_max = 6; 20 - const int feed_div_min = 7; 21 - const int feed_div_max = 127; 22 - u8 testp, testm, testn; 23 - u8 n = 0, m = 0, p, s; 24 - long f_vco; 25 - long computed; 26 - long delta, tmp_delta; 27 - long ref_clk = g200->ref_clk; 28 - long p_clk_min = g200->pclk_min; 29 - long p_clk_max = g200->pclk_max; 30 - 31 - if (clock > p_clk_max) { 32 - drm_err(dev, "Pixel Clock %ld too high\n", clock); 33 - return -EINVAL; 34 - } 35 - 36 - if (clock < p_clk_min >> 3) 37 - clock = p_clk_min >> 3; 38 - 39 - f_vco = clock; 40 - for (testp = 0; 41 - testp <= post_div_max && f_vco < p_clk_min; 42 - testp = (testp << 1) + 1, f_vco <<= 1) 43 - ; 44 - p = testp + 1; 45 - 46 - delta = clock; 47 - 48 - for (testm = in_div_min; testm <= in_div_max; testm++) { 49 - for (testn = feed_div_min; testn <= feed_div_max; testn++) { 50 - computed = ref_clk * (testn + 1) / (testm + 1); 51 - if (computed < f_vco) 52 - tmp_delta = f_vco - computed; 53 - else 54 - tmp_delta = computed - f_vco; 55 - if (tmp_delta < delta) { 56 - delta = tmp_delta; 57 - m = testm + 1; 58 - n = testn + 1; 59 - } 60 - } 61 - } 62 - f_vco = ref_clk * n / m; 63 - if (f_vco < 100000) 64 - s = 0; 65 - else if (f_vco < 140000) 66 - s = 1; 67 - else if (f_vco < 180000) 68 - s = 2; 69 - else 70 - s = 3; 71 - 72 - drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", 73 - clock, f_vco, m, n, p, s); 74 - 75 - pixpllc->m = m; 76 - pixpllc->n = n; 77 - pixpllc->p = p; 78 - pixpllc->s = s; 79 - 80 - return 0; 81 - } 82 - 83 - static void 84 - mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) 85 - { 86 - struct mga_device *mdev = pixpll->mdev; 87 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 88 - u8 xpixpllcm, xpixpllcn, xpixpllcp; 89 - 90 - pixpllcm = pixpllc->m - 1; 91 - pixpllcn = pixpllc->n - 1; 92 - pixpllcp = pixpllc->p - 1; 93 - pixpllcs = pixpllc->s; 94 - 95 - xpixpllcm = pixpllcm; 96 - xpixpllcn = pixpllcn; 97 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 98 - 99 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 100 - 101 - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 102 - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 103 - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 104 - } 105 - 106 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = { 107 - .compute = mgag200_pixpll_compute_g200, 108 - .update = mgag200_pixpll_update_g200, 109 - }; 110 - 111 - /* 112 - * G200SE 113 - */ 114 - 115 - static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock, 116 - struct mgag200_pll_values *pixpllc) 117 - { 118 - static const unsigned int vcomax = 320000; 119 - static const unsigned int vcomin = 160000; 120 - static const unsigned int pllreffreq = 25000; 121 - 122 - unsigned int delta, tmpdelta, permitteddelta; 123 - unsigned int testp, testm, testn; 124 - unsigned int p, m, n, s; 125 - unsigned int computed; 126 - 127 - m = n = p = s = 0; 128 - delta = 0xffffffff; 129 - permitteddelta = clock * 5 / 1000; 130 - 131 - for (testp = 8; testp > 0; testp /= 2) { 132 - if (clock * testp > vcomax) 133 - continue; 134 - if (clock * testp < vcomin) 135 - continue; 136 - 137 - for (testn = 17; testn < 256; testn++) { 138 - for (testm = 1; testm < 32; testm++) { 139 - computed = (pllreffreq * testn) / (testm * testp); 140 - if (computed > clock) 141 - tmpdelta = computed - clock; 142 - else 143 - tmpdelta = clock - computed; 144 - if (tmpdelta < delta) { 145 - delta = tmpdelta; 146 - m = testm; 147 - n = testn; 148 - p = testp; 149 - } 150 - } 151 - } 152 - } 153 - 154 - if (delta > permitteddelta) { 155 - pr_warn("PLL delta too large\n"); 156 - return -EINVAL; 157 - } 158 - 159 - pixpllc->m = m; 160 - pixpllc->n = n; 161 - pixpllc->p = p; 162 - pixpllc->s = s; 163 - 164 - return 0; 165 - } 166 - 167 - static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll, 168 - const struct mgag200_pll_values *pixpllc) 169 - { 170 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 171 - u8 xpixpllcm, xpixpllcn, xpixpllcp; 172 - struct mga_device *mdev = pixpll->mdev; 173 - 174 - pixpllcm = pixpllc->m - 1; 175 - pixpllcn = pixpllc->n - 1; 176 - pixpllcp = pixpllc->p - 1; 177 - pixpllcs = pixpllc->s; 178 - 179 - xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); 180 - xpixpllcn = pixpllcn; 181 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 182 - 183 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 184 - 185 - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 186 - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 187 - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 188 - } 189 - 190 - static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock, 191 - struct mgag200_pll_values *pixpllc) 192 - { 193 - static const unsigned int vcomax = 1600000; 194 - static const unsigned int vcomin = 800000; 195 - static const unsigned int pllreffreq = 25000; 196 - static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1}; 197 - 198 - unsigned int delta, tmpdelta, permitteddelta; 199 - unsigned int testp, testm, testn; 200 - unsigned int p, m, n, s; 201 - unsigned int computed; 202 - unsigned int fvv; 203 - unsigned int i; 204 - 205 - m = n = p = s = 0; 206 - delta = 0xffffffff; 207 - 208 - if (clock < 25000) 209 - clock = 25000; 210 - clock = clock * 2; 211 - 212 - /* Permited delta is 0.5% as VESA Specification */ 213 - permitteddelta = clock * 5 / 1000; 214 - 215 - for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) { 216 - testp = pvalues_e4[i]; 217 - 218 - if ((clock * testp) > vcomax) 219 - continue; 220 - if ((clock * testp) < vcomin) 221 - continue; 222 - 223 - for (testn = 50; testn <= 256; testn++) { 224 - for (testm = 1; testm <= 32; testm++) { 225 - computed = (pllreffreq * testn) / (testm * testp); 226 - if (computed > clock) 227 - tmpdelta = computed - clock; 228 - else 229 - tmpdelta = clock - computed; 230 - 231 - if (tmpdelta < delta) { 232 - delta = tmpdelta; 233 - m = testm; 234 - n = testn; 235 - p = testp; 236 - } 237 - } 238 - } 239 - } 240 - 241 - fvv = pllreffreq * n / m; 242 - fvv = (fvv - 800000) / 50000; 243 - if (fvv > 15) 244 - fvv = 15; 245 - s = fvv << 1; 246 - 247 - if (delta > permitteddelta) { 248 - pr_warn("PLL delta too large\n"); 249 - return -EINVAL; 250 - } 251 - 252 - pixpllc->m = m; 253 - pixpllc->n = n; 254 - pixpllc->p = p; 255 - pixpllc->s = s; 256 - 257 - return 0; 258 - } 259 - 260 - static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll, 261 - const struct mgag200_pll_values *pixpllc) 262 - { 263 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 264 - u8 xpixpllcm, xpixpllcn, xpixpllcp; 265 - struct mga_device *mdev = pixpll->mdev; 266 - 267 - pixpllcm = pixpllc->m - 1; 268 - pixpllcn = pixpllc->n - 1; 269 - pixpllcp = pixpllc->p - 1; 270 - pixpllcs = pixpllc->s; 271 - 272 - xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); 273 - xpixpllcn = pixpllcn; 274 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 275 - 276 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 277 - 278 - WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm); 279 - WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn); 280 - WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp); 281 - 282 - WREG_DAC(0x1a, 0x09); 283 - msleep(20); 284 - WREG_DAC(0x1a, 0x01); 285 - } 286 - 287 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = { 288 - .compute = mgag200_pixpll_compute_g200se_00, 289 - .update = mgag200_pixpll_update_g200se_00, 290 - }; 291 - 292 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = { 293 - .compute = mgag200_pixpll_compute_g200se_04, 294 - .update = mgag200_pixpll_update_g200se_04, 295 - }; 296 - 297 - /* 298 - * G200WB 299 - */ 300 - 301 - static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock, 302 - struct mgag200_pll_values *pixpllc) 303 - { 304 - static const unsigned int vcomax = 550000; 305 - static const unsigned int vcomin = 150000; 306 - static const unsigned int pllreffreq = 48000; 307 - 308 - unsigned int delta, tmpdelta; 309 - unsigned int testp, testm, testn; 310 - unsigned int p, m, n, s; 311 - unsigned int computed; 312 - 313 - m = n = p = s = 0; 314 - delta = 0xffffffff; 315 - 316 - for (testp = 1; testp < 9; testp++) { 317 - if (clock * testp > vcomax) 318 - continue; 319 - if (clock * testp < vcomin) 320 - continue; 321 - 322 - for (testm = 1; testm < 17; testm++) { 323 - for (testn = 1; testn < 151; testn++) { 324 - computed = (pllreffreq * testn) / (testm * testp); 325 - if (computed > clock) 326 - tmpdelta = computed - clock; 327 - else 328 - tmpdelta = clock - computed; 329 - if (tmpdelta < delta) { 330 - delta = tmpdelta; 331 - n = testn; 332 - m = testm; 333 - p = testp; 334 - s = 0; 335 - } 336 - } 337 - } 338 - } 339 - 340 - pixpllc->m = m; 341 - pixpllc->n = n; 342 - pixpllc->p = p; 343 - pixpllc->s = s; 344 - 345 - return 0; 346 - } 347 - 348 - static void 349 - mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) 350 - { 351 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 352 - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 353 - int i, j, tmpcount, vcount; 354 - struct mga_device *mdev = pixpll->mdev; 355 - bool pll_locked = false; 356 - 357 - pixpllcm = pixpllc->m - 1; 358 - pixpllcn = pixpllc->n - 1; 359 - pixpllcp = pixpllc->p - 1; 360 - pixpllcs = pixpllc->s; 361 - 362 - xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; 363 - xpixpllcn = pixpllcn; 364 - xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp; 365 - 366 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 367 - 368 - for (i = 0; i <= 32 && pll_locked == false; i++) { 369 - if (i > 0) { 370 - WREG8(MGAREG_CRTC_INDEX, 0x1e); 371 - tmp = RREG8(MGAREG_CRTC_DATA); 372 - if (tmp < 0xff) 373 - WREG8(MGAREG_CRTC_DATA, tmp+1); 374 - } 375 - 376 - /* set pixclkdis to 1 */ 377 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 378 - tmp = RREG8(DAC_DATA); 379 - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 380 - WREG8(DAC_DATA, tmp); 381 - 382 - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 383 - tmp = RREG8(DAC_DATA); 384 - tmp |= MGA1064_REMHEADCTL_CLKDIS; 385 - WREG8(DAC_DATA, tmp); 386 - 387 - /* select PLL Set C */ 388 - tmp = RREG8(MGAREG_MEM_MISC_READ); 389 - tmp |= 0x3 << 2; 390 - WREG8(MGAREG_MEM_MISC_WRITE, tmp); 391 - 392 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 393 - tmp = RREG8(DAC_DATA); 394 - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; 395 - WREG8(DAC_DATA, tmp); 396 - 397 - udelay(500); 398 - 399 - /* reset the PLL */ 400 - WREG8(DAC_INDEX, MGA1064_VREF_CTL); 401 - tmp = RREG8(DAC_DATA); 402 - tmp &= ~0x04; 403 - WREG8(DAC_DATA, tmp); 404 - 405 - udelay(50); 406 - 407 - /* program pixel pll register */ 408 - WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn); 409 - WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm); 410 - WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp); 411 - 412 - udelay(50); 413 - 414 - /* turn pll on */ 415 - WREG8(DAC_INDEX, MGA1064_VREF_CTL); 416 - tmp = RREG8(DAC_DATA); 417 - tmp |= 0x04; 418 - WREG_DAC(MGA1064_VREF_CTL, tmp); 419 - 420 - udelay(500); 421 - 422 - /* select the pixel pll */ 423 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 424 - tmp = RREG8(DAC_DATA); 425 - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 426 - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 427 - WREG8(DAC_DATA, tmp); 428 - 429 - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 430 - tmp = RREG8(DAC_DATA); 431 - tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; 432 - tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; 433 - WREG8(DAC_DATA, tmp); 434 - 435 - /* reset dotclock rate bit */ 436 - WREG8(MGAREG_SEQ_INDEX, 1); 437 - tmp = RREG8(MGAREG_SEQ_DATA); 438 - tmp &= ~0x8; 439 - WREG8(MGAREG_SEQ_DATA, tmp); 440 - 441 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 442 - tmp = RREG8(DAC_DATA); 443 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 444 - WREG8(DAC_DATA, tmp); 445 - 446 - vcount = RREG8(MGAREG_VCOUNT); 447 - 448 - for (j = 0; j < 30 && pll_locked == false; j++) { 449 - tmpcount = RREG8(MGAREG_VCOUNT); 450 - if (tmpcount < vcount) 451 - vcount = 0; 452 - if ((tmpcount - vcount) > 2) 453 - pll_locked = true; 454 - else 455 - udelay(5); 456 - } 457 - } 458 - 459 - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 460 - tmp = RREG8(DAC_DATA); 461 - tmp &= ~MGA1064_REMHEADCTL_CLKDIS; 462 - WREG_DAC(MGA1064_REMHEADCTL, tmp); 463 - } 464 - 465 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = { 466 - .compute = mgag200_pixpll_compute_g200wb, 467 - .update = mgag200_pixpll_update_g200wb, 468 - }; 469 - 470 - /* 471 - * G200EV 472 - */ 473 - 474 - static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock, 475 - struct mgag200_pll_values *pixpllc) 476 - { 477 - static const unsigned int vcomax = 550000; 478 - static const unsigned int vcomin = 150000; 479 - static const unsigned int pllreffreq = 50000; 480 - 481 - unsigned int delta, tmpdelta; 482 - unsigned int testp, testm, testn; 483 - unsigned int p, m, n, s; 484 - unsigned int computed; 485 - 486 - m = n = p = s = 0; 487 - delta = 0xffffffff; 488 - 489 - for (testp = 16; testp > 0; testp--) { 490 - if (clock * testp > vcomax) 491 - continue; 492 - if (clock * testp < vcomin) 493 - continue; 494 - 495 - for (testn = 1; testn < 257; testn++) { 496 - for (testm = 1; testm < 17; testm++) { 497 - computed = (pllreffreq * testn) / 498 - (testm * testp); 499 - if (computed > clock) 500 - tmpdelta = computed - clock; 501 - else 502 - tmpdelta = clock - computed; 503 - if (tmpdelta < delta) { 504 - delta = tmpdelta; 505 - n = testn; 506 - m = testm; 507 - p = testp; 508 - } 509 - } 510 - } 511 - } 512 - 513 - pixpllc->m = m; 514 - pixpllc->n = n; 515 - pixpllc->p = p; 516 - pixpllc->s = s; 517 - 518 - return 0; 519 - } 520 - 521 - static void 522 - mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) 523 - { 524 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 525 - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 526 - struct mga_device *mdev = pixpll->mdev; 527 - 528 - pixpllcm = pixpllc->m - 1; 529 - pixpllcn = pixpllc->n - 1; 530 - pixpllcp = pixpllc->p - 1; 531 - pixpllcs = pixpllc->s; 532 - 533 - xpixpllcm = pixpllcm; 534 - xpixpllcn = pixpllcn; 535 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 536 - 537 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 538 - 539 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 540 - tmp = RREG8(DAC_DATA); 541 - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 542 - WREG8(DAC_DATA, tmp); 543 - 544 - tmp = RREG8(MGAREG_MEM_MISC_READ); 545 - tmp |= 0x3 << 2; 546 - WREG8(MGAREG_MEM_MISC_WRITE, tmp); 547 - 548 - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); 549 - tmp = RREG8(DAC_DATA); 550 - WREG8(DAC_DATA, tmp & ~0x40); 551 - 552 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 553 - tmp = RREG8(DAC_DATA); 554 - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 555 - WREG8(DAC_DATA, tmp); 556 - 557 - WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm); 558 - WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn); 559 - WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp); 560 - 561 - udelay(50); 562 - 563 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 564 - tmp = RREG8(DAC_DATA); 565 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 566 - WREG8(DAC_DATA, tmp); 567 - 568 - udelay(500); 569 - 570 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 571 - tmp = RREG8(DAC_DATA); 572 - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 573 - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 574 - WREG8(DAC_DATA, tmp); 575 - 576 - WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); 577 - tmp = RREG8(DAC_DATA); 578 - WREG8(DAC_DATA, tmp | 0x40); 579 - 580 - tmp = RREG8(MGAREG_MEM_MISC_READ); 581 - tmp |= (0x3 << 2); 582 - WREG8(MGAREG_MEM_MISC_WRITE, tmp); 583 - 584 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 585 - tmp = RREG8(DAC_DATA); 586 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 587 - WREG8(DAC_DATA, tmp); 588 - } 589 - 590 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = { 591 - .compute = mgag200_pixpll_compute_g200ev, 592 - .update = mgag200_pixpll_update_g200ev, 593 - }; 594 - 595 - /* 596 - * G200EH 597 - */ 598 - 599 - static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock, 600 - struct mgag200_pll_values *pixpllc) 601 - { 602 - static const unsigned int vcomax = 800000; 603 - static const unsigned int vcomin = 400000; 604 - static const unsigned int pllreffreq = 33333; 605 - 606 - unsigned int delta, tmpdelta; 607 - unsigned int testp, testm, testn; 608 - unsigned int p, m, n, s; 609 - unsigned int computed; 610 - 611 - m = n = p = s = 0; 612 - delta = 0xffffffff; 613 - 614 - for (testp = 16; testp > 0; testp >>= 1) { 615 - if (clock * testp > vcomax) 616 - continue; 617 - if (clock * testp < vcomin) 618 - continue; 619 - 620 - for (testm = 1; testm < 33; testm++) { 621 - for (testn = 17; testn < 257; testn++) { 622 - computed = (pllreffreq * testn) / (testm * testp); 623 - if (computed > clock) 624 - tmpdelta = computed - clock; 625 - else 626 - tmpdelta = clock - computed; 627 - if (tmpdelta < delta) { 628 - delta = tmpdelta; 629 - n = testn; 630 - m = testm; 631 - p = testp; 632 - } 633 - } 634 - } 635 - } 636 - 637 - pixpllc->m = m; 638 - pixpllc->n = n; 639 - pixpllc->p = p; 640 - pixpllc->s = s; 641 - 642 - return 0; 643 - } 644 - 645 - static void 646 - mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) 647 - { 648 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 649 - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 650 - int i, j, tmpcount, vcount; 651 - struct mga_device *mdev = pixpll->mdev; 652 - bool pll_locked = false; 653 - 654 - pixpllcm = pixpllc->m - 1; 655 - pixpllcn = pixpllc->n - 1; 656 - pixpllcp = pixpllc->p - 1; 657 - pixpllcs = pixpllc->s; 658 - 659 - xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm; 660 - xpixpllcn = pixpllcn; 661 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 662 - 663 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 664 - 665 - for (i = 0; i <= 32 && pll_locked == false; i++) { 666 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 667 - tmp = RREG8(DAC_DATA); 668 - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 669 - WREG8(DAC_DATA, tmp); 670 - 671 - tmp = RREG8(MGAREG_MEM_MISC_READ); 672 - tmp |= 0x3 << 2; 673 - WREG8(MGAREG_MEM_MISC_WRITE, tmp); 674 - 675 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 676 - tmp = RREG8(DAC_DATA); 677 - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 678 - WREG8(DAC_DATA, tmp); 679 - 680 - udelay(500); 681 - 682 - WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm); 683 - WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn); 684 - WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp); 685 - 686 - udelay(500); 687 - 688 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 689 - tmp = RREG8(DAC_DATA); 690 - tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; 691 - tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; 692 - WREG8(DAC_DATA, tmp); 693 - 694 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 695 - tmp = RREG8(DAC_DATA); 696 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 697 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 698 - WREG8(DAC_DATA, tmp); 699 - 700 - vcount = RREG8(MGAREG_VCOUNT); 701 - 702 - for (j = 0; j < 30 && pll_locked == false; j++) { 703 - tmpcount = RREG8(MGAREG_VCOUNT); 704 - if (tmpcount < vcount) 705 - vcount = 0; 706 - if ((tmpcount - vcount) > 2) 707 - pll_locked = true; 708 - else 709 - udelay(5); 710 - } 711 - } 712 - } 713 - 714 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = { 715 - .compute = mgag200_pixpll_compute_g200eh, 716 - .update = mgag200_pixpll_update_g200eh, 717 - }; 718 - 719 - /* 720 - * G200EH3 721 - */ 722 - 723 - static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock, 724 - struct mgag200_pll_values *pixpllc) 725 - { 726 - static const unsigned int vcomax = 3000000; 727 - static const unsigned int vcomin = 1500000; 728 - static const unsigned int pllreffreq = 25000; 729 - 730 - unsigned int delta, tmpdelta; 731 - unsigned int testp, testm, testn; 732 - unsigned int p, m, n, s; 733 - unsigned int computed; 734 - 735 - m = n = p = s = 0; 736 - delta = 0xffffffff; 737 - testp = 0; 738 - 739 - for (testm = 150; testm >= 6; testm--) { 740 - if (clock * testm > vcomax) 741 - continue; 742 - if (clock * testm < vcomin) 743 - continue; 744 - for (testn = 120; testn >= 60; testn--) { 745 - computed = (pllreffreq * testn) / testm; 746 - if (computed > clock) 747 - tmpdelta = computed - clock; 748 - else 749 - tmpdelta = clock - computed; 750 - if (tmpdelta < delta) { 751 - delta = tmpdelta; 752 - n = testn + 1; 753 - m = testm + 1; 754 - p = testp + 1; 755 - } 756 - if (delta == 0) 757 - break; 758 - } 759 - if (delta == 0) 760 - break; 761 - } 762 - 763 - pixpllc->m = m; 764 - pixpllc->n = n; 765 - pixpllc->p = p; 766 - pixpllc->s = s; 767 - 768 - return 0; 769 - } 770 - 771 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = { 772 - .compute = mgag200_pixpll_compute_g200eh3, 773 - .update = mgag200_pixpll_update_g200eh, // same as G200EH 774 - }; 775 - 776 - /* 777 - * G200ER 778 - */ 779 - 780 - static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock, 781 - struct mgag200_pll_values *pixpllc) 782 - { 783 - static const unsigned int vcomax = 1488000; 784 - static const unsigned int vcomin = 1056000; 785 - static const unsigned int pllreffreq = 48000; 786 - static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; 787 - 788 - unsigned int delta, tmpdelta; 789 - int testr, testn, testm, testo; 790 - unsigned int p, m, n, s; 791 - unsigned int computed, vco; 792 - 793 - m = n = p = s = 0; 794 - delta = 0xffffffff; 795 - 796 - for (testr = 0; testr < 4; testr++) { 797 - if (delta == 0) 798 - break; 799 - for (testn = 5; testn < 129; testn++) { 800 - if (delta == 0) 801 - break; 802 - for (testm = 3; testm >= 0; testm--) { 803 - if (delta == 0) 804 - break; 805 - for (testo = 5; testo < 33; testo++) { 806 - vco = pllreffreq * (testn + 1) / 807 - (testr + 1); 808 - if (vco < vcomin) 809 - continue; 810 - if (vco > vcomax) 811 - continue; 812 - computed = vco / (m_div_val[testm] * (testo + 1)); 813 - if (computed > clock) 814 - tmpdelta = computed - clock; 815 - else 816 - tmpdelta = clock - computed; 817 - if (tmpdelta < delta) { 818 - delta = tmpdelta; 819 - m = (testm | (testo << 3)) + 1; 820 - n = testn + 1; 821 - p = testr + 1; 822 - s = testr; 823 - } 824 - } 825 - } 826 - } 827 - } 828 - 829 - pixpllc->m = m; 830 - pixpllc->n = n; 831 - pixpllc->p = p; 832 - pixpllc->s = s; 833 - 834 - return 0; 835 - } 836 - 837 - static void 838 - mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc) 839 - { 840 - unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 841 - u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 842 - struct mga_device *mdev = pixpll->mdev; 843 - 844 - pixpllcm = pixpllc->m - 1; 845 - pixpllcn = pixpllc->n - 1; 846 - pixpllcp = pixpllc->p - 1; 847 - pixpllcs = pixpllc->s; 848 - 849 - xpixpllcm = pixpllcm; 850 - xpixpllcn = pixpllcn; 851 - xpixpllcp = (pixpllcs << 3) | pixpllcp; 852 - 853 - WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 854 - 855 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 856 - tmp = RREG8(DAC_DATA); 857 - tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 858 - WREG8(DAC_DATA, tmp); 859 - 860 - WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 861 - tmp = RREG8(DAC_DATA); 862 - tmp |= MGA1064_REMHEADCTL_CLKDIS; 863 - WREG8(DAC_DATA, tmp); 864 - 865 - tmp = RREG8(MGAREG_MEM_MISC_READ); 866 - tmp |= (0x3<<2) | 0xc0; 867 - WREG8(MGAREG_MEM_MISC_WRITE, tmp); 868 - 869 - WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 870 - tmp = RREG8(DAC_DATA); 871 - tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 872 - tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 873 - WREG8(DAC_DATA, tmp); 874 - 875 - udelay(500); 876 - 877 - WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); 878 - WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); 879 - WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); 880 - 881 - udelay(50); 882 - } 883 - 884 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = { 885 - .compute = mgag200_pixpll_compute_g200er, 886 - .update = mgag200_pixpll_update_g200er, 887 - }; 888 - 889 - /* 890 - * G200EW3 891 - */ 892 - 893 - static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock, 894 - struct mgag200_pll_values *pixpllc) 895 - { 896 - static const unsigned int vcomax = 800000; 897 - static const unsigned int vcomin = 400000; 898 - static const unsigned int pllreffreq = 25000; 899 - 900 - unsigned int delta, tmpdelta; 901 - unsigned int testp, testm, testn, testp2; 902 - unsigned int p, m, n, s; 903 - unsigned int computed; 904 - 905 - m = n = p = s = 0; 906 - delta = 0xffffffff; 907 - 908 - for (testp = 1; testp < 8; testp++) { 909 - for (testp2 = 1; testp2 < 8; testp2++) { 910 - if (testp < testp2) 911 - continue; 912 - if ((clock * testp * testp2) > vcomax) 913 - continue; 914 - if ((clock * testp * testp2) < vcomin) 915 - continue; 916 - for (testm = 1; testm < 26; testm++) { 917 - for (testn = 32; testn < 2048 ; testn++) { 918 - computed = (pllreffreq * testn) / (testm * testp * testp2); 919 - if (computed > clock) 920 - tmpdelta = computed - clock; 921 - else 922 - tmpdelta = clock - computed; 923 - if (tmpdelta < delta) { 924 - delta = tmpdelta; 925 - m = testm + 1; 926 - n = testn + 1; 927 - p = testp + 1; 928 - s = testp2; 929 - } 930 - } 931 - } 932 - } 933 - } 934 - 935 - pixpllc->m = m; 936 - pixpllc->n = n; 937 - pixpllc->p = p; 938 - pixpllc->s = s; 939 - 940 - return 0; 941 - } 942 - 943 - static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = { 944 - .compute = mgag200_pixpll_compute_g200ew3, 945 - .update = mgag200_pixpll_update_g200wb, // same as G200WB 946 - }; 947 - 948 - /* 949 - * PLL initialization 950 - */ 951 - 952 - int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev) 953 - { 954 - struct drm_device *dev = &mdev->base; 955 - struct mgag200_g200se_device *g200se; 956 - 957 - pixpll->mdev = mdev; 958 - 959 - switch (mdev->type) { 960 - case G200_PCI: 961 - case G200_AGP: 962 - pixpll->funcs = &mgag200_pixpll_funcs_g200; 963 - break; 964 - case G200_SE_A: 965 - case G200_SE_B: 966 - g200se = to_mgag200_g200se_device(dev); 967 - 968 - if (g200se->unique_rev_id >= 0x04) 969 - pixpll->funcs = &mgag200_pixpll_funcs_g200se_04; 970 - else 971 - pixpll->funcs = &mgag200_pixpll_funcs_g200se_00; 972 - break; 973 - case G200_WB: 974 - pixpll->funcs = &mgag200_pixpll_funcs_g200wb; 975 - break; 976 - case G200_EV: 977 - pixpll->funcs = &mgag200_pixpll_funcs_g200ev; 978 - break; 979 - case G200_EH: 980 - pixpll->funcs = &mgag200_pixpll_funcs_g200eh; 981 - break; 982 - case G200_EH3: 983 - pixpll->funcs = &mgag200_pixpll_funcs_g200eh3; 984 - break; 985 - case G200_ER: 986 - pixpll->funcs = &mgag200_pixpll_funcs_g200er; 987 - break; 988 - case G200_EW3: 989 - pixpll->funcs = &mgag200_pixpll_funcs_g200ew3; 990 - break; 991 - default: 992 - drm_err(dev, "unknown device type %d\n", mdev->type); 993 - return -ENODEV; 994 - } 995 - 996 - return 0; 997 - }