xref: /linux/drivers/gpu/drm/mgag200/mgag200_g200se.c (revision 566ab427f827b0256d3e8ce0235d088e6a9c28bd)
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 int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
16 {
17 	struct device *dev = &pdev->dev;
18 	bool has_sgram;
19 	u32 option;
20 	int err;
21 
22 	err = pci_read_config_dword(pdev, PCI_MGA_OPTION, &option);
23 	if (err != PCIBIOS_SUCCESSFUL) {
24 		dev_err(dev, "pci_read_config_dword(PCI_MGA_OPTION) failed: %d\n", err);
25 		return pcibios_err_to_errno(err);
26 	}
27 
28 	has_sgram = !!(option & PCI_MGA_OPTION_HARDPWMSK);
29 
30 	option = 0x40049120;
31 	if (has_sgram)
32 		option |= PCI_MGA_OPTION_HARDPWMSK;
33 
34 	return mgag200_init_pci_options(pdev, option, 0x00008000);
35 }
36 
37 static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
38 {
39 	static const u8 dacvalue[] = {
40 		MGAG200_DAC_DEFAULT(0x03,
41 				    MGA1064_PIX_CLK_CTL_SEL_PLL,
42 				    MGA1064_MISC_CTL_DAC_EN |
43 				    MGA1064_MISC_CTL_VGA8 |
44 				    MGA1064_MISC_CTL_DAC_RAM_CS,
45 				    0x00, 0x00, 0x00)
46 	};
47 
48 	struct mga_device *mdev = &g200se->base;
49 	size_t i;
50 
51 	for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
52 		if ((i <= 0x17) ||
53 		    (i == 0x1b) ||
54 		    (i == 0x1c) ||
55 		    ((i >= 0x1f) && (i <= 0x29)) ||
56 		    ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) ||
57 		    ((i >= 0x30) && (i <= 0x37)))
58 			continue;
59 		WREG_DAC(i, dacvalue[i]);
60 	}
61 
62 	mgag200_init_registers(mdev);
63 }
64 
65 static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
66 					const struct drm_display_mode *mode,
67 					const struct drm_format_info *format)
68 {
69 	struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
70 	unsigned int hiprilvl;
71 	u8 crtcext6;
72 
73 	if  (g200se->unique_rev_id >= 0x04) {
74 		hiprilvl = 0;
75 	} else if (g200se->unique_rev_id >= 0x02) {
76 		unsigned int bpp;
77 		unsigned long mb;
78 
79 		if (format->cpp[0] * 8 > 16)
80 			bpp = 32;
81 		else if (format->cpp[0] * 8 > 8)
82 			bpp = 16;
83 		else
84 			bpp = 8;
85 
86 		mb = (mode->clock * bpp) / 1000;
87 		if (mb > 3100)
88 			hiprilvl = 0;
89 		else if (mb > 2600)
90 			hiprilvl = 1;
91 		else if (mb > 1900)
92 			hiprilvl = 2;
93 		else if (mb > 1160)
94 			hiprilvl = 3;
95 		else if (mb > 440)
96 			hiprilvl = 4;
97 		else
98 			hiprilvl = 5;
99 
100 	} else if (g200se->unique_rev_id >= 0x01) {
101 		hiprilvl = 3;
102 	} else {
103 		hiprilvl = 4;
104 	}
105 
106 	crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */
107 
108 	WREG_ECRT(0x06, crtcext6);
109 }
110 
111 /*
112  * PIXPLLC
113  */
114 
115 static int mgag200_g200se_00_pixpllc_atomic_check(struct drm_crtc *crtc,
116 						  struct drm_atomic_state *new_state)
117 {
118 	static const unsigned int vcomax = 320000;
119 	static const unsigned int vcomin = 160000;
120 	static const unsigned int pllreffreq = 25000;
121 
122 	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
123 	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
124 	long clock = new_crtc_state->mode.clock;
125 	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
126 	unsigned int delta, tmpdelta, permitteddelta;
127 	unsigned int testp, testm, testn;
128 	unsigned int p, m, n, s;
129 	unsigned int computed;
130 
131 	m = n = p = s = 0;
132 	delta = 0xffffffff;
133 	permitteddelta = clock * 5 / 1000;
134 
135 	for (testp = 8; testp > 0; testp /= 2) {
136 		if (clock * testp > vcomax)
137 			continue;
138 		if (clock * testp < vcomin)
139 			continue;
140 
141 		for (testn = 17; testn < 256; testn++) {
142 			for (testm = 1; testm < 32; testm++) {
143 				computed = (pllreffreq * testn) / (testm * testp);
144 				if (computed > clock)
145 					tmpdelta = computed - clock;
146 				else
147 					tmpdelta = clock - computed;
148 				if (tmpdelta < delta) {
149 					delta = tmpdelta;
150 					m = testm;
151 					n = testn;
152 					p = testp;
153 				}
154 			}
155 		}
156 	}
157 
158 	if (delta > permitteddelta) {
159 		pr_warn("PLL delta too large\n");
160 		return -EINVAL;
161 	}
162 
163 	pixpllc->m = m;
164 	pixpllc->n = n;
165 	pixpllc->p = p;
166 	pixpllc->s = s;
167 
168 	return 0;
169 }
170 
171 static void mgag200_g200se_00_pixpllc_atomic_update(struct drm_crtc *crtc,
172 						    struct drm_atomic_state *old_state)
173 {
174 	struct drm_device *dev = crtc->dev;
175 	struct mga_device *mdev = to_mga_device(dev);
176 	struct drm_crtc_state *crtc_state = crtc->state;
177 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
178 	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
179 	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
180 	u8 xpixpllcm, xpixpllcn, xpixpllcp;
181 
182 	pixpllcm = pixpllc->m - 1;
183 	pixpllcn = pixpllc->n - 1;
184 	pixpllcp = pixpllc->p - 1;
185 	pixpllcs = pixpllc->s;
186 
187 	xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
188 	xpixpllcn = pixpllcn;
189 	xpixpllcp = (pixpllcs << 3) | pixpllcp;
190 
191 	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
192 
193 	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
194 	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
195 	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
196 }
197 
198 static int mgag200_g200se_04_pixpllc_atomic_check(struct drm_crtc *crtc,
199 						  struct drm_atomic_state *new_state)
200 {
201 	static const unsigned int vcomax = 1600000;
202 	static const unsigned int vcomin = 800000;
203 	static const unsigned int pllreffreq = 25000;
204 	static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
205 
206 	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
207 	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
208 	long clock = new_crtc_state->mode.clock;
209 	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
210 	unsigned int delta, tmpdelta, permitteddelta;
211 	unsigned int testp, testm, testn;
212 	unsigned int p, m, n, s;
213 	unsigned int computed;
214 	unsigned int fvv;
215 	unsigned int i;
216 
217 	m = n = p = s = 0;
218 	delta = 0xffffffff;
219 
220 	if (clock < 25000)
221 		clock = 25000;
222 	clock = clock * 2;
223 
224 	/* Permited delta is 0.5% as VESA Specification */
225 	permitteddelta = clock * 5 / 1000;
226 
227 	for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
228 		testp = pvalues_e4[i];
229 
230 		if ((clock * testp) > vcomax)
231 			continue;
232 		if ((clock * testp) < vcomin)
233 			continue;
234 
235 		for (testn = 50; testn <= 256; testn++) {
236 			for (testm = 1; testm <= 32; testm++) {
237 				computed = (pllreffreq * testn) / (testm * testp);
238 				if (computed > clock)
239 					tmpdelta = computed - clock;
240 				else
241 					tmpdelta = clock - computed;
242 
243 				if (tmpdelta < delta) {
244 					delta = tmpdelta;
245 					m = testm;
246 					n = testn;
247 					p = testp;
248 				}
249 			}
250 		}
251 	}
252 
253 	fvv = pllreffreq * n / m;
254 	fvv = (fvv - 800000) / 50000;
255 	if (fvv > 15)
256 		fvv = 15;
257 	s = fvv << 1;
258 
259 	if (delta > permitteddelta) {
260 		pr_warn("PLL delta too large\n");
261 		return -EINVAL;
262 	}
263 
264 	pixpllc->m = m;
265 	pixpllc->n = n;
266 	pixpllc->p = p;
267 	pixpllc->s = s;
268 
269 	return 0;
270 }
271 
272 static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc,
273 						    struct drm_atomic_state *old_state)
274 {
275 	struct drm_device *dev = crtc->dev;
276 	struct mga_device *mdev = to_mga_device(dev);
277 	struct drm_crtc_state *crtc_state = crtc->state;
278 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
279 	struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
280 	unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
281 	u8 xpixpllcm, xpixpllcn, xpixpllcp;
282 
283 	pixpllcm = pixpllc->m - 1;
284 	pixpllcn = pixpllc->n - 1;
285 	pixpllcp = pixpllc->p - 1;
286 	pixpllcs = pixpllc->s;
287 
288 	// For G200SE A, BIT(7) should be set unconditionally.
289 	xpixpllcm = BIT(7) | pixpllcm;
290 	xpixpllcn = pixpllcn;
291 	xpixpllcp = (pixpllcs << 3) | pixpllcp;
292 
293 	WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
294 
295 	WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
296 	WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
297 	WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
298 
299 	WREG_DAC(0x1a, 0x09);
300 	msleep(20);
301 	WREG_DAC(0x1a, 0x01);
302 }
303 
304 /*
305  * Mode-setting pipeline
306  */
307 
308 static const struct drm_plane_helper_funcs mgag200_g200se_primary_plane_helper_funcs = {
309 	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
310 };
311 
312 static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = {
313 	MGAG200_PRIMARY_PLANE_FUNCS,
314 };
315 
316 static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc,
317 						     struct drm_atomic_state *old_state)
318 {
319 	struct drm_device *dev = crtc->dev;
320 	struct mga_device *mdev = to_mga_device(dev);
321 	const struct mgag200_device_funcs *funcs = mdev->funcs;
322 	struct drm_crtc_state *crtc_state = crtc->state;
323 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
324 	struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
325 	const struct drm_format_info *format = mgag200_crtc_state->format;
326 
327 	mgag200_set_format_regs(mdev, format);
328 	mgag200_set_mode_regs(mdev, adjusted_mode, mgag200_crtc_state->set_vidrst);
329 
330 	if (funcs->pixpllc_atomic_update)
331 		funcs->pixpllc_atomic_update(crtc, old_state);
332 
333 	mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
334 
335 	if (crtc_state->gamma_lut)
336 		mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
337 	else
338 		mgag200_crtc_set_gamma_linear(mdev, format);
339 
340 	mgag200_enable_display(mdev);
341 
342 	drm_crtc_vblank_on(crtc);
343 }
344 
345 static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = {
346 	.mode_valid = mgag200_crtc_helper_mode_valid,
347 	.atomic_check = mgag200_crtc_helper_atomic_check,
348 	.atomic_flush = mgag200_crtc_helper_atomic_flush,
349 	.atomic_enable = mgag200_g200se_crtc_helper_atomic_enable,
350 	.atomic_disable = mgag200_crtc_helper_atomic_disable,
351 	.get_scanout_position = mgag200_crtc_helper_get_scanout_position,
352 };
353 
354 static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
355 	MGAG200_CRTC_FUNCS,
356 };
357 
358 static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
359 {
360 	struct drm_device *dev = &mdev->base;
361 	struct drm_plane *primary_plane = &mdev->primary_plane;
362 	struct drm_crtc *crtc = &mdev->crtc;
363 	int ret;
364 
365 	ret = drm_universal_plane_init(dev, primary_plane, 0,
366 				       &mgag200_g200se_primary_plane_funcs,
367 				       mgag200_primary_plane_formats,
368 				       mgag200_primary_plane_formats_size,
369 				       mgag200_primary_plane_fmtmods,
370 				       DRM_PLANE_TYPE_PRIMARY, NULL);
371 	if (ret) {
372 		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
373 		return ret;
374 	}
375 	drm_plane_helper_add(primary_plane, &mgag200_g200se_primary_plane_helper_funcs);
376 	drm_plane_enable_fb_damage_clips(primary_plane);
377 
378 	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
379 					&mgag200_g200se_crtc_funcs, NULL);
380 	if (ret) {
381 		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
382 		return ret;
383 	}
384 	drm_crtc_helper_add(crtc, &mgag200_g200se_crtc_helper_funcs);
385 
386 	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
387 	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
388 	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
389 
390 	ret = mgag200_vga_bmc_output_init(mdev);
391 	if (ret)
392 		return ret;
393 
394 	return 0;
395 }
396 
397 /*
398  * DRM device
399  */
400 
401 static const struct mgag200_device_info mgag200_g200se_a_01_device_info =
402 	MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, true);
403 
404 static const struct mgag200_device_info mgag200_g200se_a_02_device_info =
405 	MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, true);
406 
407 static const struct mgag200_device_info mgag200_g200se_a_03_device_info =
408 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false);
409 
410 static const struct mgag200_device_info mgag200_g200se_b_01_device_info =
411 	MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, false);
412 
413 static const struct mgag200_device_info mgag200_g200se_b_02_device_info =
414 	MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, false);
415 
416 static const struct mgag200_device_info mgag200_g200se_b_03_device_info =
417 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false);
418 
419 static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200se)
420 {
421 	struct mga_device *mdev = &g200se->base;
422 	struct drm_device *dev = &mdev->base;
423 
424 	/* stash G200 SE model number for later use */
425 	g200se->unique_rev_id = RREG32(0x1e24);
426 	if (!g200se->unique_rev_id)
427 		return -ENODEV;
428 
429 	drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id);
430 
431 	return 0;
432 }
433 
434 static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = {
435 	.pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check,
436 	.pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update,
437 };
438 
439 static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = {
440 	.pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check,
441 	.pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update,
442 };
443 
444 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
445 						enum mga_type type)
446 {
447 	struct mgag200_g200se_device *g200se;
448 	const struct mgag200_device_info *info;
449 	const struct mgag200_device_funcs *funcs;
450 	struct mga_device *mdev;
451 	struct drm_device *dev;
452 	resource_size_t vram_available;
453 	int ret;
454 
455 	g200se = devm_drm_dev_alloc(&pdev->dev, drv, struct mgag200_g200se_device, base.base);
456 	if (IS_ERR(g200se))
457 		return ERR_CAST(g200se);
458 	mdev = &g200se->base;
459 	dev = &mdev->base;
460 
461 	pci_set_drvdata(pdev, dev);
462 
463 	ret = mgag200_g200se_init_pci_options(pdev);
464 	if (ret)
465 		return ERR_PTR(ret);
466 
467 	ret = mgag200_device_preinit(mdev);
468 	if (ret)
469 		return ERR_PTR(ret);
470 
471 	ret = mgag200_g200se_init_unique_rev_id(g200se);
472 	if (ret)
473 		return ERR_PTR(ret);
474 
475 	switch (type) {
476 	case G200_SE_A:
477 		if (g200se->unique_rev_id >= 0x03)
478 			info = &mgag200_g200se_a_03_device_info;
479 		else if (g200se->unique_rev_id >= 0x02)
480 			info = &mgag200_g200se_a_02_device_info;
481 		else
482 			info = &mgag200_g200se_a_01_device_info;
483 		break;
484 	case G200_SE_B:
485 		if (g200se->unique_rev_id >= 0x03)
486 			info = &mgag200_g200se_b_03_device_info;
487 		else if (g200se->unique_rev_id >= 0x02)
488 			info = &mgag200_g200se_b_02_device_info;
489 		else
490 			info = &mgag200_g200se_b_01_device_info;
491 		break;
492 	default:
493 		return ERR_PTR(-EINVAL);
494 	}
495 
496 	if (g200se->unique_rev_id >= 0x04)
497 		funcs = &mgag200_g200se_04_device_funcs;
498 	else
499 		funcs = &mgag200_g200se_00_device_funcs;
500 
501 	ret = mgag200_device_init(mdev, info, funcs);
502 	if (ret)
503 		return ERR_PTR(ret);
504 
505 	mgag200_g200se_init_registers(g200se);
506 
507 	vram_available = mgag200_device_probe_vram(mdev);
508 
509 	ret = mgag200_mode_config_init(mdev, vram_available);
510 	if (ret)
511 		return ERR_PTR(ret);
512 
513 	ret = mgag200_g200se_pipeline_init(mdev);
514 	if (ret)
515 		return ERR_PTR(ret);
516 
517 	drm_mode_config_reset(dev);
518 	drm_kms_helper_poll_init(dev);
519 
520 	ret = drm_vblank_init(dev, 1);
521 	if (ret)
522 		return ERR_PTR(ret);
523 
524 	return mdev;
525 }
526