1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/delay.h> 4 #include <linux/pci.h> 5 6 #include <drm/drm_atomic.h> 7 #include <drm/drm_atomic_helper.h> 8 #include <drm/drm_drv.h> 9 #include <drm/drm_gem_atomic_helper.h> 10 #include <drm/drm_probe_helper.h> 11 #include <drm/drm_vblank.h> 12 13 #include "mgag200_drv.h" 14 15 static void mgag200_g200er_init_registers(struct mga_device *mdev) 16 { 17 static const u8 dacvalue[] = { 18 MGAG200_DAC_DEFAULT(0x00, 0xc9, 0x1f, 0x00, 0x00, 0x00) 19 }; 20 21 size_t i; 22 23 for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { 24 if ((i <= 0x17) || 25 (i == 0x1b) || 26 (i == 0x1c) || 27 ((i >= 0x1f) && (i <= 0x29)) || 28 ((i >= 0x30) && (i <= 0x37))) 29 continue; 30 WREG_DAC(i, dacvalue[i]); 31 } 32 33 WREG_DAC(0x90, 0); /* G200ER specific */ 34 35 mgag200_init_registers(mdev); 36 37 WREG_ECRT(0x24, 0x5); /* G200ER specific */ 38 } 39 40 static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) 41 { 42 static const uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */ 43 u32 memctl; 44 45 memctl = RREG32(MGAREG_MEMCTL); 46 47 memctl |= RESET_FLAG; 48 WREG32(MGAREG_MEMCTL, memctl); 49 50 udelay(1000); 51 52 memctl &= ~RESET_FLAG; 53 WREG32(MGAREG_MEMCTL, memctl); 54 } 55 56 /* 57 * PIXPLLC 58 */ 59 60 static int mgag200_g200er_pixpllc_atomic_check(struct drm_crtc *crtc, 61 struct drm_atomic_state *new_state) 62 { 63 static const unsigned int vcomax = 1488000; 64 static const unsigned int vcomin = 1056000; 65 static const unsigned int pllreffreq = 48000; 66 static const unsigned int m_div_val[] = { 1, 2, 4, 8 }; 67 68 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc); 69 struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state); 70 long clock = new_crtc_state->mode.clock; 71 struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc; 72 unsigned int delta, tmpdelta; 73 int testr, testn, testm, testo; 74 unsigned int p, m, n, s; 75 unsigned int computed, vco; 76 77 m = n = p = s = 0; 78 delta = 0xffffffff; 79 80 for (testr = 0; testr < 4; testr++) { 81 if (delta == 0) 82 break; 83 for (testn = 5; testn < 129; testn++) { 84 if (delta == 0) 85 break; 86 for (testm = 3; testm >= 0; testm--) { 87 if (delta == 0) 88 break; 89 for (testo = 5; testo < 33; testo++) { 90 vco = pllreffreq * (testn + 1) / 91 (testr + 1); 92 if (vco < vcomin) 93 continue; 94 if (vco > vcomax) 95 continue; 96 computed = vco / (m_div_val[testm] * (testo + 1)); 97 if (computed > clock) 98 tmpdelta = computed - clock; 99 else 100 tmpdelta = clock - computed; 101 if (tmpdelta < delta) { 102 delta = tmpdelta; 103 m = (testm | (testo << 3)) + 1; 104 n = testn + 1; 105 p = testr + 1; 106 s = testr; 107 } 108 } 109 } 110 } 111 } 112 113 pixpllc->m = m; 114 pixpllc->n = n; 115 pixpllc->p = p; 116 pixpllc->s = s; 117 118 return 0; 119 } 120 121 static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc, 122 struct drm_atomic_state *old_state) 123 { 124 struct drm_device *dev = crtc->dev; 125 struct mga_device *mdev = to_mga_device(dev); 126 struct drm_crtc_state *crtc_state = crtc->state; 127 struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 128 struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc; 129 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs; 130 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp; 131 132 pixpllcm = pixpllc->m - 1; 133 pixpllcn = pixpllc->n - 1; 134 pixpllcp = pixpllc->p - 1; 135 pixpllcs = pixpllc->s; 136 137 xpixpllcm = pixpllcm; 138 xpixpllcn = pixpllcn; 139 xpixpllcp = (pixpllcs << 3) | pixpllcp; 140 141 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK); 142 143 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 144 tmp = RREG8(DAC_DATA); 145 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; 146 WREG8(DAC_DATA, tmp); 147 148 WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 149 tmp = RREG8(DAC_DATA); 150 tmp |= MGA1064_REMHEADCTL_CLKDIS; 151 WREG8(DAC_DATA, tmp); 152 153 tmp = RREG8(MGAREG_MEM_MISC_READ); 154 tmp |= (0x3<<2) | 0xc0; 155 WREG8(MGAREG_MEM_MISC_WRITE, tmp); 156 157 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); 158 tmp = RREG8(DAC_DATA); 159 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; 160 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; 161 WREG8(DAC_DATA, tmp); 162 163 udelay(500); 164 165 WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn); 166 WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm); 167 WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp); 168 169 udelay(50); 170 } 171 172 /* 173 * Mode-setting pipeline 174 */ 175 176 static const struct drm_plane_helper_funcs mgag200_g200er_primary_plane_helper_funcs = { 177 MGAG200_PRIMARY_PLANE_HELPER_FUNCS, 178 }; 179 180 static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = { 181 MGAG200_PRIMARY_PLANE_FUNCS, 182 }; 183 184 static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc, 185 struct drm_atomic_state *old_state) 186 { 187 struct drm_device *dev = crtc->dev; 188 struct mga_device *mdev = to_mga_device(dev); 189 const struct mgag200_device_funcs *funcs = mdev->funcs; 190 struct drm_crtc_state *crtc_state = crtc->state; 191 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; 192 struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state); 193 const struct drm_format_info *format = mgag200_crtc_state->format; 194 195 mgag200_set_format_regs(mdev, format); 196 mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst); 197 198 if (funcs->pixpllc_atomic_update) 199 funcs->pixpllc_atomic_update(crtc, old_state); 200 201 mgag200_g200er_reset_tagfifo(mdev); 202 203 if (crtc_state->gamma_lut) 204 mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data); 205 else 206 mgag200_crtc_set_gamma_linear(mdev, format); 207 208 mgag200_enable_display(mdev); 209 210 drm_crtc_vblank_on(crtc); 211 } 212 213 static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = { 214 .mode_valid = mgag200_crtc_helper_mode_valid, 215 .atomic_check = mgag200_crtc_helper_atomic_check, 216 .atomic_flush = mgag200_crtc_helper_atomic_flush, 217 .atomic_enable = mgag200_g200er_crtc_helper_atomic_enable, 218 .atomic_disable = mgag200_crtc_helper_atomic_disable, 219 .get_scanout_position = mgag200_crtc_helper_get_scanout_position, 220 }; 221 222 static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = { 223 MGAG200_CRTC_FUNCS, 224 }; 225 226 static int mgag200_g200er_pipeline_init(struct mga_device *mdev) 227 { 228 struct drm_device *dev = &mdev->base; 229 struct drm_plane *primary_plane = &mdev->primary_plane; 230 struct drm_crtc *crtc = &mdev->crtc; 231 int ret; 232 233 ret = drm_universal_plane_init(dev, primary_plane, 0, 234 &mgag200_g200er_primary_plane_funcs, 235 mgag200_primary_plane_formats, 236 mgag200_primary_plane_formats_size, 237 mgag200_primary_plane_fmtmods, 238 DRM_PLANE_TYPE_PRIMARY, NULL); 239 if (ret) { 240 drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); 241 return ret; 242 } 243 drm_plane_helper_add(primary_plane, &mgag200_g200er_primary_plane_helper_funcs); 244 drm_plane_enable_fb_damage_clips(primary_plane); 245 246 ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, 247 &mgag200_g200er_crtc_funcs, NULL); 248 if (ret) { 249 drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret); 250 return ret; 251 } 252 drm_crtc_helper_add(crtc, &mgag200_g200er_crtc_helper_funcs); 253 254 /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */ 255 drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE); 256 drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE); 257 258 ret = mgag200_vga_bmc_output_init(mdev); 259 if (ret) 260 return ret; 261 262 return 0; 263 } 264 265 /* 266 * DRM device 267 */ 268 269 static const struct mgag200_device_info mgag200_g200er_device_info = 270 MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false); 271 272 static const struct mgag200_device_funcs mgag200_g200er_device_funcs = { 273 .pixpllc_atomic_check = mgag200_g200er_pixpllc_atomic_check, 274 .pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update, 275 }; 276 277 struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv) 278 { 279 struct mga_device *mdev; 280 struct drm_device *dev; 281 resource_size_t vram_available; 282 int ret; 283 284 mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base); 285 if (IS_ERR(mdev)) 286 return mdev; 287 dev = &mdev->base; 288 289 pci_set_drvdata(pdev, dev); 290 291 ret = mgag200_device_preinit(mdev); 292 if (ret) 293 return ERR_PTR(ret); 294 295 ret = mgag200_device_init(mdev, &mgag200_g200er_device_info, 296 &mgag200_g200er_device_funcs); 297 if (ret) 298 return ERR_PTR(ret); 299 300 mgag200_g200er_init_registers(mdev); 301 302 vram_available = mgag200_device_probe_vram(mdev); 303 304 ret = mgag200_mode_config_init(mdev, vram_available); 305 if (ret) 306 return ERR_PTR(ret); 307 308 ret = mgag200_g200er_pipeline_init(mdev); 309 if (ret) 310 return ERR_PTR(ret); 311 312 drm_mode_config_reset(dev); 313 drm_kms_helper_poll_init(dev); 314 315 ret = drm_vblank_init(dev, 1); 316 if (ret) 317 return ERR_PTR(ret); 318 319 return mdev; 320 } 321