gma500: introduce some register maps
[deliverable/linux.git] / drivers / gpu / drm / gma500 / mdfld_intel_display.c
CommitLineData
026abc33
KS
1/*
2 * Copyright © 2006-2007 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Authors:
18 * Eric Anholt <eric@anholt.net>
19 */
20
21#include <linux/i2c.h>
22#include <linux/pm_runtime.h>
23
24#include <drm/drmP.h>
25#include "psb_intel_reg.h"
26#include "psb_intel_display.h"
27#include "framebuffer.h"
28#include "mdfld_output.h"
29#include "mdfld_dsi_output.h"
30
31/* Hardcoded currently */
32static int ksel = KSEL_CRYSTAL_19;
33
34struct psb_intel_range_t {
35 int min, max;
36};
37
38struct mrst_limit_t {
39 struct psb_intel_range_t dot, m, p1;
40};
41
42struct mrst_clock_t {
43 /* derived values */
44 int dot;
45 int m;
46 int p1;
47};
48
49#define COUNT_MAX 0x10000000
50
51void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
52{
53 int count, temp;
54 u32 pipeconf_reg = PIPEACONF;
55
56 switch (pipe) {
57 case 0:
58 break;
59 case 1:
60 pipeconf_reg = PIPEBCONF;
61 break;
62 case 2:
63 pipeconf_reg = PIPECCONF;
64 break;
65 default:
66 DRM_ERROR("Illegal Pipe Number.\n");
67 return;
68 }
69
70 /* FIXME JLIU7_PO */
71 psb_intel_wait_for_vblank(dev);
72 return;
73
74 /* Wait for for the pipe disable to take effect. */
75 for (count = 0; count < COUNT_MAX; count++) {
76 temp = REG_READ(pipeconf_reg);
77 if ((temp & PIPEACONF_PIPE_STATE) == 0)
78 break;
79 }
80}
81
82void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
83{
84 int count, temp;
85 u32 pipeconf_reg = PIPEACONF;
86
87 switch (pipe) {
88 case 0:
89 break;
90 case 1:
91 pipeconf_reg = PIPEBCONF;
92 break;
93 case 2:
94 pipeconf_reg = PIPECCONF;
95 break;
96 default:
97 DRM_ERROR("Illegal Pipe Number.\n");
98 return;
99 }
100
101 /* FIXME JLIU7_PO */
102 psb_intel_wait_for_vblank(dev);
103 return;
104
105 /* Wait for for the pipe enable to take effect. */
106 for (count = 0; count < COUNT_MAX; count++) {
107 temp = REG_READ(pipeconf_reg);
108 if ((temp & PIPEACONF_PIPE_STATE) == 1)
109 break;
110 }
111}
112
113static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
114{
115 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
116 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
117}
118
119static void psb_intel_crtc_commit(struct drm_crtc *crtc)
120{
121 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
122 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
123}
124
125static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
126 struct drm_display_mode *mode,
127 struct drm_display_mode *adjusted_mode)
128{
129 return true;
130}
131
132/**
133 * Return the pipe currently connected to the panel fitter,
134 * or -1 if the panel fitter is not present or not in use
135 */
136static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
137{
138 u32 pfit_control;
139
140 pfit_control = REG_READ(PFIT_CONTROL);
141
142 /* See if the panel fitter is in use */
143 if ((pfit_control & PFIT_ENABLE) == 0)
144 return -1;
145
146 /* 965 can place panel fitter on either pipe */
147 return (pfit_control >> 29) & 0x3;
148}
149
150static struct drm_device globle_dev;
151
152void mdfld__intel_plane_set_alpha(int enable)
153{
154 struct drm_device *dev = &globle_dev;
155 int dspcntr_reg = DSPACNTR;
156 u32 dspcntr;
157
158 dspcntr = REG_READ(dspcntr_reg);
159
160 if (enable) {
161 dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
162 dspcntr |= DISPPLANE_32BPP;
163 } else {
164 dspcntr &= ~DISPPLANE_32BPP;
165 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
166 }
167
168 REG_WRITE(dspcntr_reg, dspcntr);
169}
170
171static int check_fb(struct drm_framebuffer *fb)
172{
173 if (!fb)
174 return 0;
175
176 switch (fb->bits_per_pixel) {
177 case 8:
178 case 16:
179 case 24:
180 case 32:
181 return 0;
182 default:
183 DRM_ERROR("Unknown color depth\n");
184 return -EINVAL;
185 }
186}
187
188static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
189 struct drm_framebuffer *old_fb)
190{
191 struct drm_device *dev = crtc->dev;
192 /* struct drm_i915_master_private *master_priv; */
193 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
194 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
195 int pipe = psb_intel_crtc->pipe;
196 unsigned long start, offset;
197 int dsplinoff = DSPALINOFF;
198 int dspsurf = DSPASURF;
199 int dspstride = DSPASTRIDE;
200 int dspcntr_reg = DSPACNTR;
201 u32 dspcntr;
202 int ret;
203
204 memcpy(&globle_dev, dev, sizeof(struct drm_device));
205
206 dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
207
208 /* no fb bound */
209 if (!crtc->fb) {
210 dev_dbg(dev->dev, "No FB bound\n");
211 return 0;
212 }
213
214 ret = check_fb(crtc->fb);
215 if (ret)
216 return ret;
217
218 switch (pipe) {
219 case 0:
220 dsplinoff = DSPALINOFF;
221 break;
222 case 1:
223 dsplinoff = DSPBLINOFF;
224 dspsurf = DSPBSURF;
225 dspstride = DSPBSTRIDE;
226 dspcntr_reg = DSPBCNTR;
227 break;
228 case 2:
229 dsplinoff = DSPCLINOFF;
230 dspsurf = DSPCSURF;
231 dspstride = DSPCSTRIDE;
232 dspcntr_reg = DSPCCNTR;
233 break;
234 default:
235 DRM_ERROR("Illegal Pipe Number.\n");
236 return -EINVAL;
237 }
238
239 if (!gma_power_begin(dev, true))
240 return 0;
241
242 start = psbfb->gtt->offset;
243 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
244
245 REG_WRITE(dspstride, crtc->fb->pitches[0]);
246 dspcntr = REG_READ(dspcntr_reg);
247 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
248
249 switch (crtc->fb->bits_per_pixel) {
250 case 8:
251 dspcntr |= DISPPLANE_8BPP;
252 break;
253 case 16:
254 if (crtc->fb->depth == 15)
255 dspcntr |= DISPPLANE_15_16BPP;
256 else
257 dspcntr |= DISPPLANE_16BPP;
258 break;
259 case 24:
260 case 32:
261 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
262 break;
263 }
264 REG_WRITE(dspcntr_reg, dspcntr);
265
266 dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
267 start, offset, x, y);
268 REG_WRITE(dsplinoff, offset);
269 REG_READ(dsplinoff);
270 REG_WRITE(dspsurf, start);
271 REG_READ(dspsurf);
272
273 gma_power_end(dev);
274
275 return 0;
276}
277
278/*
279 * Disable the pipe, plane and pll.
280 *
281 */
282void mdfld_disable_crtc(struct drm_device *dev, int pipe)
283{
284 int dpll_reg = MRST_DPLL_A;
285 int dspcntr_reg = DSPACNTR;
286 int dspbase_reg = MRST_DSPABASE;
287 int pipeconf_reg = PIPEACONF;
288 u32 temp;
289
290 dev_dbg(dev->dev, "pipe = %d\n", pipe);
291
292
293 switch (pipe) {
294 case 0:
295 break;
296 case 1:
297 dpll_reg = MDFLD_DPLL_B;
298 dspcntr_reg = DSPBCNTR;
299 dspbase_reg = DSPBSURF;
300 pipeconf_reg = PIPEBCONF;
301 break;
302 case 2:
303 dpll_reg = MRST_DPLL_A;
304 dspcntr_reg = DSPCCNTR;
305 dspbase_reg = MDFLD_DSPCBASE;
306 pipeconf_reg = PIPECCONF;
307 break;
308 default:
309 DRM_ERROR("Illegal Pipe Number.\n");
310 return;
311 }
312
313 if (pipe != 1)
314 mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe),
315 HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
316
317 /* Disable display plane */
318 temp = REG_READ(dspcntr_reg);
319 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
320 REG_WRITE(dspcntr_reg,
321 temp & ~DISPLAY_PLANE_ENABLE);
322 /* Flush the plane changes */
323 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
324 REG_READ(dspbase_reg);
325 }
326
327 /* FIXME_JLIU7 MDFLD_PO revisit */
328
329 /* Next, disable display pipes */
330 temp = REG_READ(pipeconf_reg);
331 if ((temp & PIPEACONF_ENABLE) != 0) {
332 temp &= ~PIPEACONF_ENABLE;
333 temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
334 REG_WRITE(pipeconf_reg, temp);
335 REG_READ(pipeconf_reg);
336
337 /* Wait for for the pipe disable to take effect. */
338 mdfldWaitForPipeDisable(dev, pipe);
339 }
340
341 temp = REG_READ(dpll_reg);
342 if (temp & DPLL_VCO_ENABLE) {
343 if ((pipe != 1 &&
344 !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF))
345 & PIPEACONF_ENABLE)) || pipe == 1) {
346 temp &= ~(DPLL_VCO_ENABLE);
347 REG_WRITE(dpll_reg, temp);
348 REG_READ(dpll_reg);
349 /* Wait for the clocks to turn off. */
350 /* FIXME_MDFLD PO may need more delay */
351 udelay(500);
352
353 if (!(temp & MDFLD_PWR_GATE_EN)) {
354 /* gating power of DPLL */
355 REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
356 /* FIXME_MDFLD PO - change 500 to 1 after PO */
357 udelay(5000);
358 }
359 }
360 }
361
362}
363
364/**
365 * Sets the power management mode of the pipe and plane.
366 *
367 * This code should probably grow support for turning the cursor off and back
368 * on appropriately at the same time as we're turning the pipe off/on.
369 */
370static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
371{
372 struct drm_device *dev = crtc->dev;
373 struct drm_psb_private *dev_priv = dev->dev_private;
374 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
375 int pipe = psb_intel_crtc->pipe;
376 int dpll_reg = MRST_DPLL_A;
377 int dspcntr_reg = DSPACNTR;
378 int dspbase_reg = MRST_DSPABASE;
379 int pipeconf_reg = PIPEACONF;
380 u32 pipestat_reg = PIPEASTAT;
381 u32 pipeconf = dev_priv->pipeconf[pipe];
382 u32 temp;
026abc33
KS
383 int timeout = 0;
384
385 dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe);
386
387/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
388/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
389
390 switch (pipe) {
391 case 0:
392 break;
393 case 1:
394 dpll_reg = DPLL_B;
395 dspcntr_reg = DSPBCNTR;
396 dspbase_reg = MRST_DSPBBASE;
397 pipeconf_reg = PIPEBCONF;
398 dpll_reg = MDFLD_DPLL_B;
399 break;
400 case 2:
401 dpll_reg = MRST_DPLL_A;
402 dspcntr_reg = DSPCCNTR;
403 dspbase_reg = MDFLD_DSPCBASE;
404 pipeconf_reg = PIPECCONF;
405 pipestat_reg = PIPECSTAT;
406 break;
407 default:
408 DRM_ERROR("Illegal Pipe Number.\n");
409 return;
410 }
411
412 if (!gma_power_begin(dev, true))
413 return;
414
415 /* XXX: When our outputs are all unaware of DPMS modes other than off
416 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
417 */
418 switch (mode) {
419 case DRM_MODE_DPMS_ON:
420 case DRM_MODE_DPMS_STANDBY:
421 case DRM_MODE_DPMS_SUSPEND:
422 /* Enable the DPLL */
423 temp = REG_READ(dpll_reg);
424
425 if ((temp & DPLL_VCO_ENABLE) == 0) {
426 /* When ungating power of DPLL, needs to wait 0.5us
427 before enable the VCO */
428 if (temp & MDFLD_PWR_GATE_EN) {
429 temp &= ~MDFLD_PWR_GATE_EN;
430 REG_WRITE(dpll_reg, temp);
431 /* FIXME_MDFLD PO - change 500 to 1 after PO */
432 udelay(500);
433 }
434
435 REG_WRITE(dpll_reg, temp);
436 REG_READ(dpll_reg);
437 /* FIXME_MDFLD PO - change 500 to 1 after PO */
438 udelay(500);
439
440 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
441 REG_READ(dpll_reg);
442
443 /**
444 * wait for DSI PLL to lock
445 * NOTE: only need to poll status of pipe 0 and pipe 1,
446 * since both MIPI pipes share the same PLL.
447 */
448 while ((pipe != 2) && (timeout < 20000) &&
449 !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
450 udelay(150);
451 timeout++;
452 }
453 }
454
455 /* Enable the plane */
456 temp = REG_READ(dspcntr_reg);
457 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
458 REG_WRITE(dspcntr_reg,
459 temp | DISPLAY_PLANE_ENABLE);
460 /* Flush the plane changes */
461 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
462 }
463
464 /* Enable the pipe */
465 temp = REG_READ(pipeconf_reg);
466 if ((temp & PIPEACONF_ENABLE) == 0) {
467 REG_WRITE(pipeconf_reg, pipeconf);
468
469 /* Wait for for the pipe enable to take effect. */
470 mdfldWaitForPipeEnable(dev, pipe);
471 }
472
473 /*workaround for sighting 3741701 Random X blank display*/
474 /*perform w/a in video mode only on pipe A or C*/
475 if (pipe == 0 || pipe == 2) {
476 REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
477 msleep(100);
478 if (PIPE_VBLANK_STATUS & REG_READ(pipestat_reg))
479 dev_dbg(dev->dev, "OK");
480 else {
481 dev_dbg(dev->dev, "STUCK!!!!");
482 /*shutdown controller*/
483 temp = REG_READ(dspcntr_reg);
484 REG_WRITE(dspcntr_reg,
485 temp & ~DISPLAY_PLANE_ENABLE);
486 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
487 /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
488 REG_WRITE(0xb048, 1);
489 msleep(100);
490 temp = REG_READ(pipeconf_reg);
491 temp &= ~PIPEACONF_ENABLE;
492 REG_WRITE(pipeconf_reg, temp);
493 msleep(100); /*wait for pipe disable*/
494 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
495 msleep(100);
496 REG_WRITE(0xb004, REG_READ(0xb004));
497 /* try to bring the controller back up again*/
498 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
499 temp = REG_READ(dspcntr_reg);
500 REG_WRITE(dspcntr_reg,
501 temp | DISPLAY_PLANE_ENABLE);
502 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
503 /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
504 REG_WRITE(0xb048, 2);
505 msleep(100);
506 temp = REG_READ(pipeconf_reg);
507 temp |= PIPEACONF_ENABLE;
508 REG_WRITE(pipeconf_reg, temp);
509 }
510 }
511
512 psb_intel_crtc_load_lut(crtc);
513
514 /* Give the overlay scaler a chance to enable
515 if it's on this pipe */
516 /* psb_intel_crtc_dpms_video(crtc, true); TODO */
517
518 break;
519 case DRM_MODE_DPMS_OFF:
520 /* Give the overlay scaler a chance to disable
521 * if it's on this pipe */
522 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
523 if (pipe != 1)
524 mdfld_dsi_gen_fifo_ready(dev,
525 MIPI_GEN_FIFO_STAT_REG(pipe),
526 HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
527
528 /* Disable the VGA plane that we never use */
529 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
530
531 /* Disable display plane */
532 temp = REG_READ(dspcntr_reg);
533 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
534 REG_WRITE(dspcntr_reg,
535 temp & ~DISPLAY_PLANE_ENABLE);
536 /* Flush the plane changes */
537 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
538 REG_READ(dspbase_reg);
539 }
540
541 /* Next, disable display pipes */
542 temp = REG_READ(pipeconf_reg);
543 if ((temp & PIPEACONF_ENABLE) != 0) {
544 temp &= ~PIPEACONF_ENABLE;
545 temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
546 REG_WRITE(pipeconf_reg, temp);
547 REG_READ(pipeconf_reg);
548
549 /* Wait for for the pipe disable to take effect. */
550 mdfldWaitForPipeDisable(dev, pipe);
551 }
552
553 temp = REG_READ(dpll_reg);
554 if (temp & DPLL_VCO_ENABLE) {
555 if ((pipe != 1 && !((REG_READ(PIPEACONF)
556 | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
557 || pipe == 1) {
558 temp &= ~(DPLL_VCO_ENABLE);
559 REG_WRITE(dpll_reg, temp);
560 REG_READ(dpll_reg);
561 /* Wait for the clocks to turn off. */
562 /* FIXME_MDFLD PO may need more delay */
563 udelay(500);
564 }
565 }
566 break;
567 }
026abc33
KS
568 gma_power_end(dev);
569}
570
571
572#define MDFLD_LIMT_DPLL_19 0
573#define MDFLD_LIMT_DPLL_25 1
574#define MDFLD_LIMT_DPLL_83 2
575#define MDFLD_LIMT_DPLL_100 3
576#define MDFLD_LIMT_DSIPLL_19 4
577#define MDFLD_LIMT_DSIPLL_25 5
578#define MDFLD_LIMT_DSIPLL_83 6
579#define MDFLD_LIMT_DSIPLL_100 7
580
581#define MDFLD_DOT_MIN 19750
582#define MDFLD_DOT_MAX 120000
583#define MDFLD_DPLL_M_MIN_19 113
584#define MDFLD_DPLL_M_MAX_19 155
585#define MDFLD_DPLL_P1_MIN_19 2
586#define MDFLD_DPLL_P1_MAX_19 10
587#define MDFLD_DPLL_M_MIN_25 101
588#define MDFLD_DPLL_M_MAX_25 130
589#define MDFLD_DPLL_P1_MIN_25 2
590#define MDFLD_DPLL_P1_MAX_25 10
591#define MDFLD_DPLL_M_MIN_83 64
592#define MDFLD_DPLL_M_MAX_83 64
593#define MDFLD_DPLL_P1_MIN_83 2
594#define MDFLD_DPLL_P1_MAX_83 2
595#define MDFLD_DPLL_M_MIN_100 64
596#define MDFLD_DPLL_M_MAX_100 64
597#define MDFLD_DPLL_P1_MIN_100 2
598#define MDFLD_DPLL_P1_MAX_100 2
599#define MDFLD_DSIPLL_M_MIN_19 131
600#define MDFLD_DSIPLL_M_MAX_19 175
601#define MDFLD_DSIPLL_P1_MIN_19 3
602#define MDFLD_DSIPLL_P1_MAX_19 8
603#define MDFLD_DSIPLL_M_MIN_25 97
604#define MDFLD_DSIPLL_M_MAX_25 140
605#define MDFLD_DSIPLL_P1_MIN_25 3
606#define MDFLD_DSIPLL_P1_MAX_25 9
607#define MDFLD_DSIPLL_M_MIN_83 33
608#define MDFLD_DSIPLL_M_MAX_83 92
609#define MDFLD_DSIPLL_P1_MIN_83 2
610#define MDFLD_DSIPLL_P1_MAX_83 3
611#define MDFLD_DSIPLL_M_MIN_100 97
612#define MDFLD_DSIPLL_M_MAX_100 140
613#define MDFLD_DSIPLL_P1_MIN_100 3
614#define MDFLD_DSIPLL_P1_MAX_100 9
615
616static const struct mrst_limit_t mdfld_limits[] = {
617 { /* MDFLD_LIMT_DPLL_19 */
618 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
619 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
620 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
621 },
622 { /* MDFLD_LIMT_DPLL_25 */
623 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
624 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
625 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
626 },
627 { /* MDFLD_LIMT_DPLL_83 */
628 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
629 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
630 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
631 },
632 { /* MDFLD_LIMT_DPLL_100 */
633 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
634 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
635 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
636 },
637 { /* MDFLD_LIMT_DSIPLL_19 */
638 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
639 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
640 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
641 },
642 { /* MDFLD_LIMT_DSIPLL_25 */
643 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
644 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
645 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
646 },
647 { /* MDFLD_LIMT_DSIPLL_83 */
648 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
649 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
650 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
651 },
652 { /* MDFLD_LIMT_DSIPLL_100 */
653 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
654 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
655 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
656 },
657};
658
659#define MDFLD_M_MIN 21
660#define MDFLD_M_MAX 180
661static const u32 mdfld_m_converts[] = {
662/* M configuration table from 9-bit LFSR table */
663 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
664 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
665 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
666 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
667 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
668 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
669 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
670 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
671 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
672 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
673 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
674 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
675 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
676 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
677 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
678 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
679};
680
681static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc)
682{
683 const struct mrst_limit_t *limit = NULL;
684 struct drm_device *dev = crtc->dev;
685 struct drm_psb_private *dev_priv = dev->dev_private;
686
687 if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
688 || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
689 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
690 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
691 else if (ksel == KSEL_BYPASS_25)
692 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
693 else if ((ksel == KSEL_BYPASS_83_100) &&
694 (dev_priv->core_freq == 166))
695 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
696 else if ((ksel == KSEL_BYPASS_83_100) &&
697 (dev_priv->core_freq == 100 ||
698 dev_priv->core_freq == 200))
699 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
700 } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
701 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
702 limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
703 else if (ksel == KSEL_BYPASS_25)
704 limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
705 else if ((ksel == KSEL_BYPASS_83_100) &&
706 (dev_priv->core_freq == 166))
707 limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
708 else if ((ksel == KSEL_BYPASS_83_100) &&
709 (dev_priv->core_freq == 100 ||
710 dev_priv->core_freq == 200))
711 limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
712 } else {
713 limit = NULL;
714 dev_dbg(dev->dev, "mdfld_limit Wrong display type.\n");
715 }
716
717 return limit;
718}
719
720/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
721static void mdfld_clock(int refclk, struct mrst_clock_t *clock)
722{
723 clock->dot = (refclk * clock->m) / clock->p1;
724}
725
726/**
727 * Returns a set of divisors for the desired target clock with the given refclk,
728 * or FALSE. Divisor values are the actual divisors for
729 */
730static bool
731mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
732 struct mrst_clock_t *best_clock)
733{
734 struct mrst_clock_t clock;
735 const struct mrst_limit_t *limit = mdfld_limit(crtc);
736 int err = target;
737
738 memset(best_clock, 0, sizeof(*best_clock));
739
740 for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
741 for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
742 clock.p1++) {
743 int this_err;
744
745 mdfld_clock(refclk, &clock);
746
747 this_err = abs(clock.dot - target);
748 if (this_err < err) {
749 *best_clock = clock;
750 err = this_err;
751 }
752 }
753 }
754 return err != target;
755}
756
757static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
758 struct drm_display_mode *mode,
759 struct drm_display_mode *adjusted_mode,
760 int x, int y,
761 struct drm_framebuffer *old_fb)
762{
763 struct drm_device *dev = crtc->dev;
764 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
765 struct drm_psb_private *dev_priv = dev->dev_private;
766 int pipe = psb_intel_crtc->pipe;
767 int fp_reg = MRST_FPA0;
768 int dpll_reg = MRST_DPLL_A;
769 int dspcntr_reg = DSPACNTR;
770 int pipeconf_reg = PIPEACONF;
771 int htot_reg = HTOTAL_A;
772 int hblank_reg = HBLANK_A;
773 int hsync_reg = HSYNC_A;
774 int vtot_reg = VTOTAL_A;
775 int vblank_reg = VBLANK_A;
776 int vsync_reg = VSYNC_A;
777 int dspsize_reg = DSPASIZE;
778 int dsppos_reg = DSPAPOS;
779 int pipesrc_reg = PIPEASRC;
780 u32 *pipeconf = &dev_priv->pipeconf[pipe];
781 u32 *dspcntr = &dev_priv->dspcntr[pipe];
782 int refclk = 0;
783 int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0,
784 clk_tmp = 0;
785 struct mrst_clock_t clock;
786 bool ok;
787 u32 dpll = 0, fp = 0;
026abc33
KS
788 bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
789 struct drm_mode_config *mode_config = &dev->mode_config;
790 struct psb_intel_encoder *psb_intel_encoder = NULL;
791 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
792 struct drm_encoder *encoder;
793 struct drm_connector *connector;
794 int timeout = 0;
795 int ret;
796
797 dev_dbg(dev->dev, "pipe = 0x%x\n", pipe);
798
799#if 0
800 if (pipe == 1) {
801 if (!gma_power_begin(dev, true))
802 return 0;
803 android_hdmi_crtc_mode_set(crtc, mode, adjusted_mode,
804 x, y, old_fb);
805 goto mrst_crtc_mode_set_exit;
806 }
807#endif
808
809 switch (pipe) {
810 case 0:
811 break;
812 case 1:
813 fp_reg = FPB0;
814 dpll_reg = DPLL_B;
815 dspcntr_reg = DSPBCNTR;
816 pipeconf_reg = PIPEBCONF;
817 htot_reg = HTOTAL_B;
818 hblank_reg = HBLANK_B;
819 hsync_reg = HSYNC_B;
820 vtot_reg = VTOTAL_B;
821 vblank_reg = VBLANK_B;
822 vsync_reg = VSYNC_B;
823 dspsize_reg = DSPBSIZE;
824 dsppos_reg = DSPBPOS;
825 pipesrc_reg = PIPEBSRC;
826 fp_reg = MDFLD_DPLL_DIV0;
827 dpll_reg = MDFLD_DPLL_B;
828 break;
829 case 2:
830 dpll_reg = MRST_DPLL_A;
831 dspcntr_reg = DSPCCNTR;
832 pipeconf_reg = PIPECCONF;
833 htot_reg = HTOTAL_C;
834 hblank_reg = HBLANK_C;
835 hsync_reg = HSYNC_C;
836 vtot_reg = VTOTAL_C;
837 vblank_reg = VBLANK_C;
838 vsync_reg = VSYNC_C;
839 dspsize_reg = DSPCSIZE;
840 dsppos_reg = DSPCPOS;
841 pipesrc_reg = PIPECSRC;
842 break;
843 default:
844 DRM_ERROR("Illegal Pipe Number.\n");
845 return 0;
846 }
847
848 ret = check_fb(crtc->fb);
849 if (ret)
850 return ret;
851
852 dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
853 adjusted_mode->hdisplay);
854 dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
855 adjusted_mode->vdisplay);
856 dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
857 adjusted_mode->hsync_start);
858 dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
859 adjusted_mode->hsync_end);
860 dev_dbg(dev->dev, "adjusted_htotal = %d\n",
861 adjusted_mode->htotal);
862 dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
863 adjusted_mode->vsync_start);
864 dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
865 adjusted_mode->vsync_end);
866 dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
867 adjusted_mode->vtotal);
868 dev_dbg(dev->dev, "adjusted_clock = %d\n",
869 adjusted_mode->clock);
870 dev_dbg(dev->dev, "hdisplay = %d\n",
871 mode->hdisplay);
872 dev_dbg(dev->dev, "vdisplay = %d\n",
873 mode->vdisplay);
874
875 if (!gma_power_begin(dev, true))
876 return 0;
877
878 memcpy(&psb_intel_crtc->saved_mode, mode,
879 sizeof(struct drm_display_mode));
880 memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode,
881 sizeof(struct drm_display_mode));
882
883 list_for_each_entry(connector, &mode_config->connector_list, head) {
884 if (!connector)
885 continue;
886
887 encoder = connector->encoder;
888
889 if (!encoder)
890 continue;
891
892 if (encoder->crtc != crtc)
893 continue;
894
895 psb_intel_encoder = psb_intel_attached_encoder(connector);
896
897 switch (psb_intel_encoder->type) {
026abc33
KS
898 case INTEL_OUTPUT_MIPI:
899 is_mipi = true;
900 break;
901 case INTEL_OUTPUT_MIPI2:
902 is_mipi2 = true;
903 break;
904 case INTEL_OUTPUT_HDMI:
905 is_hdmi = true;
906 break;
907 }
908 }
909
910 /* Disable the VGA plane that we never use */
911 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
912
913 /* Disable the panel fitter if it was on our pipe */
914 if (psb_intel_panel_fitter_pipe(dev) == pipe)
915 REG_WRITE(PFIT_CONTROL, 0);
916
917 /* pipesrc and dspsize control the size that is scaled from,
918 * which should always be the user's requested size.
919 */
920 if (pipe == 1) {
921 /* FIXME: To make HDMI display with 864x480 (TPO), 480x864
922 * (PYR) or 480x854 (TMD), set the sprite width/height and
923 * souce image size registers with the adjusted mode for
924 * pipe B.
925 */
926
927 /*
928 * The defined sprite rectangle must always be completely
929 * contained within the displayable area of the screen image
930 * (frame buffer).
931 */
932 REG_WRITE(dspsize_reg, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
933 | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
934 /* Set the CRTC with encoder mode. */
935 REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
936 | (mode->crtc_vdisplay - 1));
937 } else {
938 REG_WRITE(dspsize_reg,
939 ((mode->crtc_vdisplay - 1) << 16) |
940 (mode->crtc_hdisplay - 1));
941 REG_WRITE(pipesrc_reg,
942 ((mode->crtc_hdisplay - 1) << 16) |
943 (mode->crtc_vdisplay - 1));
944 }
945
946 REG_WRITE(dsppos_reg, 0);
947
948 if (psb_intel_encoder)
949 drm_connector_property_get_value(connector,
950 dev->mode_config.scaling_mode_property, &scalingType);
951
952 if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
953 /* Medfield doesn't have register support for centering so we
954 * need to mess with the h/vblank and h/vsync start and ends
955 * to get centering
956 */
957 int offsetX = 0, offsetY = 0;
958
959 offsetX = (adjusted_mode->crtc_hdisplay -
960 mode->crtc_hdisplay) / 2;
961 offsetY = (adjusted_mode->crtc_vdisplay -
962 mode->crtc_vdisplay) / 2;
963
964 REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
965 ((adjusted_mode->crtc_htotal - 1) << 16));
966 REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
967 ((adjusted_mode->crtc_vtotal - 1) << 16));
968 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start -
969 offsetX - 1) |
970 ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
971 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start -
972 offsetX - 1) |
973 ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
974 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start -
975 offsetY - 1) |
976 ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
977 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start -
978 offsetY - 1) |
979 ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
980 } else {
981 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
982 ((adjusted_mode->crtc_htotal - 1) << 16));
983 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
984 ((adjusted_mode->crtc_vtotal - 1) << 16));
985 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
986 ((adjusted_mode->crtc_hblank_end - 1) << 16));
987 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
988 ((adjusted_mode->crtc_hsync_end - 1) << 16));
989 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
990 ((adjusted_mode->crtc_vblank_end - 1) << 16));
991 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
992 ((adjusted_mode->crtc_vsync_end - 1) << 16));
993 }
994
995 /* Flush the plane changes */
996 {
997 struct drm_crtc_helper_funcs *crtc_funcs =
998 crtc->helper_private;
999 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
1000 }
1001
1002 /* setup pipeconf */
1003 *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
1004
1005 /* Set up the display plane register */
1006 *dspcntr = REG_READ(dspcntr_reg);
1007 *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
1008 *dspcntr |= DISPLAY_PLANE_ENABLE;
1009
1010 if (is_mipi2)
1011 goto mrst_crtc_mode_set_exit;
1012 clk = adjusted_mode->clock;
1013
1014 if (is_hdmi) {
1015 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) {
1016 refclk = 19200;
1017
1018 if (is_mipi || is_mipi2)
1019 clk_n = 1, clk_p2 = 8;
1020 else if (is_hdmi)
1021 clk_n = 1, clk_p2 = 10;
1022 } else if (ksel == KSEL_BYPASS_25) {
1023 refclk = 25000;
1024
1025 if (is_mipi || is_mipi2)
1026 clk_n = 1, clk_p2 = 8;
1027 else if (is_hdmi)
1028 clk_n = 1, clk_p2 = 10;
1029 } else if ((ksel == KSEL_BYPASS_83_100) &&
1030 dev_priv->core_freq == 166) {
1031 refclk = 83000;
1032
1033 if (is_mipi || is_mipi2)
1034 clk_n = 4, clk_p2 = 8;
1035 else if (is_hdmi)
1036 clk_n = 4, clk_p2 = 10;
1037 } else if ((ksel == KSEL_BYPASS_83_100) &&
1038 (dev_priv->core_freq == 100 ||
1039 dev_priv->core_freq == 200)) {
1040 refclk = 100000;
1041 if (is_mipi || is_mipi2)
1042 clk_n = 4, clk_p2 = 8;
1043 else if (is_hdmi)
1044 clk_n = 4, clk_p2 = 10;
1045 }
1046
1047 if (is_mipi)
1048 clk_byte = dev_priv->bpp / 8;
1049 else if (is_mipi2)
1050 clk_byte = dev_priv->bpp2 / 8;
1051
1052 clk_tmp = clk * clk_n * clk_p2 * clk_byte;
1053
1054 dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d.\n",
1055 clk, clk_n, clk_p2);
1056 dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d.\n",
1057 adjusted_mode->clock, clk_tmp);
1058
1059 ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
1060
1061 if (!ok) {
1062 DRM_ERROR
1063 ("mdfldFindBestPLL fail in mdfld_crtc_mode_set.\n");
1064 } else {
1065 m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
1066
1067 dev_dbg(dev->dev, "dot clock = %d,"
1068 "m = %d, p1 = %d, m_conv = %d.\n",
1069 clock.dot, clock.m,
1070 clock.p1, m_conv);
1071 }
1072
1073 dpll = REG_READ(dpll_reg);
1074
1075 if (dpll & DPLL_VCO_ENABLE) {
1076 dpll &= ~DPLL_VCO_ENABLE;
1077 REG_WRITE(dpll_reg, dpll);
1078 REG_READ(dpll_reg);
1079
1080 /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
1081 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1082 udelay(500);
1083
1084 /* reset M1, N1 & P1 */
1085 REG_WRITE(fp_reg, 0);
1086 dpll &= ~MDFLD_P1_MASK;
1087 REG_WRITE(dpll_reg, dpll);
1088 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1089 udelay(500);
1090 }
1091
1092 /* When ungating power of DPLL, needs to wait 0.5us before
1093 * enable the VCO */
1094 if (dpll & MDFLD_PWR_GATE_EN) {
1095 dpll &= ~MDFLD_PWR_GATE_EN;
1096 REG_WRITE(dpll_reg, dpll);
1097 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1098 udelay(500);
1099 }
1100 dpll = 0;
1101
1102#if 0 /* FIXME revisit later */
1103 if (ksel == KSEL_CRYSTAL_19 || ksel == KSEL_BYPASS_19 ||
1104 ksel == KSEL_BYPASS_25)
1105 dpll &= ~MDFLD_INPUT_REF_SEL;
1106 else if (ksel == KSEL_BYPASS_83_100)
1107 dpll |= MDFLD_INPUT_REF_SEL;
1108#endif /* FIXME revisit later */
1109
1110 if (is_hdmi)
1111 dpll |= MDFLD_VCO_SEL;
1112
1113 fp = (clk_n / 2) << 16;
1114 fp |= m_conv;
1115
1116 /* compute bitmask from p1 value */
1117 dpll |= (1 << (clock.p1 - 2)) << 17;
1118
1119#if 0 /* 1080p30 & 720p */
1120 dpll = 0x00050000;
1121 fp = 0x000001be;
1122#endif
1123#if 0 /* 480p */
1124 dpll = 0x02010000;
1125 fp = 0x000000d2;
1126#endif
1127 } else {
1128#if 0 /*DBI_TPO_480x864*/
1129 dpll = 0x00020000;
1130 fp = 0x00000156;
1131#endif /* DBI_TPO_480x864 */ /* get from spec. */
1132
1133 dpll = 0x00800000;
1134 fp = 0x000000c1;
1135 }
1136
1137 REG_WRITE(fp_reg, fp);
1138 REG_WRITE(dpll_reg, dpll);
1139 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1140 udelay(500);
1141
1142 dpll |= DPLL_VCO_ENABLE;
1143 REG_WRITE(dpll_reg, dpll);
1144 REG_READ(dpll_reg);
1145
1146 /* wait for DSI PLL to lock */
1147 while (timeout < 20000 &&
1148 !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
1149 udelay(150);
1150 timeout++;
1151 }
1152
1153 if (is_mipi)
1154 goto mrst_crtc_mode_set_exit;
1155
1156 dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi);
1157
1158 REG_WRITE(pipeconf_reg, *pipeconf);
1159 REG_READ(pipeconf_reg);
1160
1161 /* Wait for for the pipe enable to take effect. */
1162 REG_WRITE(dspcntr_reg, *dspcntr);
1163 psb_intel_wait_for_vblank(dev);
1164
1165mrst_crtc_mode_set_exit:
1166
1167 gma_power_end(dev);
1168
1169 return 0;
1170}
1171
1172const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
1173 .dpms = mdfld_crtc_dpms,
1174 .mode_fixup = psb_intel_crtc_mode_fixup,
1175 .mode_set = mdfld_crtc_mode_set,
1176 .mode_set_base = mdfld__intel_pipe_set_base,
1177 .prepare = psb_intel_crtc_prepare,
1178 .commit = psb_intel_crtc_commit,
1179};
1180
This page took 0.08379 seconds and 5 git commands to generate.