xref: /linux/drivers/gpu/drm/mgag200/mgag200_g200se.c (revision 815e260a18a3af4dab59025ee99a7156c0e8b5e0)
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_print.h>
11 #include <drm/drm_probe_helper.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_load_gamma(mdev, format, crtc_state->gamma_lut->data);
337 	else
338 		mgag200_crtc_fill_gamma(mdev, format);
339 
340 	mgag200_enable_display(mdev);
341 }
342 
343 static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = {
344 	.mode_valid = mgag200_crtc_helper_mode_valid,
345 	.atomic_check = mgag200_crtc_helper_atomic_check,
346 	.atomic_flush = mgag200_crtc_helper_atomic_flush,
347 	.atomic_enable = mgag200_g200se_crtc_helper_atomic_enable,
348 	.atomic_disable = mgag200_crtc_helper_atomic_disable
349 };
350 
351 static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
352 	MGAG200_CRTC_FUNCS,
353 };
354 
355 static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
356 {
357 	struct drm_device *dev = &mdev->base;
358 	struct drm_plane *primary_plane = &mdev->primary_plane;
359 	struct drm_crtc *crtc = &mdev->crtc;
360 	int ret;
361 
362 	ret = drm_universal_plane_init(dev, primary_plane, 0,
363 				       &mgag200_g200se_primary_plane_funcs,
364 				       mgag200_primary_plane_formats,
365 				       mgag200_primary_plane_formats_size,
366 				       mgag200_primary_plane_fmtmods,
367 				       DRM_PLANE_TYPE_PRIMARY, NULL);
368 	if (ret) {
369 		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
370 		return ret;
371 	}
372 	drm_plane_helper_add(primary_plane, &mgag200_g200se_primary_plane_helper_funcs);
373 	drm_plane_enable_fb_damage_clips(primary_plane);
374 
375 	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
376 					&mgag200_g200se_crtc_funcs, NULL);
377 	if (ret) {
378 		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
379 		return ret;
380 	}
381 	drm_crtc_helper_add(crtc, &mgag200_g200se_crtc_helper_funcs);
382 
383 	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
384 	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
385 	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
386 
387 	ret = mgag200_vga_bmc_output_init(mdev);
388 	if (ret)
389 		return ret;
390 
391 	return 0;
392 }
393 
394 /*
395  * DRM device
396  */
397 
398 static const struct mgag200_device_info mgag200_g200se_a_01_device_info =
399 	MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, true);
400 
401 static const struct mgag200_device_info mgag200_g200se_a_02_device_info =
402 	MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, true);
403 
404 static const struct mgag200_device_info mgag200_g200se_a_03_device_info =
405 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false);
406 
407 static const struct mgag200_device_info mgag200_g200se_b_01_device_info =
408 	MGAG200_DEVICE_INFO_INIT(1600, 1200, 24400, false, 0, 1, false);
409 
410 static const struct mgag200_device_info mgag200_g200se_b_02_device_info =
411 	MGAG200_DEVICE_INFO_INIT(1920, 1200, 30100, false, 0, 1, false);
412 
413 static const struct mgag200_device_info mgag200_g200se_b_03_device_info =
414 	MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 0, 1, false);
415 
416 static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200se)
417 {
418 	struct mga_device *mdev = &g200se->base;
419 	struct drm_device *dev = &mdev->base;
420 
421 	/* stash G200 SE model number for later use */
422 	g200se->unique_rev_id = RREG32(0x1e24);
423 	if (!g200se->unique_rev_id)
424 		return -ENODEV;
425 
426 	drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", g200se->unique_rev_id);
427 
428 	return 0;
429 }
430 
431 static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = {
432 	.pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check,
433 	.pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update,
434 };
435 
436 static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = {
437 	.pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check,
438 	.pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update,
439 };
440 
441 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
442 						enum mga_type type)
443 {
444 	struct mgag200_g200se_device *g200se;
445 	const struct mgag200_device_info *info;
446 	const struct mgag200_device_funcs *funcs;
447 	struct mga_device *mdev;
448 	struct drm_device *dev;
449 	resource_size_t vram_available;
450 	int ret;
451 
452 	g200se = devm_drm_dev_alloc(&pdev->dev, drv, struct mgag200_g200se_device, base.base);
453 	if (IS_ERR(g200se))
454 		return ERR_CAST(g200se);
455 	mdev = &g200se->base;
456 	dev = &mdev->base;
457 
458 	pci_set_drvdata(pdev, dev);
459 
460 	ret = mgag200_g200se_init_pci_options(pdev);
461 	if (ret)
462 		return ERR_PTR(ret);
463 
464 	ret = mgag200_device_preinit(mdev);
465 	if (ret)
466 		return ERR_PTR(ret);
467 
468 	ret = mgag200_g200se_init_unique_rev_id(g200se);
469 	if (ret)
470 		return ERR_PTR(ret);
471 
472 	switch (type) {
473 	case G200_SE_A:
474 		if (g200se->unique_rev_id >= 0x03)
475 			info = &mgag200_g200se_a_03_device_info;
476 		else if (g200se->unique_rev_id >= 0x02)
477 			info = &mgag200_g200se_a_02_device_info;
478 		else
479 			info = &mgag200_g200se_a_01_device_info;
480 		break;
481 	case G200_SE_B:
482 		if (g200se->unique_rev_id >= 0x03)
483 			info = &mgag200_g200se_b_03_device_info;
484 		else if (g200se->unique_rev_id >= 0x02)
485 			info = &mgag200_g200se_b_02_device_info;
486 		else
487 			info = &mgag200_g200se_b_01_device_info;
488 		break;
489 	default:
490 		return ERR_PTR(-EINVAL);
491 	}
492 
493 	if (g200se->unique_rev_id >= 0x04)
494 		funcs = &mgag200_g200se_04_device_funcs;
495 	else
496 		funcs = &mgag200_g200se_00_device_funcs;
497 
498 	ret = mgag200_device_init(mdev, info, funcs);
499 	if (ret)
500 		return ERR_PTR(ret);
501 
502 	mgag200_g200se_init_registers(g200se);
503 
504 	vram_available = mgag200_device_probe_vram(mdev);
505 
506 	ret = mgag200_mode_config_init(mdev, vram_available);
507 	if (ret)
508 		return ERR_PTR(ret);
509 
510 	ret = mgag200_g200se_pipeline_init(mdev);
511 	if (ret)
512 		return ERR_PTR(ret);
513 
514 	drm_mode_config_reset(dev);
515 	drm_kms_helper_poll_init(dev);
516 
517 	return mdev;
518 }
519