blob: 8f7a3a16c92ab261845a694292734817ef3975d8 [file] [log] [blame]
Dave Airlie414c4532012-04-17 15:01:25 +01001/*
2 * Copyright 2010 Matt Turner.
3 * Copyright 2012 Red Hat
4 *
5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main
7 * directory of this archive for more details.
8 *
9 * Authors: Matthew Garrett
10 * Matt Turner
11 * Dave Airlie
12 */
13
14#include <linux/delay.h>
15
David Howells760285e2012-10-02 18:01:07 +010016#include <drm/drmP.h>
17#include <drm/drm_crtc_helper.h>
Daniel Vetter3cb9ae42014-10-29 10:03:57 +010018#include <drm/drm_plane_helper.h>
Dave Airlie414c4532012-04-17 15:01:25 +010019
20#include "mgag200_drv.h"
21
22#define MGAG200_LUT_SIZE 256
23
24/*
25 * This file contains setup code for the CRTC.
26 */
27
28static void mga_crtc_load_lut(struct drm_crtc *crtc)
29{
30 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
31 struct drm_device *dev = crtc->dev;
32 struct mga_device *mdev = dev->dev_private;
Matt Roperf4510a22014-04-01 15:22:40 -070033 struct drm_framebuffer *fb = crtc->primary->fb;
Dave Airlie414c4532012-04-17 15:01:25 +010034 int i;
35
36 if (!crtc->enabled)
37 return;
38
39 WREG8(DAC_INDEX + MGA1064_INDEX, 0);
40
Egbert Eichde7500e2013-07-17 15:07:27 +020041 if (fb && fb->bits_per_pixel == 16) {
42 int inc = (fb->depth == 15) ? 8 : 4;
43 u8 r, b;
44 for (i = 0; i < MGAG200_LUT_SIZE; i += inc) {
45 if (fb->depth == 16) {
46 if (i > (MGAG200_LUT_SIZE >> 1)) {
47 r = b = 0;
48 } else {
49 r = mga_crtc->lut_r[i << 1];
50 b = mga_crtc->lut_b[i << 1];
51 }
52 } else {
53 r = mga_crtc->lut_r[i];
54 b = mga_crtc->lut_b[i];
55 }
56 /* VGA registers */
57 WREG8(DAC_INDEX + MGA1064_COL_PAL, r);
58 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]);
59 WREG8(DAC_INDEX + MGA1064_COL_PAL, b);
60 }
61 return;
62 }
Dave Airlie414c4532012-04-17 15:01:25 +010063 for (i = 0; i < MGAG200_LUT_SIZE; i++) {
64 /* VGA registers */
65 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_r[i]);
66 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]);
67 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_b[i]);
68 }
69}
70
71static inline void mga_wait_vsync(struct mga_device *mdev)
72{
Christopher Harvey3cdc0e82013-05-06 15:56:17 +000073 unsigned long timeout = jiffies + HZ/10;
Dave Airlie414c4532012-04-17 15:01:25 +010074 unsigned int status = 0;
75
76 do {
77 status = RREG32(MGAREG_Status);
Christopher Harvey3cdc0e82013-05-06 15:56:17 +000078 } while ((status & 0x08) && time_before(jiffies, timeout));
79 timeout = jiffies + HZ/10;
Dave Airlie414c4532012-04-17 15:01:25 +010080 status = 0;
81 do {
82 status = RREG32(MGAREG_Status);
Christopher Harvey3cdc0e82013-05-06 15:56:17 +000083 } while (!(status & 0x08) && time_before(jiffies, timeout));
Dave Airlie414c4532012-04-17 15:01:25 +010084}
85
86static inline void mga_wait_busy(struct mga_device *mdev)
87{
Christopher Harvey3cdc0e82013-05-06 15:56:17 +000088 unsigned long timeout = jiffies + HZ;
Dave Airlie414c4532012-04-17 15:01:25 +010089 unsigned int status = 0;
90 do {
91 status = RREG8(MGAREG_Status + 2);
Christopher Harvey3cdc0e82013-05-06 15:56:17 +000092 } while ((status & 0x01) && time_before(jiffies, timeout));
Dave Airlie414c4532012-04-17 15:01:25 +010093}
94
95/*
96 * The core passes the desired mode to the CRTC code to see whether any
97 * CRTC-specific modifications need to be made to it. We're in a position
98 * to just pass that straight through, so this does nothing
99 */
100static bool mga_crtc_mode_fixup(struct drm_crtc *crtc,
Laurent Pincharte811f5a2012-07-17 17:56:50 +0200101 const struct drm_display_mode *mode,
102 struct drm_display_mode *adjusted_mode)
Dave Airlie414c4532012-04-17 15:01:25 +0100103{
104 return true;
105}
106
107static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
108{
109 unsigned int vcomax, vcomin, pllreffreq;
110 unsigned int delta, tmpdelta, permitteddelta;
111 unsigned int testp, testm, testn;
112 unsigned int p, m, n;
113 unsigned int computed;
114
115 m = n = p = 0;
116 vcomax = 320000;
117 vcomin = 160000;
118 pllreffreq = 25000;
119
120 delta = 0xffffffff;
121 permitteddelta = clock * 5 / 1000;
122
123 for (testp = 8; testp > 0; testp /= 2) {
124 if (clock * testp > vcomax)
125 continue;
126 if (clock * testp < vcomin)
127 continue;
128
129 for (testn = 17; testn < 256; testn++) {
130 for (testm = 1; testm < 32; testm++) {
131 computed = (pllreffreq * testn) /
132 (testm * testp);
133 if (computed > clock)
134 tmpdelta = computed - clock;
135 else
136 tmpdelta = clock - computed;
137 if (tmpdelta < delta) {
138 delta = tmpdelta;
139 m = testm - 1;
140 n = testn - 1;
141 p = testp - 1;
142 }
143 }
144 }
145 }
146
147 if (delta > permitteddelta) {
148 printk(KERN_WARNING "PLL delta too large\n");
149 return 1;
150 }
151
152 WREG_DAC(MGA1064_PIX_PLLC_M, m);
153 WREG_DAC(MGA1064_PIX_PLLC_N, n);
154 WREG_DAC(MGA1064_PIX_PLLC_P, p);
155 return 0;
156}
157
158static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
159{
160 unsigned int vcomax, vcomin, pllreffreq;
Sudip Mukherjee546aee52015-07-01 17:12:45 +0530161 unsigned int delta, tmpdelta;
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400162 unsigned int testp, testm, testn, testp2;
Dave Airlie414c4532012-04-17 15:01:25 +0100163 unsigned int p, m, n;
164 unsigned int computed;
165 int i, j, tmpcount, vcount;
166 bool pll_locked = false;
167 u8 tmp;
168
169 m = n = p = 0;
Dave Airlie414c4532012-04-17 15:01:25 +0100170
171 delta = 0xffffffff;
Dave Airlie414c4532012-04-17 15:01:25 +0100172
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400173 if (mdev->type == G200_EW3) {
Dave Airlie414c4532012-04-17 15:01:25 +0100174
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400175 vcomax = 800000;
176 vcomin = 400000;
177 pllreffreq = 25000;
178
179 for (testp = 1; testp < 8; testp++) {
180 for (testp2 = 1; testp2 < 8; testp2++) {
181 if (testp < testp2)
182 continue;
183 if ((clock * testp * testp2) > vcomax)
184 continue;
185 if ((clock * testp * testp2) < vcomin)
186 continue;
187 for (testm = 1; testm < 26; testm++) {
188 for (testn = 32; testn < 2048 ; testn++) {
189 computed = (pllreffreq * testn) /
190 (testm * testp * testp2);
191 if (computed > clock)
192 tmpdelta = computed - clock;
193 else
194 tmpdelta = clock - computed;
195 if (tmpdelta < delta) {
196 delta = tmpdelta;
197 m = ((testn & 0x100) >> 1) |
198 (testm);
199 n = (testn & 0xFF);
200 p = ((testn & 0x600) >> 3) |
201 (testp2 << 3) |
202 (testp);
203 }
204 }
205 }
206 }
207 }
208 } else {
209
210 vcomax = 550000;
211 vcomin = 150000;
212 pllreffreq = 48000;
213
214 for (testp = 1; testp < 9; testp++) {
215 if (clock * testp > vcomax)
216 continue;
217 if (clock * testp < vcomin)
218 continue;
219
220 for (testm = 1; testm < 17; testm++) {
221 for (testn = 1; testn < 151; testn++) {
222 computed = (pllreffreq * testn) /
223 (testm * testp);
224 if (computed > clock)
225 tmpdelta = computed - clock;
226 else
227 tmpdelta = clock - computed;
228 if (tmpdelta < delta) {
229 delta = tmpdelta;
230 n = testn - 1;
231 m = (testm - 1) |
232 ((n >> 1) & 0x80);
233 p = testp - 1;
234 }
Dave Airlie414c4532012-04-17 15:01:25 +0100235 }
236 }
237 }
238 }
239
240 for (i = 0; i <= 32 && pll_locked == false; i++) {
241 if (i > 0) {
242 WREG8(MGAREG_CRTC_INDEX, 0x1e);
243 tmp = RREG8(MGAREG_CRTC_DATA);
244 if (tmp < 0xff)
245 WREG8(MGAREG_CRTC_DATA, tmp+1);
246 }
247
248 /* set pixclkdis to 1 */
249 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
250 tmp = RREG8(DAC_DATA);
251 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000252 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100253
254 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
255 tmp = RREG8(DAC_DATA);
256 tmp |= MGA1064_REMHEADCTL_CLKDIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000257 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100258
259 /* select PLL Set C */
260 tmp = RREG8(MGAREG_MEM_MISC_READ);
261 tmp |= 0x3 << 2;
262 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
263
264 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
265 tmp = RREG8(DAC_DATA);
266 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000267 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100268
269 udelay(500);
270
271 /* reset the PLL */
272 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
273 tmp = RREG8(DAC_DATA);
274 tmp &= ~0x04;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000275 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100276
277 udelay(50);
278
279 /* program pixel pll register */
280 WREG_DAC(MGA1064_WB_PIX_PLLC_N, n);
281 WREG_DAC(MGA1064_WB_PIX_PLLC_M, m);
282 WREG_DAC(MGA1064_WB_PIX_PLLC_P, p);
283
284 udelay(50);
285
286 /* turn pll on */
287 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
288 tmp = RREG8(DAC_DATA);
289 tmp |= 0x04;
290 WREG_DAC(MGA1064_VREF_CTL, tmp);
291
292 udelay(500);
293
294 /* select the pixel pll */
295 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
296 tmp = RREG8(DAC_DATA);
297 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
298 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000299 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100300
301 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
302 tmp = RREG8(DAC_DATA);
303 tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
304 tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000305 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100306
307 /* reset dotclock rate bit */
308 WREG8(MGAREG_SEQ_INDEX, 1);
309 tmp = RREG8(MGAREG_SEQ_DATA);
310 tmp &= ~0x8;
311 WREG8(MGAREG_SEQ_DATA, tmp);
312
313 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
314 tmp = RREG8(DAC_DATA);
315 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000316 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100317
318 vcount = RREG8(MGAREG_VCOUNT);
319
320 for (j = 0; j < 30 && pll_locked == false; j++) {
321 tmpcount = RREG8(MGAREG_VCOUNT);
322 if (tmpcount < vcount)
323 vcount = 0;
324 if ((tmpcount - vcount) > 2)
325 pll_locked = true;
326 else
327 udelay(5);
328 }
329 }
330 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
331 tmp = RREG8(DAC_DATA);
332 tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
333 WREG_DAC(MGA1064_REMHEADCTL, tmp);
334 return 0;
335}
336
337static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
338{
339 unsigned int vcomax, vcomin, pllreffreq;
Sudip Mukherjee546aee52015-07-01 17:12:45 +0530340 unsigned int delta, tmpdelta;
Dave Airlie414c4532012-04-17 15:01:25 +0100341 unsigned int testp, testm, testn;
342 unsigned int p, m, n;
343 unsigned int computed;
344 u8 tmp;
345
346 m = n = p = 0;
347 vcomax = 550000;
348 vcomin = 150000;
349 pllreffreq = 50000;
350
351 delta = 0xffffffff;
Dave Airlie414c4532012-04-17 15:01:25 +0100352
353 for (testp = 16; testp > 0; testp--) {
354 if (clock * testp > vcomax)
355 continue;
356 if (clock * testp < vcomin)
357 continue;
358
359 for (testn = 1; testn < 257; testn++) {
360 for (testm = 1; testm < 17; testm++) {
361 computed = (pllreffreq * testn) /
362 (testm * testp);
363 if (computed > clock)
364 tmpdelta = computed - clock;
365 else
366 tmpdelta = clock - computed;
367 if (tmpdelta < delta) {
368 delta = tmpdelta;
369 n = testn - 1;
370 m = testm - 1;
371 p = testp - 1;
372 }
373 }
374 }
375 }
376
377 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
378 tmp = RREG8(DAC_DATA);
379 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000380 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100381
382 tmp = RREG8(MGAREG_MEM_MISC_READ);
383 tmp |= 0x3 << 2;
384 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
385
386 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
387 tmp = RREG8(DAC_DATA);
Christopher Harveyfb70a662013-04-12 22:24:05 +0000388 WREG8(DAC_DATA, tmp & ~0x40);
Dave Airlie414c4532012-04-17 15:01:25 +0100389
390 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
391 tmp = RREG8(DAC_DATA);
392 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000393 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100394
395 WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
396 WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
397 WREG_DAC(MGA1064_EV_PIX_PLLC_P, p);
398
399 udelay(50);
400
401 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
402 tmp = RREG8(DAC_DATA);
403 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000404 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100405
406 udelay(500);
407
408 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
409 tmp = RREG8(DAC_DATA);
410 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
411 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000412 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100413
414 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
415 tmp = RREG8(DAC_DATA);
Christopher Harveyfb70a662013-04-12 22:24:05 +0000416 WREG8(DAC_DATA, tmp | 0x40);
Dave Airlie414c4532012-04-17 15:01:25 +0100417
418 tmp = RREG8(MGAREG_MEM_MISC_READ);
419 tmp |= (0x3 << 2);
420 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
421
422 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
423 tmp = RREG8(DAC_DATA);
424 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000425 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100426
427 return 0;
428}
429
430static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
431{
432 unsigned int vcomax, vcomin, pllreffreq;
Sudip Mukherjee546aee52015-07-01 17:12:45 +0530433 unsigned int delta, tmpdelta;
Dave Airlie414c4532012-04-17 15:01:25 +0100434 unsigned int testp, testm, testn;
435 unsigned int p, m, n;
436 unsigned int computed;
437 int i, j, tmpcount, vcount;
438 u8 tmp;
439 bool pll_locked = false;
440
441 m = n = p = 0;
442 vcomax = 800000;
443 vcomin = 400000;
Julia Lemire260b3f12013-03-18 10:17:47 -0400444 pllreffreq = 33333;
Dave Airlie414c4532012-04-17 15:01:25 +0100445
446 delta = 0xffffffff;
Dave Airlie414c4532012-04-17 15:01:25 +0100447
Julia Lemire260b3f12013-03-18 10:17:47 -0400448 for (testp = 16; testp > 0; testp >>= 1) {
Dave Airlie414c4532012-04-17 15:01:25 +0100449 if (clock * testp > vcomax)
450 continue;
451 if (clock * testp < vcomin)
452 continue;
453
454 for (testm = 1; testm < 33; testm++) {
Julia Lemire260b3f12013-03-18 10:17:47 -0400455 for (testn = 17; testn < 257; testn++) {
Dave Airlie414c4532012-04-17 15:01:25 +0100456 computed = (pllreffreq * testn) /
457 (testm * testp);
458 if (computed > clock)
459 tmpdelta = computed - clock;
460 else
461 tmpdelta = clock - computed;
462 if (tmpdelta < delta) {
463 delta = tmpdelta;
464 n = testn - 1;
Julia Lemire260b3f12013-03-18 10:17:47 -0400465 m = (testm - 1);
Dave Airlie414c4532012-04-17 15:01:25 +0100466 p = testp - 1;
467 }
468 if ((clock * testp) >= 600000)
Julia Lemire260b3f12013-03-18 10:17:47 -0400469 p |= 0x80;
Dave Airlie414c4532012-04-17 15:01:25 +0100470 }
471 }
472 }
473 for (i = 0; i <= 32 && pll_locked == false; i++) {
474 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
475 tmp = RREG8(DAC_DATA);
476 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000477 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100478
479 tmp = RREG8(MGAREG_MEM_MISC_READ);
480 tmp |= 0x3 << 2;
481 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
482
483 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
484 tmp = RREG8(DAC_DATA);
485 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000486 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100487
488 udelay(500);
489
490 WREG_DAC(MGA1064_EH_PIX_PLLC_M, m);
491 WREG_DAC(MGA1064_EH_PIX_PLLC_N, n);
492 WREG_DAC(MGA1064_EH_PIX_PLLC_P, p);
493
494 udelay(500);
495
496 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
497 tmp = RREG8(DAC_DATA);
498 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
499 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000500 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100501
502 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
503 tmp = RREG8(DAC_DATA);
504 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
505 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000506 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100507
508 vcount = RREG8(MGAREG_VCOUNT);
509
510 for (j = 0; j < 30 && pll_locked == false; j++) {
511 tmpcount = RREG8(MGAREG_VCOUNT);
512 if (tmpcount < vcount)
513 vcount = 0;
514 if ((tmpcount - vcount) > 2)
515 pll_locked = true;
516 else
517 udelay(5);
518 }
519 }
520
521 return 0;
522}
523
524static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
525{
526 unsigned int vcomax, vcomin, pllreffreq;
527 unsigned int delta, tmpdelta;
Dave Airlie98306052012-08-09 15:00:15 +1000528 int testr, testn, testm, testo;
Dave Airlie414c4532012-04-17 15:01:25 +0100529 unsigned int p, m, n;
Dave Airlie98306052012-08-09 15:00:15 +1000530 unsigned int computed, vco;
Dave Airlie414c4532012-04-17 15:01:25 +0100531 int tmp;
Dave Airlie98306052012-08-09 15:00:15 +1000532 const unsigned int m_div_val[] = { 1, 2, 4, 8 };
Dave Airlie414c4532012-04-17 15:01:25 +0100533
534 m = n = p = 0;
535 vcomax = 1488000;
536 vcomin = 1056000;
537 pllreffreq = 48000;
538
539 delta = 0xffffffff;
540
541 for (testr = 0; testr < 4; testr++) {
542 if (delta == 0)
543 break;
544 for (testn = 5; testn < 129; testn++) {
545 if (delta == 0)
546 break;
547 for (testm = 3; testm >= 0; testm--) {
548 if (delta == 0)
549 break;
550 for (testo = 5; testo < 33; testo++) {
Dave Airlie98306052012-08-09 15:00:15 +1000551 vco = pllreffreq * (testn + 1) /
Dave Airlie414c4532012-04-17 15:01:25 +0100552 (testr + 1);
Dave Airlie98306052012-08-09 15:00:15 +1000553 if (vco < vcomin)
Dave Airlie414c4532012-04-17 15:01:25 +0100554 continue;
Dave Airlie98306052012-08-09 15:00:15 +1000555 if (vco > vcomax)
Dave Airlie414c4532012-04-17 15:01:25 +0100556 continue;
Dave Airlie98306052012-08-09 15:00:15 +1000557 computed = vco / (m_div_val[testm] * (testo + 1));
Dave Airlie414c4532012-04-17 15:01:25 +0100558 if (computed > clock)
559 tmpdelta = computed - clock;
560 else
561 tmpdelta = clock - computed;
562 if (tmpdelta < delta) {
563 delta = tmpdelta;
564 m = testm | (testo << 3);
565 n = testn;
566 p = testr | (testr << 3);
567 }
568 }
569 }
570 }
571 }
572
573 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
574 tmp = RREG8(DAC_DATA);
575 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000576 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100577
578 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
579 tmp = RREG8(DAC_DATA);
580 tmp |= MGA1064_REMHEADCTL_CLKDIS;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000581 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100582
583 tmp = RREG8(MGAREG_MEM_MISC_READ);
584 tmp |= (0x3<<2) | 0xc0;
585 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
586
587 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
588 tmp = RREG8(DAC_DATA);
589 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
590 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
Christopher Harveyfb70a662013-04-12 22:24:05 +0000591 WREG8(DAC_DATA, tmp);
Dave Airlie414c4532012-04-17 15:01:25 +0100592
593 udelay(500);
594
595 WREG_DAC(MGA1064_ER_PIX_PLLC_N, n);
596 WREG_DAC(MGA1064_ER_PIX_PLLC_M, m);
597 WREG_DAC(MGA1064_ER_PIX_PLLC_P, p);
598
599 udelay(50);
600
601 return 0;
602}
603
604static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
605{
606 switch(mdev->type) {
607 case G200_SE_A:
608 case G200_SE_B:
609 return mga_g200se_set_plls(mdev, clock);
610 break;
611 case G200_WB:
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400612 case G200_EW3:
Dave Airlie414c4532012-04-17 15:01:25 +0100613 return mga_g200wb_set_plls(mdev, clock);
614 break;
615 case G200_EV:
616 return mga_g200ev_set_plls(mdev, clock);
617 break;
618 case G200_EH:
619 return mga_g200eh_set_plls(mdev, clock);
620 break;
621 case G200_ER:
622 return mga_g200er_set_plls(mdev, clock);
623 break;
624 }
625 return 0;
626}
627
628static void mga_g200wb_prepare(struct drm_crtc *crtc)
629{
630 struct mga_device *mdev = crtc->dev->dev_private;
631 u8 tmp;
632 int iter_max;
633
634 /* 1- The first step is to warn the BMC of an upcoming mode change.
635 * We are putting the misc<0> to output.*/
636
637 WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
638 tmp = RREG8(DAC_DATA);
639 tmp |= 0x10;
640 WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
641
642 /* we are putting a 1 on the misc<0> line */
643 WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
644 tmp = RREG8(DAC_DATA);
645 tmp |= 0x10;
646 WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
647
648 /* 2- Second step to mask and further scan request
649 * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
650 */
651 WREG8(DAC_INDEX, MGA1064_SPAREREG);
652 tmp = RREG8(DAC_DATA);
653 tmp |= 0x80;
654 WREG_DAC(MGA1064_SPAREREG, tmp);
655
656 /* 3a- the third step is to verifu if there is an active scan
657 * We are searching for a 0 on remhsyncsts <XSPAREREG<0>)
658 */
659 iter_max = 300;
660 while (!(tmp & 0x1) && iter_max) {
661 WREG8(DAC_INDEX, MGA1064_SPAREREG);
662 tmp = RREG8(DAC_DATA);
663 udelay(1000);
664 iter_max--;
665 }
666
667 /* 3b- this step occurs only if the remove is actually scanning
668 * we are waiting for the end of the frame which is a 1 on
669 * remvsyncsts (XSPAREREG<1>)
670 */
671 if (iter_max) {
672 iter_max = 300;
673 while ((tmp & 0x2) && iter_max) {
674 WREG8(DAC_INDEX, MGA1064_SPAREREG);
675 tmp = RREG8(DAC_DATA);
676 udelay(1000);
677 iter_max--;
678 }
679 }
680}
681
682static void mga_g200wb_commit(struct drm_crtc *crtc)
683{
684 u8 tmp;
685 struct mga_device *mdev = crtc->dev->dev_private;
686
687 /* 1- The first step is to ensure that the vrsten and hrsten are set */
688 WREG8(MGAREG_CRTCEXT_INDEX, 1);
689 tmp = RREG8(MGAREG_CRTCEXT_DATA);
690 WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
691
692 /* 2- second step is to assert the rstlvl2 */
693 WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
694 tmp = RREG8(DAC_DATA);
695 tmp |= 0x8;
696 WREG8(DAC_DATA, tmp);
697
698 /* wait 10 us */
699 udelay(10);
700
701 /* 3- deassert rstlvl2 */
702 tmp &= ~0x08;
703 WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
704 WREG8(DAC_DATA, tmp);
705
706 /* 4- remove mask of scan request */
707 WREG8(DAC_INDEX, MGA1064_SPAREREG);
708 tmp = RREG8(DAC_DATA);
709 tmp &= ~0x80;
710 WREG8(DAC_DATA, tmp);
711
712 /* 5- put back a 0 on the misc<0> line */
713 WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
714 tmp = RREG8(DAC_DATA);
715 tmp &= ~0x10;
716 WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
717}
718
Christopher Harvey9f1d0362013-05-08 19:10:38 +0000719/*
720 This is how the framebuffer base address is stored in g200 cards:
721 * Assume @offset is the gpu_addr variable of the framebuffer object
722 * Then addr is the number of _pixels_ (not bytes) from the start of
723 VRAM to the first pixel we want to display. (divided by 2 for 32bit
724 framebuffers)
725 * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers
726 addr<20> -> CRTCEXT0<6>
727 addr<19-16> -> CRTCEXT0<3-0>
728 addr<15-8> -> CRTCC<7-0>
729 addr<7-0> -> CRTCD<7-0>
730 CRTCEXT0 has to be programmed last to trigger an update and make the
731 new addr variable take effect.
732 */
Rashika080fd6b2014-01-06 20:37:15 +0530733static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
Dave Airlie414c4532012-04-17 15:01:25 +0100734{
735 struct mga_device *mdev = crtc->dev->dev_private;
736 u32 addr;
737 int count;
Christopher Harvey9f1d0362013-05-08 19:10:38 +0000738 u8 crtcext0;
Dave Airlie414c4532012-04-17 15:01:25 +0100739
740 while (RREG8(0x1fda) & 0x08);
741 while (!(RREG8(0x1fda) & 0x08));
742
743 count = RREG8(MGAREG_VCOUNT) + 2;
744 while (RREG8(MGAREG_VCOUNT) < count);
745
Christopher Harvey9f1d0362013-05-08 19:10:38 +0000746 WREG8(MGAREG_CRTCEXT_INDEX, 0);
747 crtcext0 = RREG8(MGAREG_CRTCEXT_DATA);
748 crtcext0 &= 0xB0;
749 addr = offset / 8;
750 /* Can't store addresses any higher than that...
751 but we also don't have more than 16MB of memory, so it should be fine. */
752 WARN_ON(addr > 0x1fffff);
753 crtcext0 |= (!!(addr & (1<<20)))<<6;
Dave Airlie414c4532012-04-17 15:01:25 +0100754 WREG_CRT(0x0d, (u8)(addr & 0xff));
755 WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff);
Christopher Harvey9f1d0362013-05-08 19:10:38 +0000756 WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);
Dave Airlie414c4532012-04-17 15:01:25 +0100757}
758
759
760/* ast is different - we will force move buffers out of VRAM */
761static int mga_crtc_do_set_base(struct drm_crtc *crtc,
762 struct drm_framebuffer *fb,
763 int x, int y, int atomic)
764{
765 struct mga_device *mdev = crtc->dev->dev_private;
766 struct drm_gem_object *obj;
767 struct mga_framebuffer *mga_fb;
768 struct mgag200_bo *bo;
769 int ret;
770 u64 gpu_addr;
771
772 /* push the previous fb to system ram */
773 if (!atomic && fb) {
774 mga_fb = to_mga_framebuffer(fb);
775 obj = mga_fb->obj;
776 bo = gem_to_mga_bo(obj);
777 ret = mgag200_bo_reserve(bo, false);
778 if (ret)
779 return ret;
780 mgag200_bo_push_sysram(bo);
781 mgag200_bo_unreserve(bo);
782 }
783
Matt Roperf4510a22014-04-01 15:22:40 -0700784 mga_fb = to_mga_framebuffer(crtc->primary->fb);
Dave Airlie414c4532012-04-17 15:01:25 +0100785 obj = mga_fb->obj;
786 bo = gem_to_mga_bo(obj);
787
788 ret = mgag200_bo_reserve(bo, false);
789 if (ret)
790 return ret;
791
792 ret = mgag200_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
793 if (ret) {
794 mgag200_bo_unreserve(bo);
795 return ret;
796 }
797
798 if (&mdev->mfbdev->mfb == mga_fb) {
799 /* if pushing console in kmap it */
800 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
801 if (ret)
802 DRM_ERROR("failed to kmap fbcon\n");
803
804 }
805 mgag200_bo_unreserve(bo);
806
Dave Airlie414c4532012-04-17 15:01:25 +0100807 mga_set_start_address(crtc, (u32)gpu_addr);
808
809 return 0;
810}
811
812static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
813 struct drm_framebuffer *old_fb)
814{
815 return mga_crtc_do_set_base(crtc, old_fb, x, y, 0);
816}
817
818static int mga_crtc_mode_set(struct drm_crtc *crtc,
819 struct drm_display_mode *mode,
820 struct drm_display_mode *adjusted_mode,
821 int x, int y, struct drm_framebuffer *old_fb)
822{
823 struct drm_device *dev = crtc->dev;
824 struct mga_device *mdev = dev->dev_private;
825 int hdisplay, hsyncstart, hsyncend, htotal;
826 int vdisplay, vsyncstart, vsyncend, vtotal;
827 int pitch;
828 int option = 0, option2 = 0;
829 int i;
830 unsigned char misc = 0;
831 unsigned char ext_vga[6];
Dave Airlie414c4532012-04-17 15:01:25 +0100832 u8 bppshift;
833
834 static unsigned char dacvalue[] = {
835 /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0,
836 /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0,
837 /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0,
838 /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
839 /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40,
841 /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
842 /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
843 /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0,
844 /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0
845 };
846
Matt Roperf4510a22014-04-01 15:22:40 -0700847 bppshift = mdev->bpp_shifts[(crtc->primary->fb->bits_per_pixel >> 3) - 1];
Dave Airlie414c4532012-04-17 15:01:25 +0100848
849 switch (mdev->type) {
850 case G200_SE_A:
851 case G200_SE_B:
852 dacvalue[MGA1064_VREF_CTL] = 0x03;
853 dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
854 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
855 MGA1064_MISC_CTL_VGA8 |
856 MGA1064_MISC_CTL_DAC_RAM_CS;
857 if (mdev->has_sdram)
858 option = 0x40049120;
859 else
860 option = 0x4004d120;
861 option2 = 0x00008000;
862 break;
863 case G200_WB:
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400864 case G200_EW3:
Dave Airlie414c4532012-04-17 15:01:25 +0100865 dacvalue[MGA1064_VREF_CTL] = 0x07;
866 option = 0x41049120;
867 option2 = 0x0000b000;
868 break;
869 case G200_EV:
870 dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
871 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
872 MGA1064_MISC_CTL_DAC_RAM_CS;
873 option = 0x00000120;
874 option2 = 0x0000b000;
875 break;
876 case G200_EH:
877 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
878 MGA1064_MISC_CTL_DAC_RAM_CS;
879 option = 0x00000120;
880 option2 = 0x0000b000;
881 break;
882 case G200_ER:
Dave Airlie414c4532012-04-17 15:01:25 +0100883 break;
884 }
885
Matt Roperf4510a22014-04-01 15:22:40 -0700886 switch (crtc->primary->fb->bits_per_pixel) {
Dave Airlie414c4532012-04-17 15:01:25 +0100887 case 8:
888 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
889 break;
890 case 16:
Matt Roperf4510a22014-04-01 15:22:40 -0700891 if (crtc->primary->fb->depth == 15)
Dave Airlie414c4532012-04-17 15:01:25 +0100892 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
893 else
894 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
895 break;
896 case 24:
897 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_24bits;
898 break;
899 case 32:
900 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_32_24bits;
901 break;
902 }
903
904 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
905 misc |= 0x40;
906 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
907 misc |= 0x80;
908
909
910 for (i = 0; i < sizeof(dacvalue); i++) {
Christopher Harvey9d8aa552013-04-12 20:42:19 +0000911 if ((i <= 0x17) ||
Dave Airlie414c4532012-04-17 15:01:25 +0100912 (i == 0x1b) ||
913 (i == 0x1c) ||
914 ((i >= 0x1f) && (i <= 0x29)) ||
915 ((i >= 0x30) && (i <= 0x37)))
916 continue;
917 if (IS_G200_SE(mdev) &&
918 ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
919 continue;
Mathieu Larouche6d857c12015-08-21 09:24:05 -0400920 if ((mdev->type == G200_EV ||
921 mdev->type == G200_WB ||
922 mdev->type == G200_EH ||
923 mdev->type == G200_EW3) &&
Dave Airlie414c4532012-04-17 15:01:25 +0100924 (i >= 0x44) && (i <= 0x4e))
925 continue;
926
927 WREG_DAC(i, dacvalue[i]);
928 }
929
Christopher Harvey1812a3d2013-04-05 10:51:15 -0400930 if (mdev->type == G200_ER)
931 WREG_DAC(0x90, 0);
Dave Airlie414c4532012-04-17 15:01:25 +0100932
933 if (option)
934 pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
935 if (option2)
936 pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2);
937
938 WREG_SEQ(2, 0xf);
939 WREG_SEQ(3, 0);
940 WREG_SEQ(4, 0xe);
941
Matt Roperf4510a22014-04-01 15:22:40 -0700942 pitch = crtc->primary->fb->pitches[0] / (crtc->primary->fb->bits_per_pixel / 8);
943 if (crtc->primary->fb->bits_per_pixel == 24)
Takashi Iwaida558392013-07-17 15:07:26 +0200944 pitch = (pitch * 3) >> (4 - bppshift);
Dave Airlie414c4532012-04-17 15:01:25 +0100945 else
946 pitch = pitch >> (4 - bppshift);
947
948 hdisplay = mode->hdisplay / 8 - 1;
949 hsyncstart = mode->hsync_start / 8 - 1;
950 hsyncend = mode->hsync_end / 8 - 1;
951 htotal = mode->htotal / 8 - 1;
952
953 /* Work around hardware quirk */
954 if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04)
955 htotal++;
956
957 vdisplay = mode->vdisplay - 1;
958 vsyncstart = mode->vsync_start - 1;
959 vsyncend = mode->vsync_end - 1;
960 vtotal = mode->vtotal - 2;
961
962 WREG_GFX(0, 0);
963 WREG_GFX(1, 0);
964 WREG_GFX(2, 0);
965 WREG_GFX(3, 0);
966 WREG_GFX(4, 0);
967 WREG_GFX(5, 0x40);
968 WREG_GFX(6, 0x5);
969 WREG_GFX(7, 0xf);
970 WREG_GFX(8, 0xf);
971
972 WREG_CRT(0, htotal - 4);
973 WREG_CRT(1, hdisplay);
974 WREG_CRT(2, hdisplay);
975 WREG_CRT(3, (htotal & 0x1F) | 0x80);
976 WREG_CRT(4, hsyncstart);
977 WREG_CRT(5, ((htotal & 0x20) << 2) | (hsyncend & 0x1F));
978 WREG_CRT(6, vtotal & 0xFF);
979 WREG_CRT(7, ((vtotal & 0x100) >> 8) |
980 ((vdisplay & 0x100) >> 7) |
981 ((vsyncstart & 0x100) >> 6) |
982 ((vdisplay & 0x100) >> 5) |
983 ((vdisplay & 0x100) >> 4) | /* linecomp */
984 ((vtotal & 0x200) >> 4)|
985 ((vdisplay & 0x200) >> 3) |
986 ((vsyncstart & 0x200) >> 2));
987 WREG_CRT(9, ((vdisplay & 0x200) >> 4) |
988 ((vdisplay & 0x200) >> 3));
989 WREG_CRT(10, 0);
990 WREG_CRT(11, 0);
991 WREG_CRT(12, 0);
992 WREG_CRT(13, 0);
993 WREG_CRT(14, 0);
994 WREG_CRT(15, 0);
995 WREG_CRT(16, vsyncstart & 0xFF);
996 WREG_CRT(17, (vsyncend & 0x0F) | 0x20);
997 WREG_CRT(18, vdisplay & 0xFF);
998 WREG_CRT(19, pitch & 0xFF);
999 WREG_CRT(20, 0);
1000 WREG_CRT(21, vdisplay & 0xFF);
1001 WREG_CRT(22, (vtotal + 1) & 0xFF);
1002 WREG_CRT(23, 0xc3);
1003 WREG_CRT(24, vdisplay & 0xFF);
1004
1005 ext_vga[0] = 0;
1006 ext_vga[5] = 0;
1007
1008 /* TODO interlace */
1009
1010 ext_vga[0] |= (pitch & 0x300) >> 4;
1011 ext_vga[1] = (((htotal - 4) & 0x100) >> 8) |
1012 ((hdisplay & 0x100) >> 7) |
1013 ((hsyncstart & 0x100) >> 6) |
1014 (htotal & 0x40);
1015 ext_vga[2] = ((vtotal & 0xc00) >> 10) |
1016 ((vdisplay & 0x400) >> 8) |
1017 ((vdisplay & 0xc00) >> 7) |
1018 ((vsyncstart & 0xc00) >> 5) |
1019 ((vdisplay & 0x400) >> 3);
Matt Roperf4510a22014-04-01 15:22:40 -07001020 if (crtc->primary->fb->bits_per_pixel == 24)
Dave Airlie414c4532012-04-17 15:01:25 +01001021 ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
1022 else
1023 ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
1024 ext_vga[4] = 0;
Mathieu Larouche6d857c12015-08-21 09:24:05 -04001025 if (mdev->type == G200_WB || mdev->type == G200_EW3)
Dave Airlie414c4532012-04-17 15:01:25 +01001026 ext_vga[1] |= 0x88;
1027
Dave Airlie414c4532012-04-17 15:01:25 +01001028 /* Set pixel clocks */
1029 misc = 0x2d;
1030 WREG8(MGA_MISC_OUT, misc);
1031
1032 mga_crtc_set_plls(mdev, mode->clock);
1033
1034 for (i = 0; i < 6; i++) {
1035 WREG_ECRT(i, ext_vga[i]);
1036 }
1037
1038 if (mdev->type == G200_ER)
Christopher Harvey1812a3d2013-04-05 10:51:15 -04001039 WREG_ECRT(0x24, 0x5);
Dave Airlie414c4532012-04-17 15:01:25 +01001040
Mathieu Larouche6d857c12015-08-21 09:24:05 -04001041 if (mdev->type == G200_EW3)
1042 WREG_ECRT(0x34, 0x5);
1043
Dave Airlie414c4532012-04-17 15:01:25 +01001044 if (mdev->type == G200_EV) {
1045 WREG_ECRT(6, 0);
1046 }
1047
1048 WREG_ECRT(0, ext_vga[0]);
1049 /* Enable mga pixel clock */
1050 misc = 0x2d;
1051
1052 WREG8(MGA_MISC_OUT, misc);
1053
1054 if (adjusted_mode)
1055 memcpy(&mdev->mode, mode, sizeof(struct drm_display_mode));
1056
1057 mga_crtc_do_set_base(crtc, old_fb, x, y, 0);
1058
1059 /* reset tagfifo */
1060 if (mdev->type == G200_ER) {
1061 u32 mem_ctl = RREG32(MGAREG_MEMCTL);
1062 u8 seq1;
1063
1064 /* screen off */
1065 WREG8(MGAREG_SEQ_INDEX, 0x01);
1066 seq1 = RREG8(MGAREG_SEQ_DATA) | 0x20;
1067 WREG8(MGAREG_SEQ_DATA, seq1);
1068
1069 WREG32(MGAREG_MEMCTL, mem_ctl | 0x00200000);
1070 udelay(1000);
1071 WREG32(MGAREG_MEMCTL, mem_ctl & ~0x00200000);
1072
1073 WREG8(MGAREG_SEQ_DATA, seq1 & ~0x20);
1074 }
1075
1076
1077 if (IS_G200_SE(mdev)) {
Julia Lemireabbee622013-06-27 13:38:59 -04001078 if (mdev->unique_rev_id >= 0x02) {
Dave Airlie414c4532012-04-17 15:01:25 +01001079 u8 hi_pri_lvl;
1080 u32 bpp;
1081 u32 mb;
1082
Matt Roperf4510a22014-04-01 15:22:40 -07001083 if (crtc->primary->fb->bits_per_pixel > 16)
Dave Airlie414c4532012-04-17 15:01:25 +01001084 bpp = 32;
Matt Roperf4510a22014-04-01 15:22:40 -07001085 else if (crtc->primary->fb->bits_per_pixel > 8)
Dave Airlie414c4532012-04-17 15:01:25 +01001086 bpp = 16;
1087 else
1088 bpp = 8;
1089
1090 mb = (mode->clock * bpp) / 1000;
1091 if (mb > 3100)
1092 hi_pri_lvl = 0;
1093 else if (mb > 2600)
1094 hi_pri_lvl = 1;
1095 else if (mb > 1900)
1096 hi_pri_lvl = 2;
1097 else if (mb > 1160)
1098 hi_pri_lvl = 3;
1099 else if (mb > 440)
1100 hi_pri_lvl = 4;
1101 else
1102 hi_pri_lvl = 5;
1103
Christopher Harvey91f8f102013-05-31 20:33:07 +00001104 WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
1105 WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
Dave Airlie414c4532012-04-17 15:01:25 +01001106 } else {
Christopher Harvey91f8f102013-05-31 20:33:07 +00001107 WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
Julia Lemireabbee622013-06-27 13:38:59 -04001108 if (mdev->unique_rev_id >= 0x01)
Christopher Harvey91f8f102013-05-31 20:33:07 +00001109 WREG8(MGAREG_CRTCEXT_DATA, 0x03);
Dave Airlie414c4532012-04-17 15:01:25 +01001110 else
Christopher Harvey91f8f102013-05-31 20:33:07 +00001111 WREG8(MGAREG_CRTCEXT_DATA, 0x04);
Dave Airlie414c4532012-04-17 15:01:25 +01001112 }
1113 }
1114 return 0;
1115}
1116
1117#if 0 /* code from mjg to attempt D3 on crtc dpms off - revisit later */
1118static int mga_suspend(struct drm_crtc *crtc)
1119{
1120 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1121 struct drm_device *dev = crtc->dev;
1122 struct mga_device *mdev = dev->dev_private;
1123 struct pci_dev *pdev = dev->pdev;
1124 int option;
1125
1126 if (mdev->suspended)
1127 return 0;
1128
1129 WREG_SEQ(1, 0x20);
1130 WREG_ECRT(1, 0x30);
1131 /* Disable the pixel clock */
1132 WREG_DAC(0x1a, 0x05);
1133 /* Power down the DAC */
1134 WREG_DAC(0x1e, 0x18);
1135 /* Power down the pixel PLL */
1136 WREG_DAC(0x1a, 0x0d);
1137
1138 /* Disable PLLs and clocks */
1139 pci_read_config_dword(pdev, PCI_MGA_OPTION, &option);
1140 option &= ~(0x1F8024);
1141 pci_write_config_dword(pdev, PCI_MGA_OPTION, option);
1142 pci_set_power_state(pdev, PCI_D3hot);
1143 pci_disable_device(pdev);
1144
1145 mdev->suspended = true;
1146
1147 return 0;
1148}
1149
1150static int mga_resume(struct drm_crtc *crtc)
1151{
1152 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1153 struct drm_device *dev = crtc->dev;
1154 struct mga_device *mdev = dev->dev_private;
1155 struct pci_dev *pdev = dev->pdev;
1156 int option;
1157
1158 if (!mdev->suspended)
1159 return 0;
1160
1161 pci_set_power_state(pdev, PCI_D0);
1162 pci_enable_device(pdev);
1163
1164 /* Disable sysclk */
1165 pci_read_config_dword(pdev, PCI_MGA_OPTION, &option);
1166 option &= ~(0x4);
1167 pci_write_config_dword(pdev, PCI_MGA_OPTION, option);
1168
1169 mdev->suspended = false;
1170
1171 return 0;
1172}
1173
1174#endif
1175
1176static void mga_crtc_dpms(struct drm_crtc *crtc, int mode)
1177{
1178 struct drm_device *dev = crtc->dev;
1179 struct mga_device *mdev = dev->dev_private;
1180 u8 seq1 = 0, crtcext1 = 0;
1181
1182 switch (mode) {
1183 case DRM_MODE_DPMS_ON:
1184 seq1 = 0;
1185 crtcext1 = 0;
1186 mga_crtc_load_lut(crtc);
1187 break;
1188 case DRM_MODE_DPMS_STANDBY:
1189 seq1 = 0x20;
1190 crtcext1 = 0x10;
1191 break;
1192 case DRM_MODE_DPMS_SUSPEND:
1193 seq1 = 0x20;
1194 crtcext1 = 0x20;
1195 break;
1196 case DRM_MODE_DPMS_OFF:
1197 seq1 = 0x20;
1198 crtcext1 = 0x30;
1199 break;
1200 }
1201
1202#if 0
1203 if (mode == DRM_MODE_DPMS_OFF) {
1204 mga_suspend(crtc);
1205 }
1206#endif
1207 WREG8(MGAREG_SEQ_INDEX, 0x01);
1208 seq1 |= RREG8(MGAREG_SEQ_DATA) & ~0x20;
1209 mga_wait_vsync(mdev);
1210 mga_wait_busy(mdev);
1211 WREG8(MGAREG_SEQ_DATA, seq1);
1212 msleep(20);
1213 WREG8(MGAREG_CRTCEXT_INDEX, 0x01);
1214 crtcext1 |= RREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
1215 WREG8(MGAREG_CRTCEXT_DATA, crtcext1);
1216
1217#if 0
1218 if (mode == DRM_MODE_DPMS_ON && mdev->suspended == true) {
1219 mga_resume(crtc);
1220 drm_helper_resume_force_mode(dev);
1221 }
1222#endif
1223}
1224
1225/*
1226 * This is called before a mode is programmed. A typical use might be to
1227 * enable DPMS during the programming to avoid seeing intermediate stages,
1228 * but that's not relevant to us
1229 */
1230static void mga_crtc_prepare(struct drm_crtc *crtc)
1231{
1232 struct drm_device *dev = crtc->dev;
1233 struct mga_device *mdev = dev->dev_private;
1234 u8 tmp;
1235
1236 /* mga_resume(crtc);*/
1237
1238 WREG8(MGAREG_CRTC_INDEX, 0x11);
1239 tmp = RREG8(MGAREG_CRTC_DATA);
1240 WREG_CRT(0x11, tmp | 0x80);
1241
1242 if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
1243 WREG_SEQ(0, 1);
1244 msleep(50);
1245 WREG_SEQ(1, 0x20);
1246 msleep(20);
1247 } else {
1248 WREG8(MGAREG_SEQ_INDEX, 0x1);
1249 tmp = RREG8(MGAREG_SEQ_DATA);
1250
1251 /* start sync reset */
1252 WREG_SEQ(0, 1);
1253 WREG_SEQ(1, tmp | 0x20);
1254 }
1255
Mathieu Larouche6d857c12015-08-21 09:24:05 -04001256 if (mdev->type == G200_WB || mdev->type == G200_EW3)
Dave Airlie414c4532012-04-17 15:01:25 +01001257 mga_g200wb_prepare(crtc);
1258
1259 WREG_CRT(17, 0);
1260}
1261
1262/*
1263 * This is called after a mode is programmed. It should reverse anything done
1264 * by the prepare function
1265 */
1266static void mga_crtc_commit(struct drm_crtc *crtc)
1267{
1268 struct drm_device *dev = crtc->dev;
1269 struct mga_device *mdev = dev->dev_private;
Jani Nikulad584ff82015-03-11 11:51:00 +02001270 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
Dave Airlie414c4532012-04-17 15:01:25 +01001271 u8 tmp;
1272
Mathieu Larouche6d857c12015-08-21 09:24:05 -04001273 if (mdev->type == G200_WB || mdev->type == G200_EW3)
Dave Airlie414c4532012-04-17 15:01:25 +01001274 mga_g200wb_commit(crtc);
1275
1276 if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
1277 msleep(50);
1278 WREG_SEQ(1, 0x0);
1279 msleep(20);
1280 WREG_SEQ(0, 0x3);
1281 } else {
1282 WREG8(MGAREG_SEQ_INDEX, 0x1);
1283 tmp = RREG8(MGAREG_SEQ_DATA);
1284
1285 tmp &= ~0x20;
1286 WREG_SEQ(0x1, tmp);
1287 WREG_SEQ(0, 3);
1288 }
1289 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
1290}
1291
1292/*
1293 * The core can pass us a set of gamma values to program. We actually only
1294 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
1295 * but it's a requirement that we provide the function
1296 */
1297static void mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
1298 u16 *blue, uint32_t start, uint32_t size)
1299{
1300 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1301 int end = (start + size > MGAG200_LUT_SIZE) ? MGAG200_LUT_SIZE : start + size;
1302 int i;
1303
1304 for (i = start; i < end; i++) {
1305 mga_crtc->lut_r[i] = red[i] >> 8;
1306 mga_crtc->lut_g[i] = green[i] >> 8;
1307 mga_crtc->lut_b[i] = blue[i] >> 8;
1308 }
1309 mga_crtc_load_lut(crtc);
1310}
1311
1312/* Simple cleanup function */
1313static void mga_crtc_destroy(struct drm_crtc *crtc)
1314{
1315 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1316
1317 drm_crtc_cleanup(crtc);
1318 kfree(mga_crtc);
1319}
1320
Egbert Eich64c29072013-07-17 15:07:22 +02001321static void mga_crtc_disable(struct drm_crtc *crtc)
1322{
1323 int ret;
1324 DRM_DEBUG_KMS("\n");
1325 mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
Matt Roperf4510a22014-04-01 15:22:40 -07001326 if (crtc->primary->fb) {
1327 struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb);
Egbert Eich64c29072013-07-17 15:07:22 +02001328 struct drm_gem_object *obj = mga_fb->obj;
1329 struct mgag200_bo *bo = gem_to_mga_bo(obj);
1330 ret = mgag200_bo_reserve(bo, false);
1331 if (ret)
1332 return;
1333 mgag200_bo_push_sysram(bo);
1334 mgag200_bo_unreserve(bo);
1335 }
Matt Roperf4510a22014-04-01 15:22:40 -07001336 crtc->primary->fb = NULL;
Egbert Eich64c29072013-07-17 15:07:22 +02001337}
1338
Dave Airlie414c4532012-04-17 15:01:25 +01001339/* These provide the minimum set of functions required to handle a CRTC */
1340static const struct drm_crtc_funcs mga_crtc_funcs = {
Christopher Harveya080db92013-06-05 15:24:26 -04001341 .cursor_set = mga_crtc_cursor_set,
1342 .cursor_move = mga_crtc_cursor_move,
Dave Airlie414c4532012-04-17 15:01:25 +01001343 .gamma_set = mga_crtc_gamma_set,
1344 .set_config = drm_crtc_helper_set_config,
1345 .destroy = mga_crtc_destroy,
1346};
1347
1348static const struct drm_crtc_helper_funcs mga_helper_funcs = {
Egbert Eich64c29072013-07-17 15:07:22 +02001349 .disable = mga_crtc_disable,
Dave Airlie414c4532012-04-17 15:01:25 +01001350 .dpms = mga_crtc_dpms,
1351 .mode_fixup = mga_crtc_mode_fixup,
1352 .mode_set = mga_crtc_mode_set,
1353 .mode_set_base = mga_crtc_mode_set_base,
1354 .prepare = mga_crtc_prepare,
1355 .commit = mga_crtc_commit,
1356 .load_lut = mga_crtc_load_lut,
1357};
1358
1359/* CRTC setup */
Christopher Harveyf1998fe2013-02-20 09:34:22 -05001360static void mga_crtc_init(struct mga_device *mdev)
Dave Airlie414c4532012-04-17 15:01:25 +01001361{
Dave Airlie414c4532012-04-17 15:01:25 +01001362 struct mga_crtc *mga_crtc;
1363 int i;
1364
1365 mga_crtc = kzalloc(sizeof(struct mga_crtc) +
1366 (MGAG200FB_CONN_LIMIT * sizeof(struct drm_connector *)),
1367 GFP_KERNEL);
1368
1369 if (mga_crtc == NULL)
1370 return;
1371
Christopher Harveyf1998fe2013-02-20 09:34:22 -05001372 drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs);
Dave Airlie414c4532012-04-17 15:01:25 +01001373
1374 drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE);
1375 mdev->mode_info.crtc = mga_crtc;
1376
1377 for (i = 0; i < MGAG200_LUT_SIZE; i++) {
1378 mga_crtc->lut_r[i] = i;
1379 mga_crtc->lut_g[i] = i;
1380 mga_crtc->lut_b[i] = i;
1381 }
1382
1383 drm_crtc_helper_add(&mga_crtc->base, &mga_helper_funcs);
1384}
1385
1386/** Sets the color ramps on behalf of fbcon */
1387void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
1388 u16 blue, int regno)
1389{
1390 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1391
1392 mga_crtc->lut_r[regno] = red >> 8;
1393 mga_crtc->lut_g[regno] = green >> 8;
1394 mga_crtc->lut_b[regno] = blue >> 8;
1395}
1396
1397/** Gets the color ramps on behalf of fbcon */
1398void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
1399 u16 *blue, int regno)
1400{
1401 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1402
1403 *red = (u16)mga_crtc->lut_r[regno] << 8;
1404 *green = (u16)mga_crtc->lut_g[regno] << 8;
1405 *blue = (u16)mga_crtc->lut_b[regno] << 8;
1406}
1407
1408/*
1409 * The encoder comes after the CRTC in the output pipeline, but before
1410 * the connector. It's responsible for ensuring that the digital
1411 * stream is appropriately converted into the output format. Setup is
1412 * very simple in this case - all we have to do is inform qemu of the
1413 * colour depth in order to ensure that it displays appropriately
1414 */
1415
1416/*
1417 * These functions are analagous to those in the CRTC code, but are intended
1418 * to handle any encoder-specific limitations
1419 */
1420static bool mga_encoder_mode_fixup(struct drm_encoder *encoder,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02001421 const struct drm_display_mode *mode,
1422 struct drm_display_mode *adjusted_mode)
Dave Airlie414c4532012-04-17 15:01:25 +01001423{
1424 return true;
1425}
1426
1427static void mga_encoder_mode_set(struct drm_encoder *encoder,
1428 struct drm_display_mode *mode,
1429 struct drm_display_mode *adjusted_mode)
1430{
1431
1432}
1433
1434static void mga_encoder_dpms(struct drm_encoder *encoder, int state)
1435{
1436 return;
1437}
1438
1439static void mga_encoder_prepare(struct drm_encoder *encoder)
1440{
1441}
1442
1443static void mga_encoder_commit(struct drm_encoder *encoder)
1444{
1445}
1446
Rashika080fd6b2014-01-06 20:37:15 +05301447static void mga_encoder_destroy(struct drm_encoder *encoder)
Dave Airlie414c4532012-04-17 15:01:25 +01001448{
1449 struct mga_encoder *mga_encoder = to_mga_encoder(encoder);
1450 drm_encoder_cleanup(encoder);
1451 kfree(mga_encoder);
1452}
1453
1454static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = {
1455 .dpms = mga_encoder_dpms,
1456 .mode_fixup = mga_encoder_mode_fixup,
1457 .mode_set = mga_encoder_mode_set,
1458 .prepare = mga_encoder_prepare,
1459 .commit = mga_encoder_commit,
1460};
1461
1462static const struct drm_encoder_funcs mga_encoder_encoder_funcs = {
1463 .destroy = mga_encoder_destroy,
1464};
1465
1466static struct drm_encoder *mga_encoder_init(struct drm_device *dev)
1467{
1468 struct drm_encoder *encoder;
1469 struct mga_encoder *mga_encoder;
1470
1471 mga_encoder = kzalloc(sizeof(struct mga_encoder), GFP_KERNEL);
1472 if (!mga_encoder)
1473 return NULL;
1474
1475 encoder = &mga_encoder->base;
1476 encoder->possible_crtcs = 0x1;
1477
1478 drm_encoder_init(dev, encoder, &mga_encoder_encoder_funcs,
1479 DRM_MODE_ENCODER_DAC);
1480 drm_encoder_helper_add(encoder, &mga_encoder_helper_funcs);
1481
1482 return encoder;
1483}
1484
1485
1486static int mga_vga_get_modes(struct drm_connector *connector)
1487{
1488 struct mga_connector *mga_connector = to_mga_connector(connector);
1489 struct edid *edid;
1490 int ret = 0;
1491
1492 edid = drm_get_edid(connector, &mga_connector->i2c->adapter);
1493 if (edid) {
1494 drm_mode_connector_update_edid_property(connector, edid);
1495 ret = drm_add_edid_modes(connector, edid);
Dave Airlie414c4532012-04-17 15:01:25 +01001496 kfree(edid);
1497 }
1498 return ret;
1499}
1500
Julia Lemireabbee622013-06-27 13:38:59 -04001501static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
1502 int bits_per_pixel)
1503{
1504 uint32_t total_area, divisor;
1505 int64_t active_area, pixels_per_second, bandwidth;
1506 uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
1507
1508 divisor = 1024;
1509
1510 if (!mode->htotal || !mode->vtotal || !mode->clock)
1511 return 0;
1512
1513 active_area = mode->hdisplay * mode->vdisplay;
1514 total_area = mode->htotal * mode->vtotal;
1515
1516 pixels_per_second = active_area * mode->clock * 1000;
1517 do_div(pixels_per_second, total_area);
1518
1519 bandwidth = pixels_per_second * bytes_per_pixel * 100;
1520 do_div(bandwidth, divisor);
1521
1522 return (uint32_t)(bandwidth);
1523}
1524
1525#define MODE_BANDWIDTH MODE_BAD
1526
Dave Airlie414c4532012-04-17 15:01:25 +01001527static int mga_vga_mode_valid(struct drm_connector *connector,
1528 struct drm_display_mode *mode)
1529{
Christopher Harvey0ba53172013-02-26 10:55:44 -05001530 struct drm_device *dev = connector->dev;
1531 struct mga_device *mdev = (struct mga_device*)dev->dev_private;
Christopher Harvey0ba53172013-02-26 10:55:44 -05001532 int bpp = 32;
Christopher Harvey0ba53172013-02-26 10:55:44 -05001533
Julia Lemireabbee622013-06-27 13:38:59 -04001534 if (IS_G200_SE(mdev)) {
1535 if (mdev->unique_rev_id == 0x01) {
1536 if (mode->hdisplay > 1600)
1537 return MODE_VIRTUAL_X;
1538 if (mode->vdisplay > 1200)
1539 return MODE_VIRTUAL_Y;
1540 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1541 > (24400 * 1024))
1542 return MODE_BANDWIDTH;
1543 } else if (mdev->unique_rev_id >= 0x02) {
1544 if (mode->hdisplay > 1920)
1545 return MODE_VIRTUAL_X;
1546 if (mode->vdisplay > 1200)
1547 return MODE_VIRTUAL_Y;
1548 if (mga_vga_calculate_mode_bandwidth(mode, bpp)
1549 > (30100 * 1024))
1550 return MODE_BANDWIDTH;
1551 }
1552 } else if (mdev->type == G200_WB) {
1553 if (mode->hdisplay > 1280)
1554 return MODE_VIRTUAL_X;
1555 if (mode->vdisplay > 1024)
1556 return MODE_VIRTUAL_Y;
1557 if (mga_vga_calculate_mode_bandwidth(mode,
1558 bpp > (31877 * 1024)))
1559 return MODE_BANDWIDTH;
1560 } else if (mdev->type == G200_EV &&
1561 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1562 > (32700 * 1024))) {
1563 return MODE_BANDWIDTH;
Dave Airlieec22b4a2014-02-05 14:13:56 +10001564 } else if (mdev->type == G200_EH &&
Julia Lemireabbee622013-06-27 13:38:59 -04001565 (mga_vga_calculate_mode_bandwidth(mode, bpp)
1566 > (37500 * 1024))) {
1567 return MODE_BANDWIDTH;
Dave Airlieec22b4a2014-02-05 14:13:56 +10001568 } else if (mdev->type == G200_ER &&
Julia Lemireabbee622013-06-27 13:38:59 -04001569 (mga_vga_calculate_mode_bandwidth(mode,
1570 bpp) > (55000 * 1024))) {
1571 return MODE_BANDWIDTH;
1572 }
Dave Airlie414c4532012-04-17 15:01:25 +01001573
Adam Jackson25161082015-06-15 16:16:15 -04001574 if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 ||
1575 (mode->hsync_end % 8) != 0 || (mode->htotal % 8) != 0) {
1576 return MODE_H_ILLEGAL;
1577 }
1578
Dave Airlie414c4532012-04-17 15:01:25 +01001579 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
1580 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||
1581 mode->crtc_vdisplay > 2048 || mode->crtc_vsync_start > 4096 ||
1582 mode->crtc_vsync_end > 4096 || mode->crtc_vtotal > 4096) {
1583 return MODE_BAD;
1584 }
1585
Christopher Harvey0ba53172013-02-26 10:55:44 -05001586 /* Validate the mode input by the user */
Chris Wilsoneaf99c72014-08-06 10:08:32 +02001587 if (connector->cmdline_mode.specified) {
1588 if (connector->cmdline_mode.bpp_specified)
1589 bpp = connector->cmdline_mode.bpp;
Christopher Harvey0ba53172013-02-26 10:55:44 -05001590 }
1591
1592 if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
Chris Wilsoneaf99c72014-08-06 10:08:32 +02001593 if (connector->cmdline_mode.specified)
1594 connector->cmdline_mode.specified = false;
Christopher Harvey0ba53172013-02-26 10:55:44 -05001595 return MODE_BAD;
1596 }
1597
Dave Airlie414c4532012-04-17 15:01:25 +01001598 return MODE_OK;
1599}
1600
Rashika080fd6b2014-01-06 20:37:15 +05301601static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
Dave Airlie414c4532012-04-17 15:01:25 +01001602 *connector)
1603{
1604 int enc_id = connector->encoder_ids[0];
Dave Airlie414c4532012-04-17 15:01:25 +01001605 /* pick the encoder ids */
Rob Clarkc7e95112014-07-17 23:30:00 -04001606 if (enc_id)
1607 return drm_encoder_find(connector->dev, enc_id);
Dave Airlie414c4532012-04-17 15:01:25 +01001608 return NULL;
1609}
1610
1611static enum drm_connector_status mga_vga_detect(struct drm_connector
1612 *connector, bool force)
1613{
1614 return connector_status_connected;
1615}
1616
1617static void mga_connector_destroy(struct drm_connector *connector)
1618{
1619 struct mga_connector *mga_connector = to_mga_connector(connector);
1620 mgag200_i2c_destroy(mga_connector->i2c);
1621 drm_connector_cleanup(connector);
1622 kfree(connector);
1623}
1624
1625struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
1626 .get_modes = mga_vga_get_modes,
1627 .mode_valid = mga_vga_mode_valid,
1628 .best_encoder = mga_connector_best_encoder,
1629};
1630
1631struct drm_connector_funcs mga_vga_connector_funcs = {
1632 .dpms = drm_helper_connector_dpms,
1633 .detect = mga_vga_detect,
1634 .fill_modes = drm_helper_probe_single_connector_modes,
1635 .destroy = mga_connector_destroy,
1636};
1637
1638static struct drm_connector *mga_vga_init(struct drm_device *dev)
1639{
1640 struct drm_connector *connector;
1641 struct mga_connector *mga_connector;
1642
1643 mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL);
1644 if (!mga_connector)
1645 return NULL;
1646
1647 connector = &mga_connector->base;
1648
1649 drm_connector_init(dev, connector,
1650 &mga_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
1651
1652 drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
1653
Thomas Wood34ea3d32014-05-29 16:57:41 +01001654 drm_connector_register(connector);
Egbert Eich3d5a1c52013-07-17 15:07:25 +02001655
Dave Airlie414c4532012-04-17 15:01:25 +01001656 mga_connector->i2c = mgag200_i2c_create(dev);
1657 if (!mga_connector->i2c)
1658 DRM_ERROR("failed to add ddc bus\n");
1659
1660 return connector;
1661}
1662
1663
1664int mgag200_modeset_init(struct mga_device *mdev)
1665{
1666 struct drm_encoder *encoder;
1667 struct drm_connector *connector;
1668 int ret;
1669
1670 mdev->mode_info.mode_config_initialized = true;
1671
1672 mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
1673 mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
1674
1675 mdev->dev->mode_config.fb_base = mdev->mc.vram_base;
1676
Christopher Harveyf1998fe2013-02-20 09:34:22 -05001677 mga_crtc_init(mdev);
Dave Airlie414c4532012-04-17 15:01:25 +01001678
1679 encoder = mga_encoder_init(mdev->dev);
1680 if (!encoder) {
1681 DRM_ERROR("mga_encoder_init failed\n");
1682 return -1;
1683 }
1684
1685 connector = mga_vga_init(mdev->dev);
1686 if (!connector) {
1687 DRM_ERROR("mga_vga_init failed\n");
1688 return -1;
1689 }
1690
1691 drm_mode_connector_attach_encoder(connector, encoder);
1692
1693 ret = mgag200_fbdev_init(mdev);
1694 if (ret) {
1695 DRM_ERROR("mga_fbdev_init failed\n");
1696 return ret;
1697 }
1698
1699 return 0;
1700}
1701
1702void mgag200_modeset_fini(struct mga_device *mdev)
1703{
1704
1705}