Move the drivers to a separate sub-directory
[profile/ivi/intel-emgd-kmod.git] / drivers / emgd / display / mode / plb / micro_mode_plb.c
1 /*
2  *-----------------------------------------------------------------------------
3  * Filename: micro_mode_plb.c
4  * $Revision: 1.22 $
5  *-----------------------------------------------------------------------------
6  * Copyright (c) 2002-2010, Intel Corporation.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  *
26  *-----------------------------------------------------------------------------
27  * Description:
28  *  Napa Core implementations for the mode dispatch functions.
29  *  NOTE: This file is designed to produce tiny code and is used in the
30  *  vbios port. Make sure that all MMIO reads and writes do all mmio
31  *  calculation within the OS_READ and OS_WRITE macros so that this code
32  *  will be correctly removed.
33  *  This is OK -> EMGD_READ32( MMIO(display) + foo_offset )
34  *  This is NOT OK ->  mmio = MMIO(display)
35  *  EMGD_READ32(mmio + foo_offset)
36  *-----------------------------------------------------------------------------
37  */
38
39 #define MODULE_NAME hal.mode
40
41 #include <io.h>
42
43 #include <igd.h>
44 #include <igd_pwr.h>
45
46 #include <context.h>
47 #include <rb.h>
48 #include <mode.h>
49 #include <utils.h>
50 #include <dsp.h>
51 #include <vga.h>
52 #include <intelpci.h>
53 #include <mode_access.h>
54 #include <pi.h>
55 #include <dispatch.h>
56
57 #include <plb/regs.h>
58 #include <plb/context.h>
59 #include <plb/mi.h>
60 #include "drm_emgd_private.h"
61
62 #include "../cmn/match.h"
63 #include "../cmn/mode_dispatch.h"
64 #include "mode_plb.h"
65
66 /*!
67  * @addtogroup display_group
68  * @{
69  */
70
71 #ifdef CONFIG_PLB
72
73 /*
74  * Exports from the other components of this module.
75  */
76
77 extern int program_clock_plb(igd_display_context_t *display,
78         igd_clock_t *clock, unsigned long dclk);
79 extern mode_full_dispatch_t mode_full_dispatch_plb;
80
81 static unsigned long gpio_plb[] = {
82         0x5010,
83         0x5014,
84         0x5018,
85         0x501c,
86         0x5020,
87         0x5024,
88         0x5028
89 };
90
91 mode_data_plb_t device_data_plb[1] = {
92         {
93                 0x000b0000, /* plane a preservation */
94                 0x00000000, /* plane b/c preservation */
95                 0x01000000, /* pipe preservation */
96                 0, /* port preservation */
97                 0x490A010A, /* watermark/burst length 1 */
98                 0x14100D0A, /* watermark/burst length 2*/
99                 0x00007770, /* watermark/burst length 3 */
100                 0x0B0C9812, /* watermark/burst length self */
101                 0,  /* mem_mode */
102                 0x00001D9C, /* dsp arb */
103         }
104 };
105
106 /*!
107  *
108  * @param mmio
109  *
110  * @return void
111  */
112 void disable_vga_plb (unsigned char *mmio)
113 {
114         unsigned long temp;
115         unsigned char sr01;
116
117         EMGD_TRACE_ENTER;
118
119         /* Disable VGA plane if it is enabled. */
120         temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL);
121         if ((temp & BIT31) == 0) {
122                 /* Read SR01 */
123                 READ_VGA(mmio, SR_PORT, 0x01, sr01);
124
125                 /* Turn on SR01 bit 5 */
126                 WRITE_VGA(mmio, SR_PORT, 0x01, sr01|BIT(5));
127                 /* Wait for 30us */
128                 OS_SLEEP(30);
129
130                 temp |= BIT31;     /* set bit 31 to disable */
131                 temp &= ~BIT30;    /* clear bit 30 to get VGA display in normal size */
132                 EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL);
133         }
134         /*
135          * When turing off the VGA plane the palette sometimes gets stuck.
136          * if we do a couple reads to the palette it will unstuck.
137          */
138         if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEA_CONF )) {
139                 EMGD_DEBUG("VGA Palette workaround");
140                 EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A);
141                 EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A);
142         }
143         if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEB_CONF )) {
144                 EMGD_DEBUG("VGA Palette workaround");
145                 EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B);
146                 EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B);
147         }
148
149         EMGD_TRACE_EXIT;
150 }
151
152 /*!
153  *
154  * @param display_handle
155  * @param palette_entry
156  * @param palette_color
157  *
158  * @return 0 on success
159  * @return -IGD_INVAL on failure
160  */
161 static int igd_set_palette_entry_plb(
162         igd_display_h display_handle,
163         unsigned long palette_entry,
164         unsigned long palette_color)
165 {
166         /* Too Slow For Tracing */
167
168         /* Return if Pipe is not on */
169         if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) +
170                         PIPE(display_handle)->pipe_reg))) {
171                 return -IGD_INVAL;
172         }
173         /*
174         EMGD_DEBUG("%x : %ld : %lx", display_handle,
175                 palette_entry, palette_color);
176         */
177         EMGD_WRITE32(palette_color, MMIO(display_handle) +
178                 PIPE(display_handle)->palette_reg + palette_entry * 4);
179
180         return 0;
181 }
182
183 /*!
184  *
185  * @param display_handle
186  * @param palette_entry
187  * @param palette_color
188  *
189  * @return 0 on success
190  * @return -IGD_INVAL on failure
191  */
192 static int igd_get_palette_entry_plb(
193         igd_display_h display_handle,
194         unsigned long palette_entry,
195         unsigned long *palette_color)
196 {
197         /* Too Slow For Tracing */
198
199         /* Return if Pipe is not on */
200         if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) +
201                         PIPE(display_handle)->pipe_reg))) {
202                 return -IGD_INVAL;
203         }
204
205         *palette_color = 0xffffff & EMGD_READ32(MMIO(display_handle) +
206                 PIPE(display_handle)->palette_reg + palette_entry * 4);
207         return 0;
208 }
209
210 /*!
211  *
212  * @param mmio
213  * @param pipe_reg
214  * @param time_interval
215  *
216  * @return 0 on success
217  * @return 1 on failure
218  */
219 int wait_for_vblank_timeout_plb(
220         unsigned char *mmio,
221         unsigned long pipe_reg,
222         unsigned long time_interval)
223 {
224         int ret;
225         unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET;
226         unsigned long tmp;
227         os_alarm_t timeout;
228         unsigned long request_for;
229
230         EMGD_TRACE_ENTER;
231         EMGD_DEBUG("Parameters: MMIO = %p, pipe_reg = %lx, time_interval = %lx",
232                 mmio, pipe_reg, time_interval);
233
234         /* If pipe is off then just return */
235         if(!((1L<<31) & EMGD_READ32(EMGD_MMIO(mmio) + pipe_reg))) {
236                 EMGD_DEBUG("Pipe disabled/Off");
237                 EMGD_TRACE_EXIT;
238                 return 1;
239         }
240
241         /*
242          * When VGA plane is on the normal wait for vblank won't work
243          * so just skip it.
244          */
245         if(!(EMGD_READ32(EMGD_MMIO(mmio) + 0x71400) & 0x80000000)) {
246                 EMGD_DEBUG("VGA Plane On");
247                 EMGD_TRACE_EXIT;
248                 return 1;
249         }
250
251         /* 1. Request the interrupt handler to record the next VBlank: */
252         request_for = VBINT_REQUEST(VBINT_WAIT,
253                 (pipe_status_reg == PIPEA_STAT) ? VBINT_PORT2 : VBINT_PORT4);
254         mode_context->dispatch->full->request_vblanks(request_for, mmio);
255
256         /* 2. Wait & poll for the next VBlank: */
257         timeout = OS_SET_ALARM(time_interval);
258         do {
259                 OS_SCHEDULE();
260                 tmp = mode_context->dispatch->full->vblank_occured(request_for);
261         } while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout)));
262         if (tmp == 0) {
263                 EMGD_ERROR_EXIT("Timeout waiting for VBLANK");
264                 ret = 0;
265         } else {
266                 ret = 1;
267         }
268
269         /* 3. End our request for the next VBlank: */
270         mode_context->dispatch->full->end_request(request_for, mmio);
271
272
273         EMGD_TRACE_EXIT;
274         return ret;
275 } /* wait_for_vblank_timeout_plb */
276
277 /*!
278  *
279  * @param mmio
280  * @param pipe_reg
281  *
282  * @return 0 on success
283  * @return 1 on failure
284  */
285 int wait_for_vblank_plb(unsigned char *mmio,
286         unsigned long pipe_reg)
287 {
288         return wait_for_vblank_timeout_plb(mmio, pipe_reg, 100);
289 } /* wait_for_vblank_plb */
290
291
292 /*!
293  * This procedure waits for the next vertical blanking (vertical retrace)
294  * period. If the display is already in a vertical blanking period, this
295  * procedure exits.
296  *
297  * Note: A timeout is included to prevent an endless loop.
298  *
299  * @param display_handle
300  *
301  * @return FALSE if timed out
302  */
303 static int igd_wait_vblank_plb(igd_display_h display_handle)
304 {
305
306         return wait_for_vblank_plb(MMIO(display_handle),
307                 PIPE(display_handle)->pipe_reg);
308
309 }  /* wait_vblank */
310
311
312 /*!
313  * Get the stride and stereo values based on the display.  This is also used
314  * by the MI instructions.
315  *
316  * @param display Pointer to hardware device instance data
317  * @param stride
318  * @param stereo
319  * @param flags Should the stereo be for the frontbuffer or backbuffer?
320  *
321  * @return stride - Stride of the display
322  * @return stereo - Stereo address of the display
323  */
324 static int mode_get_stride_stereo_plb(igd_display_context_t *display,
325         unsigned long *stride,
326         unsigned long *stereo,
327         unsigned long flags)
328 {
329         unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
330         igd_timing_info_t *timing = PIPE(display)->timing;
331         unsigned long base_offset;
332
333         base_offset = PLANE(display)->fb_info->visible_offset;
334
335         *stride = pitch;
336         *stereo = 0;
337
338         /* For field replication, valid for interlaced modes only
339          *     set stereo = fb_base,
340          *         stride = pitch
341          */
342         if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
343
344                 if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
345                         /* Interlaced + Line double flags means field replication.
346                          * same lines are sent for both fields. Program the
347                          * second eye to be same as the first.
348                          */
349                         *stereo = base_offset;
350                 } else {
351                         /* Regular interlaced. Second eye starts on line 2.
352                          * Skip every other line.
353                          */
354                         *stereo = base_offset + pitch;
355                         *stride = pitch * 2;
356                 }
357         }
358
359         return 0;
360 }
361
362 /*!
363  *
364  * @param display Pointer to hardware device instance data
365  *
366  * @return void
367  */
368 static void program_pipe_vga_plb(
369         igd_display_context_t *display)
370 {
371         igd_timing_info_t *timing;
372         unsigned long vga_control;
373         unsigned long upscale = 0;
374         int centering = 1;
375
376         EMGD_TRACE_ENTER;
377
378 #ifdef CONFIG_MICRO
379         /*
380          * We cannot set a VGA mode unless the display planes are turned off.
381      * This becomes evident during a Windows BSOD.  Since neither Windows
382      * nor IEGD got a chance to turn off these registers, and the VGA mode was
383      * set by the VBIOS, the screen gets corrupted.  In order to fix this
384      * problem, we will turn the cursor and display planes here.
385      *
386      * Note: Removing previous partial-fix in favor of this complete one.
387          */
388     /* Cursor A */
389         WRITE_MMIO_REG(display, 0x70080, 0);
390         WRITE_MMIO_REG(display, 0x70084, 0);
391     /* Cursor B */
392         WRITE_MMIO_REG(display, 0x700C0, 0);
393         WRITE_MMIO_REG(display, 0x700C4, 0);
394     /* Display A */
395         WRITE_MMIO_REG(display, 0x70180, 0);
396         WRITE_MMIO_REG(display, 0x70184, 0);
397     /* Display B */
398         WRITE_MMIO_REG(display, 0x71180, 0);
399         WRITE_MMIO_REG(display, 0x71184, 0);
400     /* Display C */
401         WRITE_MMIO_REG(display, 0x72180, 0);
402         WRITE_MMIO_REG(display, 0x72184, 0);
403 #endif
404
405         /*
406          * VGA Plane can attach to only one pipe at a time. LVDS can
407          * only attach to pipe B. We need to use the display passed to
408          * determine the pipe number to use. (Plba is same as Alm).
409          */
410
411         /*
412          * We can come here with following cases:
413          *   1. magic->vga    CRT, DVI type displays
414          *   2. native->vga   int-lvds, and up-scaling lvds displays
415          *   3. pipe->vga     TV and other unscaled-lvds displays
416          */
417         vga_control = READ_MMIO_REG(display, 0x71400);
418         vga_control &= 0x18e3ff00;
419         vga_control |= 0x8e;
420
421         timing = PIPE(display)->timing;
422         if(!timing->extn_ptr) {
423                 EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb");
424                 return;
425         }
426
427         /* Find UPSCALING attr value*/
428         pi_pd_find_attr_and_value(PORT_OWNER(display),
429                         PD_ATTR_ID_PANEL_FIT,
430                         0,/*no PD_FLAG for UPSCALING */
431                         NULL, /* dont need the attr ptr*/
432                         &upscale);
433         /* this PI func will not modify value of upscale if attr does not exist */
434
435         /* magic->vga or native->vga cases */
436         if ((timing->width == 720 && timing->height == 400) || upscale) {
437                 centering = 0;
438         }
439
440         /* Enable border */
441         if((timing->width >= 800) && !upscale) {
442                 EMGD_DEBUG("Enable VGA Border");
443                 vga_control |= (1L<<26);
444         }
445
446         if(timing->width == 640) {
447                 EMGD_DEBUG("Enable Nine Dot Disable");
448                 vga_control |= (1L<<18);
449         }
450
451         if(centering) {
452                 EMGD_DEBUG("Enable VGA Center Centering");
453                 vga_control |= 1L<<24;
454
455                 if(timing->height >= 960) {
456                         if(timing->width >= 1280) {
457                                 EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
458                                 vga_control |= (1L<<30) | (1L<<18);
459                         }
460                 }
461         } else {
462                 if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
463                         EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
464                         vga_control |= (1L<<25 | (1L<<18));
465                 } else if (upscale) {
466                         EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
467                         vga_control |= 1L<<25;
468                 }
469         }
470
471         if(PIPE(display)->pipe_num) {
472                 vga_control |= 1L<<29;
473         }
474
475         program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
476         WRITE_MMIO_REG(display, 0x71400, vga_control);
477
478         EMGD_TRACE_EXIT;
479         return;
480 }
481
482 /*!
483  * Program Display Plane Values.
484  *
485  * @param display Pointer to hardware device instance data
486  * @param status
487  *
488  * @return void
489  */
490 static void program_plane_plb(igd_display_context_t *display,
491         unsigned long status)
492 {
493         unsigned long stereo;
494         unsigned long stride;
495         unsigned long size;
496         unsigned long plane_control;
497         igd_timing_info_t *timing;
498         igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
499         unsigned long plane_reg = PLANE(display)->plane_reg;
500         unsigned long start_addr_reg = DSPAADDR;
501
502         EMGD_TRACE_ENTER;
503
504         EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
505         EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
506
507         igd_wait_vblank_plb((igd_display_h)display);
508
509         plane_control = EMGD_READ32(MMIO(display) + plane_reg);
510         if(PLANE(display)->plane_reg == DSPACNTR) {
511                 plane_control &= device_data_plb->plane_a_preserve;
512         }
513         else { /* if it's plane b or plane c */
514                 plane_control &= device_data_plb->plane_b_c_preserve;
515                 start_addr_reg = 0x71184;
516         }
517
518         if((status == FALSE) ||
519                 (GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {
520
521                 /*
522                  * Note: The vga programming code does not have an "off". So
523                  * when programming the plane to off we make sure VGA is off
524                  * as well.
525                  */
526                 disable_vga_plb(MMIO(display));
527
528                 /*
529                  * To turn off plane A or B, the program have to triger the plane A or B
530                  * start register.  Or else, it will not work.
531                  */
532                 EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
533                 EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
534                         MMIO(display) + start_addr_reg);
535
536                 igd_wait_vblank_plb((igd_display_h)display);
537                 return;
538         }
539         /*
540          * Note: The very first pass through this function will be with
541          * status false and timings == NULL. Don't use the timings before
542          * the check above.
543          */
544         timing = PIPE(display)->timing;
545         /* There is a special case code for legacy VGA modes */
546         while (timing->extn_ptr) {
547                 timing = (igd_timing_info_t *)timing->extn_ptr;
548         }
549         if(MODE_IS_VGA(timing)) {
550                 program_plane_vga(display, timing);
551                 return;
552         }
553
554         disable_vga_plb(MMIO(display));
555
556         size = (((unsigned long)timing->height - 1)<<16) |
557                 (unsigned long)(timing->width - 1);
558
559         /* enable plane, select pipe, enable gamma correction logic */
560         plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
561         PIPE(display)->plane = PLANE(display);
562 #ifndef CONFIG_MICRO
563         plane_control |= (1<<30);
564 #endif
565
566         /* Here the settings:
567          *   If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
568          *   If line dbling only,    set 21,20 to 11b
569          *   If pixel dbling only,   set 21,20 to 00b, but set Horz Multiply
570          *   If no doubling,         set 21,20 to 00b (no Horz Multiply)
571          * For pixel doubling
572          *           --> both progressive/interlaced modes
573          * For Line doubling
574          *           --> progressive modes only
575          */
576
577         if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
578                 /* Line doubling in progressive mode requires special bits */
579                 if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
580                         /* BIT 20 for line & pixel doubling*/
581                         plane_control |= BIT20;
582                         /* check later, if no pixel doubling, set bit 21 too*/
583                 }
584         }
585         if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
586                 /* Horz pixel multiply must be set for double */
587                 plane_control |= BIT11;
588                 /* TODO -> Plba can more than double,
589                 It can 3X, 4X etc. These arent exposed now */
590         }
591         else if(plane_control & BIT20){
592                 /* For line ONLY doubling, set bit 21 also '1' */
593                 plane_control |= BIT21;
594         }
595
596         mode_get_stride_stereo_plb(display, &stride, &stereo, 0);
597
598         /* set color depth */
599         switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
600         case PF_DEPTH_8:
601                 plane_control |= BIT27 | BIT30;
602                 break;
603         case PF_DEPTH_16:
604                 plane_control |= BIT28 | BIT26;
605                 break;
606         default:
607         case PF_DEPTH_32:
608                 plane_control |= BIT28 | BIT27;
609                 break;
610         }
611
612         if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
613                 plane_control |= (BIT30);
614         }
615
616         EMGD_DEBUG(" Plane Control = 0x%lx", plane_control);
617         EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset);
618         EMGD_DEBUG(" Plane Pitch = 0x%lx", stride);
619         EMGD_DEBUG(" Plane Size = 0x%lx", size);
620
621         EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
622         /*
623          * In reality this only exists for plane B. It doesn't seem to hurt
624          * plane A so just do it anyway and save us another case.
625          */
626         EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);
627
628         /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);
629                 - This register is Reserved ON plba */
630         EMGD_WRITE32(fb_info->visible_offset,
631                 MMIO(display) + plane_reg + DSP_START_OFFSET);
632
633         /* It seems we need push or trigger plane A/B to start to work
634          * on Poulsbo, especially for sDVO port. Let's write plane control
635          * register and start address register at last.
636          */
637         EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
638         EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
639                 MMIO(display) + start_addr_reg);
640
641         igd_wait_vblank_plb((igd_display_h)display);
642
643         EMGD_TRACE_EXIT;
644         return;
645 }
646
647 /*!
648  * This function programs the Timing registers and clock registers and
649  * other control registers for PIPE.
650  *
651  * @param display
652  * @param status
653  *
654  * @return void
655  */
656 static void program_pipe_plb(igd_display_context_t *display,
657         unsigned long status)
658 {
659         unsigned long   timing_reg;
660         unsigned long   pipe_conf;
661         unsigned long   hactive, vactive;
662         igd_timing_info_t  *pTimings;
663         unsigned long temp;
664 #ifndef CONFIG_MICRO
665         igd_display_port_t *port;
666         int i;
667 #endif
668
669         EMGD_TRACE_ENTER;
670         EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE");
671         EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
672
673         pipe_conf = device_data_plb->pipe_preserve &
674                 EMGD_READ32(MMIO(display) + PIPE(display)->pipe_reg);
675
676         /* Reset the plane of this pipe back to NULL, it will be set on the
677          * call to program_plane, which is ok, since program_pipe occurs
678          * before program_plane */
679         PIPE(display)->plane = NULL;
680
681         if((status == FALSE) ||
682                 (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
683                 /* Disable pipe */
684                 EMGD_WRITE32(pipe_conf & (~0x80000000),
685                         MMIO(display) + PIPE(display)->pipe_reg);
686
687                 return;
688         }
689
690         pTimings = PIPE(display)->timing;
691
692         /*
693          * If the mode is VGA and the PD says it handles all VGA modes without
694          * reprogramming then just set the mode and leave centering off.
695          */
696         if(pTimings->mode_info_flags & IGD_MODE_VESA) {
697                 if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
698                         /* Pipe timings and clocks are not used but it must be on anyway */
699                         EMGD_WRITE32(pipe_conf | 0x80000000,
700                                 MMIO(display) + PIPE(display)->pipe_reg);
701                         program_pipe_vga_plb(display);
702                         return;
703                 } else {
704 #ifdef CONFIG_MICRO
705                         set_256_palette(MMIO(display));
706 #endif
707                 }
708         }
709
710         /* Program dot clock divisors. */
711         program_clock_plb(display, PIPE(display)->clock_reg, pTimings->dclk);
712
713         /* Program timing registers for the pipe */
714         timing_reg = PIPE(display)->timing_reg;
715         if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
716                 hactive = (unsigned long)pTimings->width*2 - 1;
717         } else {
718                 hactive = (unsigned long)pTimings->width - 1;
719         }
720
721         if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
722                 if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
723                         vactive = (unsigned long)pTimings->height - 1;
724                 } else {
725                         vactive = (unsigned long)pTimings->height*2 - 1;
726                 }
727         } else {
728                 if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
729                         vactive = (unsigned long)pTimings->height/2 - 1;
730                 } else {
731                         vactive = (unsigned long)pTimings->height - 1;
732                 }
733         }
734
735         /*
736          * DPLL should be on at this point which is required for touching
737          * the palette.
738          */
739 #ifndef CONFIG_MICRO
740         /* reset the palette */
741         for (i = 0; i < 256; i++) {
742                 EMGD_WRITE32(((i<<16) | (i<<8) | i),
743                         MMIO(display) + PIPE(display)->palette_reg + i*4);
744         }
745
746         /* apply color correction */
747         port = PORT_OWNER(display);
748         for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
749
750                 if ((PD_ATTR_ID_FB_GAMMA      == (port->attributes[i].id)) ||
751                         (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
752                         (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)))  {
753
754                         mode_context->dispatch->full->set_color_correct(display);
755                 }
756         }
757 #endif
758
759         /*
760          * NOTE: For size reasons the timng table contains unsigned short
761          * values. Don't shift them past 16. Use a temp instead.
762          * All register offsets and bit shift are verified for Napa
763          */
764         temp = ((unsigned long)pTimings->htotal << 16) | hactive;
765         EMGD_WRITE32(temp, MMIO(display) + timing_reg);
766
767         temp = ((unsigned long)pTimings->hblank_end << 16) |
768                 (unsigned long)pTimings->hblank_start;
769         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x04);
770
771         temp = ((unsigned long)pTimings->hsync_end << 16) |
772                 (unsigned long)pTimings->hsync_start;
773         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x08);
774
775         temp = ((unsigned long)pTimings->vtotal << 16) | vactive;
776         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x0C);
777
778         temp = ((unsigned long)pTimings->vblank_end << 16) |
779                 (unsigned long)pTimings->vblank_start;
780         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x10);
781
782         temp = ((unsigned long)pTimings->vsync_end << 16) |
783                 (unsigned long)pTimings->vsync_start;
784         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x14);
785
786         /*
787          * If there is a linked mode it is either the VGA or a scaled
788          * mode. If it is scaled then we need to use it as the source size.
789          */
790         if(pTimings->extn_ptr) {
791                 igd_timing_info_t *scaled_timings =
792                         (igd_timing_info_t *)pTimings->extn_ptr;
793                 if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
794                         (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
795                         temp = (hactive << 16) | vactive;
796                 } else {
797                         temp = (unsigned long)scaled_timings->width  - 1;
798                         temp = (temp << 16) |
799                                 (unsigned long)(scaled_timings->height - 1);
800                 }
801         } else {
802                 temp = (hactive << 16) | vactive;
803         }
804         EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x1C);
805
806         /* Set other registers */
807
808         /*
809          * FIXME: max_dclk needs to be determined from core clock
810          * at init time. 915 etc has several skus with different
811          * clocks for the same device ID.
812          *
813          */
814
815         /* These values are derived from the Poulsbo B-Spec as
816          * the suggested values */
817         WRITE_MMIO_REG (display, FW_BLC1, device_data_plb->fw_blc1);
818         WRITE_MMIO_REG (display, FW_BLC2, device_data_plb->fw_blc2);
819         WRITE_MMIO_REG (display, FW_BLC3, device_data_plb->fw_blc3);
820         WRITE_MMIO_REG (display, FW_BLC_SELF, device_data_plb->fw_self);
821         WRITE_MMIO_REG (display, PIPEA_DISP_ARB_CTRL, device_data_plb->dsp_arb);
822
823         /* The SGX 2D engine can saturate the memory bus and starve
824          * the display engine causing visible screen tearing.
825          * This reduces the priority of the SGX vs. display engine
826          */
827         temp = READ_MMIO_REG (display, G_DEBUG);
828         WRITE_MMIO_REG (display, G_DEBUG, (temp | (1 << 11)));
829
830         pipe_conf |= PIPE_ENABLE;
831         WRITE_MMIO_REG(display, PIPE(display)->pipe_reg, pipe_conf);
832
833         /*
834          * Set the VGA address range to 0xa0000 so that a normal (not VGA)
835          * mode can be accessed through 0xa0000 in a 16bit world.
836          */
837         WRITE_AR(MMIO(display), 0x10, 0xb);
838         WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
839         WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);
840
841         if(pTimings->extn_ptr) {
842                 /* This means either internal scaling (LVDS) or centered VGA */
843                 pTimings = pTimings->extn_ptr;
844                 if(pTimings->extn_ptr) {
845                         /* This is both the scaled and centered VGA */
846                         pTimings = pTimings->extn_ptr;
847                 }
848                 if(pTimings->mode_info_flags & IGD_MODE_VESA) {
849                         if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
850                                 program_pipe_vga_plb(display);
851                         } else {
852 #ifdef CONFIG_MICRO
853                                 set_256_palette(MMIO(display));
854 #endif
855                         }
856                 }
857         }
858
859         EMGD_TRACE_EXIT;
860         return;
861 }
862
863 /*!
864  *
865  * @param context
866  *
867  * @return void
868  */
869 static void reset_plane_pipe_ports_plb(igd_context_t *context)
870 {
871         igd_plane_t        *plane;
872         igd_display_pipe_t *pipe;
873         igd_display_port_t *port,*tv_port=NULL;
874         unsigned long temp;
875         unsigned long i;
876         unsigned char *mmio;
877         inter_module_dispatch_t *md;
878
879         EMGD_TRACE_ENTER;
880
881         /*
882          * Disable all plane, pipe and port registers because the
883          * bios may have been using a different set. Only unset the
884          * enable bit.
885          */
886         mmio = EMGD_MMIO(context->device_context.virt_mmadr);
887         md = &context->mod_dispatch;
888
889         disable_vga_plb(EMGD_MMIO(mmio));
890
891         /* Turn off ports */
892         port = NULL;
893         while((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
894                 /* if the port is TV, then don't set the power to S3 as this causes
895                  * blank screen on analog port after killx or cosole mode,
896                  * probably because the external clock needs to be on till the pipes and
897                  * DPLLs are off
898                  */
899                 if (port->pd_driver) {
900 #ifndef CONFIG_FASTBOOT
901                         if(port->pd_type == PD_DISPLAY_TVOUT) {
902                                 tv_port = port;
903                         }else {
904                                 port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3);
905                         }
906 #endif
907                 }
908
909                 /* Disable WRITE protection on PIPE B for parts with Int-LVDS*/
910                 /* This should never happen as the panel power was set to D3 above */
911                 if (port->port_reg == LVDSCNTR) {
912                         if(EMGD_READ32(EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL) & 0x1) {
913                                 EMGD_WRITE32(0xABCD0000, EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL);
914                                 i=0;
915                                 while(i++ < 0x10) {
916                                         OS_SLEEP(10);
917                                         if((EMGD_READ32(EMGD_MMIO(mmio)+LVDS_PNL_PWR_STS)&BIT(31))==0) {
918                                                 break;
919                                         }
920                                 }
921                         }
922                 }
923
924                 temp = EMGD_READ32(EMGD_MMIO(mmio) + port->port_reg);
925                 EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + port->port_reg);
926         }
927
928         /* disable plane C */
929         temp = EMGD_READ32(EMGD_MMIO(mmio) + DSPCCNTR);
930         if(temp & BIT31) {
931                 EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR);
932                 EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR + DSP_START_OFFSET);
933         }
934
935         plane = NULL;
936         while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) {
937                 /* Only display display planes.
938                  *  Leave cursor, VGA, overlay, sprite planes alone since they will
939                  *  need a different disable bit/sequence.
940                  */
941                 temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg);
942                 if ((plane->plane_features & IGD_PLANE_DISPLAY)) {
943                         if ( temp & BIT31 ) {
944                                 if(plane->plane_reg == DSPACNTR) {
945                                         EMGD_WRITE32((temp & device_data_plb->plane_a_preserve),
946                                                 EMGD_MMIO(mmio) + plane->plane_reg);
947                                 }
948                                 else { /* if it's plane b or plane c */
949                                         EMGD_WRITE32((temp & device_data_plb->plane_b_c_preserve),
950                                                 EMGD_MMIO(mmio) + plane->plane_reg);
951                                 }
952                                 EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
953                         }
954                 } else if ((plane->plane_features & IGD_PLANE_CURSOR)) {
955                         EMGD_WRITE32((temp & 0xffffffe8),
956                                 EMGD_MMIO(mmio) + plane->plane_reg);
957                         EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
958                 }
959         }
960
961         /* Turn off pipes */
962         pipe = NULL;
963         while ((pipe = md->dsp_get_next_pipe(context, pipe, 0))) {
964                 wait_for_vblank_plb(EMGD_MMIO(mmio), pipe->pipe_reg);
965                 temp = EMGD_READ32(EMGD_MMIO(mmio) + pipe->pipe_reg);
966                 if ( temp & BIT31 ) {
967                         EMGD_WRITE32((temp & device_data_plb->pipe_preserve),
968                                 EMGD_MMIO(mmio) + pipe->pipe_reg);
969                 }
970         }
971         /* pipes and DPLLs are off, now set the power for TV */
972         if(tv_port && tv_port->pd_driver) {
973                 tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3);
974         }
975         EMGD_TRACE_EXIT;
976
977 } /* end reset_plane_pipe_ports */
978
979 /*!
980  *
981  * @param display
982  * @param port_number
983  * @param status
984  *
985  * @return 0 on success
986  * @return -IGD_ERROR_INVAL on failure
987  */
988 static int      program_port_plb(igd_display_context_t *display,
989         unsigned short port_number,
990         unsigned long status)
991 {
992         unsigned long pipe_number;
993         unsigned long port_control;
994         unsigned long port_control_analog = 0;
995         unsigned long mult_port_control;
996         unsigned long pd_powerstate = 0;
997         unsigned long upscale = 0;
998         pd_timing_t *timing;
999         pd_timing_t local_timing;
1000         unsigned long port_type;
1001         int ret;
1002
1003         /* get the pipe number */
1004         pipe_number = PIPE(display)->pipe_num;
1005
1006         /* get the timings */
1007         timing = PIPE(display)->timing;
1008
1009         /* keep the port type as local as we access it frequently */
1010         port_type = PORT(display, port_number)->port_type;
1011
1012         /* Reading the preservation     bits */
1013         port_control = PORT(display, port_number)->preserve &
1014                 READ_MMIO_REG(display, PORT(display, port_number)->port_reg);
1015
1016         /* Reading the preservation bits for SDVO Gang Mode */
1017         mult_port_control = PORT(display, port_number)->mult_preserve &
1018                 READ_MMIO_REG(display, PORT(display, port_number)->port_reg);
1019
1020         /* If status is false, quickly disable the display */
1021         if(status == FALSE) {
1022                 ret = PORT(display, port_number)->pd_driver->set_power(
1023                                 PORT(display, port_number)->pd_context, PD_POWER_MODE_D3);
1024
1025                 if (ret) {
1026                         EMGD_ERROR_EXIT("PD set_power() returned: 0x%x", ret);
1027                         return -IGD_ERROR_INVAL;
1028                 }
1029
1030                 if(port_type == IGD_PORT_DIGITAL) {
1031                         WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
1032                                         port_control);
1033
1034                         if(PORT(display, port_number)->mult_port) {
1035                                 /* either gang mode or RGBA */
1036                                 WRITE_MMIO_REG(display,
1037                                                 PORT(display, port_number)->mult_port->port_reg,
1038                                                 mult_port_control);
1039                         }
1040                 } else if (port_type == IGD_PORT_ANALOG) {
1041                         port_control |= (BIT11 | BIT10);         /* put in D3 state */
1042                         WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
1043                                 port_control);
1044
1045                         return 0;
1046                 }
1047                 return 0;
1048         }
1049
1050         EMGD_DEBUG("status isn't false, Check port enabled");
1051
1052         if(! (PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
1053                 return 0;
1054         }
1055
1056         /*
1057          * Is this is the magic mode then turn on VGA syncs
1058          */
1059         EMGD_DEBUG("Check vga_sync");
1060         if(PORT(display, port_number)->vga_sync == 1) {
1061                 /*
1062                  * Is this is the magic mode then turn on VGA syncs
1063                  */
1064                 EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
1065                 if((timing->width == 720) && (timing->height == 400)) {
1066                         EMGD_DEBUG("Modify port control and multi_port_control");
1067                         port_control |= (1L<<15);
1068                         mult_port_control |= (1L<<15);
1069                 }
1070         }
1071
1072         EMGD_DEBUG("Check analog port");
1073         if(port_type == IGD_PORT_ANALOG) {
1074                 port_control |= (0x80000000 | (pipe_number<<30));
1075                 if(timing->mode_info_flags & IGD_VSYNC_HIGH) {
1076                         port_control |= (1L<<4);
1077                 }
1078                 if(timing->mode_info_flags & IGD_HSYNC_HIGH) {
1079                         port_control |= (1L<<3);
1080                 }
1081                 /* To differentiate     between analog and other ports */
1082                 port_control_analog = port_control;
1083         }
1084
1085         EMGD_DEBUG("Get power state");
1086         EMGD_DEBUG("power state = %ld ", GET_DISPLAY_POWER_STATE(display, port_number));
1087         switch(GET_DISPLAY_POWER_STATE(display, port_number)) {
1088         case IGD_POWERSTATE_D0:
1089                 EMGD_DEBUG("Power State is D0");
1090                 pi_pd_find_attr_and_value(PORT(display, port_number),
1091                         PD_ATTR_ID_PANEL_FIT,
1092                         0, /*no PD_FLAG for UPSCALING */
1093                         NULL, /* dont need the attr ptr*/
1094                         &upscale);
1095                 if(port_type == IGD_PORT_DIGITAL) {
1096                         /* Reach the end timing if upscaling is enabled */
1097                         if (timing->extn_ptr && upscale) {
1098                                 timing = (pd_timing_t *)timing->extn_ptr;
1099                         }
1100
1101                         local_timing = *timing;
1102                         if (upscale) {
1103                                 /* For timings smaller than width 360 and height 200,
1104                                  * double the size. This is because the active area of the mode
1105                                  * is double the size of the resolution for these modes
1106                                  *  - Very tricky huh */
1107                                 if (local_timing.width <= 360) {
1108                                         local_timing.width <<= 1;
1109                                 }
1110                                 if (local_timing.height <= 200) {
1111                                         local_timing.height <<= 1;
1112                                 }
1113                         }
1114
1115                         ret = PORT(display, port_number)->pd_driver->set_mode(
1116                                 PORT(display, port_number)->pd_context, &local_timing, 0);
1117                         if (ret) {
1118                                 EMGD_ERROR_EXIT("PD set_mode returned: 0x%x", ret);
1119                                 return -IGD_ERROR_INVAL;
1120                         }
1121
1122                         /* in Plba B-Speecs, there are no bits, *
1123                          * for the polarity of the H-sync/V-sync */
1124
1125                         /* in Plba B-Speecs, there are no bits,  *
1126                          * for data ordering/format for DVO data */
1127                         /* Gang-Mode and RGBA models are "exclusive-or" */
1128                         if((PORT(display, port_number)->pd_driver->flags) &
1129                                         PD_FLAG_GANG_MODE) {
1130                                 mult_port_control |= (1L<<16);
1131                         } else if(PORT(display, port_number)->pd_type == PD_DISPLAY_RGBA) {
1132                                 mult_port_control |= (1L<<2);
1133                         }
1134
1135                         timing = PIPE(display)->timing;
1136
1137                         if(timing->dclk > 100000) {
1138                                 /* 100MPs < pixel rate < 200MPs */
1139                                 /* SDVO clock rate multiplier = 1x */
1140                                 /*
1141                                 port_control &= ~BIT23;
1142                                 mult_port_control |= ~BIT23;
1143                                         redundant code since BIT23 is
1144                                         already 0 at this point
1145                                 */
1146                         } else if(timing->dclk > 50000) {
1147                                 /* 50MPs < pixel rate < 100MPs */
1148                                 /* SDVO clock rate multiplier = 2x */
1149                                 port_control |= (1L<<23);
1150                                 mult_port_control |= (1L<<23);
1151                         } else {
1152                                 /* 25MPs < pixel rate < 50MPs */
1153                                 /* SDVO clock rate multiplier = 4x */
1154                                 port_control |= (3L<<23);
1155                                 mult_port_control |= (3L<<23);
1156                         }
1157
1158                         /*
1159                          * BIT7 = enable the border
1160                          *   Do we need to disable the SDVO border for native
1161                          *   VGA timings(i.e.,  use     DE)?
1162                          * BIT22->BIT19 = setup the clock phase-9
1163                          * BIT29 = enable the stall
1164                          *   Only set stall on DVO-B for gang mode
1165                          * BIT30 = pipe number
1166                          * BIT31 = port enable
1167                          */
1168                         port_control |= ( ( pipe_number<<30 ) | (BIT31) | ((0x9l) << 19) |
1169                                         (BIT29) | (BIT7) );
1170                         mult_port_control |= ( (BIT31) | ((0x9l) << 19) | (BIT7) );
1171
1172                         WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
1173                                         port_control);
1174
1175                         if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
1176                                 WRITE_MMIO_REG(display,
1177                                                 PORT(display, port_number)->mult_port->port_reg,
1178                                                 mult_port_control);
1179                         }
1180                         return 0;
1181                 } else if(port_type == IGD_PORT_LVDS) {
1182                         /*
1183                          * There is     a special case for LVDS scaling. If     the     timing is
1184                          * the native one and the extension     points to another non-vga
1185                          * mode then send the extension pointer.
1186                          */
1187                         /* Reach the end timing to get user requested mode */
1188                         if(timing->extn_ptr) {
1189                                 timing = (pd_timing_t *)timing->extn_ptr;
1190                         }
1191                 }
1192                 /* set mode     will take care of port control */
1193                 ret = PORT(display, port_number)->pd_driver->set_mode(
1194                         PORT(display, port_number)->pd_context, (pd_timing_t *)timing,
1195                         1<<PIPE(display)->pipe_num);
1196                 if (ret) {
1197                         EMGD_ERROR_EXIT("PD set_mode returned: 0x%x",ret);
1198                         return -IGD_INVAL;
1199                 }
1200                 break;
1201         case IGD_POWERSTATE_D1:
1202                 port_control_analog &= ~0x80000000;
1203                 port_control_analog |= 0x00000800 &
1204                         ~(PORT(display, port_number)->preserve);
1205                 pd_powerstate =PD_POWER_MODE_D1;
1206                 break;
1207         case IGD_POWERSTATE_D2:
1208                 port_control_analog &= ~0x80000000;
1209                 port_control_analog |= 0x00000400 &
1210                         ~(PORT(display, port_number)->preserve);
1211                 pd_powerstate = PD_POWER_MODE_D2;
1212                 break;
1213         case IGD_POWERSTATE_D3:
1214                 port_control_analog &= ~0x80000000;
1215                 port_control_analog |= 0x00003c00 &
1216                         ~(PORT(display, port_number)->preserve);
1217                 pd_powerstate = PD_POWER_MODE_D3;
1218                 break;
1219         default:
1220                 EMGD_ERROR_EXIT("Invalid power state: 0x%lx",
1221                         GET_DISPLAY_POWER_STATE(display, port_number));
1222                 return -IGD_ERROR_INVAL;
1223         }
1224
1225         ret = PORT(display, port_number)->pd_driver->set_power(
1226                         PORT(display, port_number)->pd_context, pd_powerstate);
1227         if (ret) {
1228                 EMGD_ERROR_EXIT("PD set_power returned: 0x%x", ret);
1229                 return -IGD_ERROR_INVAL;
1230         }
1231
1232         if(port_type == IGD_PORT_DIGITAL) {
1233                 EMGD_DEBUG("Port_control = 0x%lx", port_control);
1234
1235                 WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
1236                                 port_control);
1237                 if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
1238                         WRITE_MMIO_REG(display,
1239                                         PORT(display, port_number)->mult_port->port_reg,
1240                                         mult_port_control);
1241                 }
1242         }
1243
1244         EMGD_TRACE_EXIT;
1245         return 0;
1246 }
1247
1248 /*!
1249  * Status is currently not used
1250  *
1251  * @param display
1252  * @param port_number
1253  * @param status
1254  *
1255  * @return 0 on success
1256  * @return 1 on failure
1257  */
1258 static int post_program_port_plb(igd_display_context_t *display,
1259         unsigned short port_number,
1260         unsigned long status)
1261 {
1262         int ret;
1263         igd_display_port_t *port;
1264         igd_timing_info_t  *timings;
1265         unsigned long portreg;
1266
1267         EMGD_TRACE_ENTER;
1268
1269         port = PORT(display, port_number);
1270         timings = PIPE(display)->timing;
1271
1272         /*
1273          * Writing the sDVO control register here works around a problem
1274          * where the sDVO port is not turning on when using a CH7308
1275          * card in a 915 GM based system and the port order is 5200.
1276          *
1277          * In addition, post_set_mode() below, will report that the
1278          * "inputs are not trained", however, this does not seem to
1279          * have any negative effects.
1280          */
1281         portreg = READ_MMIO_REG(display, port->port_reg);
1282         WRITE_MMIO_REG(display, port->port_reg, (portreg & ~BIT31));
1283         WRITE_MMIO_REG(display, port->port_reg, portreg);
1284
1285         /* Reenable/Redisable other     port */
1286         if (port->port_reg == 0x61140) {
1287                 WRITE_MMIO_REG(display, 0x61160, READ_MMIO_REG(display,
1288                                         0x61160));
1289         } else {
1290                 WRITE_MMIO_REG(display, 0x61140,
1291                                 READ_MMIO_REG(display, 0x61140));
1292         }
1293
1294         /*
1295          * Added for Lakeport A0
1296          * Port clock multiplier bits 4-7, needs to be rewritten
1297          */
1298         WRITE_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control,
1299                 READ_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control));
1300
1301         /* We must wait for 150 us for the dpll clock to warm up */
1302         OS_SLEEP(150);
1303
1304         ret = 0;
1305         /* call post_set_mode() if exists */
1306         if (port->pd_driver->post_set_mode) {
1307                 ret = port->pd_driver->post_set_mode(port->pd_context, timings,
1308                         1<<PIPE(display)->pipe_num);
1309                 if (ret) {
1310                         EMGD_ERROR("PD post_set_mode returned: 0x%x", ret);
1311                 }
1312         }
1313
1314         EMGD_TRACE_EXIT;
1315         return ret;
1316 }
1317
1318 int program_cdvo_plb(void)
1319 {
1320         return TRUE;
1321 }
1322
1323 /*!
1324  *
1325  * @param gpio
1326  *
1327  * @return size
1328  */
1329 static unsigned long get_gpio_sets_plb(unsigned long **gpio)
1330 {
1331         *gpio = gpio_plb;
1332         return sizeof(gpio_plb)/sizeof(unsigned long);
1333 }
1334
1335 /*!
1336  *
1337  * @param context
1338  * @param in_list
1339  *
1340  * @return void - To small to trace
1341  */
1342 static void filter_modes_plb(igd_context_t *context, igd_display_port_t *port,
1343         pd_timing_t *in_list)
1344 {
1345
1346         return;
1347 }
1348
1349 #ifndef CONFIG_MICRO
1350 int check_display_plb(igd_display_context_t *display,
1351                                           unsigned short port_number, unsigned long status){
1352         /* For poulsbo display should be working fine */
1353         return TRUE;
1354 }
1355 #endif
1356
1357 mode_dispatch_t mode_dispatch_plb = {
1358         igd_set_palette_entry_plb,
1359         igd_get_palette_entry_plb,
1360         igd_wait_vblank_plb,
1361         program_plane_plb,
1362         program_pipe_plb,
1363         program_port_plb,
1364         post_program_port_plb,
1365         program_clock_plb,
1366         program_cdvo_plb,
1367         reset_plane_pipe_ports_plb,
1368         get_gpio_sets_plb,
1369         filter_modes_plb,
1370         OPT_MICRO_VALUE(&check_display_plb, NULL),
1371         NULL,
1372         NULL,
1373         NULL,
1374         NULL,
1375         OPT_MICRO_VALUE(&mode_full_dispatch_plb, NULL),
1376 };
1377
1378 #endif