diff options
Diffstat (limited to 'drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c')
-rw-r--r-- | drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c | 1376 |
1 files changed, 0 insertions, 1376 deletions
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c deleted file mode 100644 index d25675172a9e..000000000000 --- a/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c +++ /dev/null @@ -1,1376 +0,0 @@ -/* -*- pse-c -*- - *----------------------------------------------------------------------------- - * Filename: micro_mode_plb.c - * $Revision: 1.16 $ - *----------------------------------------------------------------------------- - * Copyright © 2002-2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - *----------------------------------------------------------------------------- - * Description: - * Napa Core implementations for the mode dispatch functions. - * NOTE: This file is designed to produce tiny code and is used in the - * vbios port. Make sure that all MMIO reads and writes do all mmio - * calculation within the OS_READ and OS_WRITE macros so that this code - * will be correctly removed. - * This is OK -> EMGD_READ32( MMIO(display) + foo_offset ) - * This is NOT OK -> mmio = MMIO(display) - * EMGD_READ32(mmio + foo_offset) - *----------------------------------------------------------------------------- - */ - -#define MODULE_NAME hal.mode - -#include <io.h> - -#include <igd.h> -#include <igd_pwr.h> - -#include <context.h> -#include <rb.h> -#include <mode.h> -#include <utils.h> -#include <dsp.h> -#include <vga.h> -#include <intelpci.h> -#include <mode_access.h> -#include <pi.h> -#include <dispatch.h> - -#include <plb/regs.h> -#include <plb/context.h> -#include <plb/mi.h> - -#include "../cmn/match.h" -#include "../cmn/mode_dispatch.h" - -/*! - * @addtogroup display_group - * @{ - */ - -#ifdef CONFIG_PLB - -typedef struct _mode_data_plb { - unsigned long plane_a_preserve; - unsigned long plane_b_c_preserve; - unsigned long pipe_preserve; - unsigned long port_preserve; - unsigned long fw_blc1; - unsigned long fw_blc2; - unsigned long fw_blc3; - unsigned long fw_self; - unsigned long mem_mode; - unsigned long dsp_arb; -}mode_data_plb_t; - -/* - * Exports from the other components of this module. - */ - -extern int program_clock_plb(igd_display_context_t *display, - igd_clock_t *clock, unsigned long dclk); -extern mode_full_dispatch_t mode_full_dispatch_plb; - -static unsigned long gpio_plb[] = { - 0x5010, - 0x5014, - 0x5018, - 0x501c, - 0x5020, - 0x5024, - 0x5028 -}; - -static mode_data_plb_t device_data[1] = { - { - 0x000b0000, /* plane a preservation */ - 0x00000000, /* plane b/c preservation */ - 0x01000000, /* pipe preservation */ - 0, /* port preservation */ - 0x490A010A, /* watermark/burst length 1 */ - 0x14100D0A, /* watermark/burst length 2*/ - 0x00007770, /* watermark/burst length 3 */ - 0x0B0C9812, /* watermark/burst length self */ - 0, /* mem_mode */ - 0x00001D9C, /* dsp arb */ - } -}; - - -/*! - * - * @param mmio - * - * @return void - */ -static void disable_vga_plb (unsigned char *mmio) -{ - unsigned long temp; - unsigned char sr01; - - EMGD_TRACE_ENTER; - - /* Disable VGA plane if it is enabled. */ - temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL); - if ((temp & BIT31) == 0) { - /* Read SR01 */ - READ_VGA(mmio, SR_PORT, 0x01, sr01); - - /* Turn on SR01 bit 5 */ - WRITE_VGA(mmio, SR_PORT, 0x01, sr01|BIT(5)); - /* Wait for 30us */ - OS_SLEEP(30); - - temp |= BIT31; /* set bit 31 to disable */ - temp &= ~BIT30; /* clear bit 30 to get VGA display in normal size */ - EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL); - } - /* - * When turing off the VGA plane the palette sometimes gets stuck. - * if we do a couple reads to the palette it will unstuck. - */ - if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEA_CONF )) { - EMGD_DEBUG("VGA Palette workaround"); - EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A); - EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A); - } - if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEB_CONF )) { - EMGD_DEBUG("VGA Palette workaround"); - EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B); - EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B); - } - - EMGD_TRACE_EXIT; -} - -/*! - * - * @param display_handle - * @param palette_entry - * @param palette_color - * - * @return 0 on success - * @return -IGD_INVAL on failure - */ -static int igd_set_palette_entry_plb( - igd_display_h display_handle, - unsigned long palette_entry, - unsigned long palette_color) -{ - /* Too Slow For Tracing */ - - /* Return if Pipe is not on */ - if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) + - PIPE(display_handle)->pipe_reg))) { - return -IGD_INVAL; - } - /* - EMGD_DEBUG("%x : %ld : %lx", display_handle, - palette_entry, palette_color); - */ - EMGD_WRITE32(palette_color, MMIO(display_handle) + - PIPE(display_handle)->palette_reg + palette_entry * 4); - - return 0; -} - -/*! - * - * @param display_handle - * @param palette_entry - * @param palette_color - * - * @return 0 on success - * @return -IGD_INVAL on failure - */ -static int igd_get_palette_entry_plb( - igd_display_h display_handle, - unsigned long palette_entry, - unsigned long *palette_color) -{ - /* Too Slow For Tracing */ - - /* Return if Pipe is not on */ - if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) + - PIPE(display_handle)->pipe_reg))) { - return -IGD_INVAL; - } - - *palette_color = 0xffffff & EMGD_READ32(MMIO(display_handle) + - PIPE(display_handle)->palette_reg + palette_entry * 4); - return 0; -} - -/*! - * - * @param mmio - * @param pipe_reg - * @param time_interval - * - * @return 0 on success - * @return 1 on failure - */ -int wait_for_vblank_timeout_plb( - unsigned char *mmio, - unsigned long pipe_reg, - unsigned long time_interval) -{ - int ret; - unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET; - unsigned long tmp; - os_alarm_t timeout; - unsigned long request_for; - - EMGD_TRACE_ENTER; - EMGD_DEBUG("Parameters: MMIO = %p, pipe_reg = %lx, time_interval = %lx", - mmio, pipe_reg, time_interval); - - /* If pipe is off then just return */ - if(!((1L<<31) & EMGD_READ32(EMGD_MMIO(mmio) + pipe_reg))) { - EMGD_DEBUG("Pipe disabled/Off"); - EMGD_TRACE_EXIT; - return 1; - } - - /* - * When VGA plane is on the normal wait for vblank won't work - * so just skip it. - */ - if(!(EMGD_READ32(EMGD_MMIO(mmio) + 0x71400) & 0x80000000)) { - EMGD_DEBUG("VGA Plane On"); - EMGD_TRACE_EXIT; - return 1; - } - - /* 1. Request the interrupt handler to record the next VBlank: */ - request_for = VBINT_REQUEST(VBINT_WAIT, - (pipe_status_reg == PIPEA_STAT) ? VBINT_PORT2 : VBINT_PORT4); - mode_context->dispatch->full->request_vblanks(request_for, mmio); - - /* 2. Wait & poll for the next VBlank: */ - timeout = OS_SET_ALARM(time_interval); - do { - OS_SCHEDULE(); - tmp = mode_context->dispatch->full->vblank_occured(request_for); - } while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout))); - if (tmp == 0) { - EMGD_ERROR_EXIT("Timeout waiting for VBLANK"); - ret = 0; - } else { - ret = 1; - } - - /* 3. End our request for the next VBlank: */ - mode_context->dispatch->full->end_request(request_for, mmio); - - - EMGD_TRACE_EXIT; - return ret; -} /* wait_for_vblank_timeout_plb */ - -/*! - * - * @param mmio - * @param pipe_reg - * - * @return 0 on success - * @return 1 on failure - */ -int wait_for_vblank_plb(unsigned char *mmio, - unsigned long pipe_reg) -{ - return wait_for_vblank_timeout_plb(mmio, pipe_reg, 100); -} /* wait_for_vblank_plb */ - -/*! - * This procedure waits for the next vertical blanking (vertical retrace) - * period. If the display is already in a vertical blanking period, this - * procedure exits. - * - * Note: A timeout is included to prevent an endless loop. - * - * @param display_handle - * - * @return FALSE if timed out - */ -static int igd_wait_vblank_plb(igd_display_h display_handle) -{ - - return wait_for_vblank_plb(MMIO(display_handle), - PIPE(display_handle)->pipe_reg); - -} /* wait_vblank */ - - -/*! - * Get the stride and stereo values based on the display. This is also used - * by the MI instructions. - * - * @param display Pointer to hardware device instance data - * @param stride - * @param stereo - * @param flags Should the stereo be for the frontbuffer or backbuffer? - * - * @return stride - Stride of the display - * @return stereo - Stereo address of the display - */ -static int mode_get_stride_stereo_plb(igd_display_context_t *display, - unsigned long *stride, - unsigned long *stereo, - unsigned long flags) -{ - unsigned long pitch = PLANE(display)->fb_info->screen_pitch; - igd_timing_info_t *timing = PIPE(display)->timing; - unsigned long base_offset; - - base_offset = PLANE(display)->fb_info->visible_offset; - - *stride = pitch; - *stereo = 0; - - /* For field replication, valid for interlaced modes only - * set stereo = fb_base, - * stride = pitch - */ - if (timing->mode_info_flags & IGD_SCAN_INTERLACE) { - - if(timing->mode_info_flags & IGD_LINE_DOUBLE) { - /* Interlaced + Line double flags means field replication. - * same lines are sent for both fields. Program the - * second eye to be same as the first. - */ - *stereo = base_offset; - } else { - /* Regular interlaced. Second eye starts on line 2. - * Skip every other line. - */ - *stereo = base_offset + pitch; - *stride = pitch * 2; - } - } - - return 0; -} - -/*! - * - * @param display Pointer to hardware device instance data - * - * @return void - */ -static void program_pipe_vga_plb( - igd_display_context_t *display) -{ - igd_timing_info_t *timing; - unsigned long vga_control; - unsigned long upscale = 0; - int centering = 1; - - EMGD_TRACE_ENTER; - -#ifdef CONFIG_MICRO - /* - * We cannot set a VGA mode unless the display planes are turned off. - * This becomes evident during a Windows BSOD. Since neither Windows - * nor IEGD got a chance to turn off these registers, and the VGA mode was - * set by the VBIOS, the screen gets corrupted. In order to fix this - * problem, we will turn the cursor and display planes here. - * - * Note: Removing previous partial-fix in favor of this complete one. - */ - /* Cursor A */ - WRITE_MMIO_REG(display, 0x70080, 0); - WRITE_MMIO_REG(display, 0x70084, 0); - /* Cursor B */ - WRITE_MMIO_REG(display, 0x700C0, 0); - WRITE_MMIO_REG(display, 0x700C4, 0); - /* Display A */ - WRITE_MMIO_REG(display, 0x70180, 0); - WRITE_MMIO_REG(display, 0x70184, 0); - /* Display B */ - WRITE_MMIO_REG(display, 0x71180, 0); - WRITE_MMIO_REG(display, 0x71184, 0); - /* Display C */ - WRITE_MMIO_REG(display, 0x72180, 0); - WRITE_MMIO_REG(display, 0x72184, 0); -#endif - - /* - * VGA Plane can attach to only one pipe at a time. LVDS can - * only attach to pipe B. We need to use the display passed to - * determine the pipe number to use. (Plba is same as Alm). - */ - - /* - * We can come here with following cases: - * 1. magic->vga CRT, DVI type displays - * 2. native->vga int-lvds, and up-scaling lvds displays - * 3. pipe->vga TV and other unscaled-lvds displays - */ - vga_control = READ_MMIO_REG(display, 0x71400); - vga_control &= 0x18e3ff00; - vga_control |= 0x8e; - - timing = PIPE(display)->timing; - if(!timing->extn_ptr) { - EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb"); - return; - } - - /* - * FIXME: For CONFIG_NEW_MATCH this should be replaced with a simple - * check of fp_native_dtd. Do not query the attribute. - */ - - /* Find UPSCALING attr value*/ - pi_pd_find_attr_and_value(PORT_OWNER(display), - PD_ATTR_ID_PANEL_FIT, - 0,/*no PD_FLAG for UPSCALING */ - NULL, /* dont need the attr ptr*/ - &upscale); - /* this PI func will not modify value of upscale if attr does not exist */ - - /* magic->vga or native->vga cases */ - if ((timing->width == 720 && timing->height == 400) || upscale) { - centering = 0; - } - - /* Enable border */ - if((timing->width >= 800) && !upscale) { - EMGD_DEBUG("Enable VGA Border"); - vga_control |= (1L<<26); - } - - if(timing->width == 640) { - EMGD_DEBUG("Enable Nine Dot Disable"); - vga_control |= (1L<<18); - } - - if(centering) { - EMGD_DEBUG("Enable VGA Center Centering"); - vga_control |= 1L<<24; - - if(timing->height >= 960) { - if(timing->width >= 1280) { - EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)"); - vga_control |= (1L<<30) | (1L<<18); - } - } - } else { - if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) { - EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable"); - vga_control |= (1L<<25 | (1L<<18)); - } else if (upscale) { - EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports"); - vga_control |= 1L<<25; - } - } - - if(PIPE(display)->pipe_num) { - vga_control |= 1L<<29; - } - - program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr); - WRITE_MMIO_REG(display, 0x71400, vga_control); - - EMGD_TRACE_EXIT; - return; -} - - -/*! - * Program Display Plane Values. - * - * @param display Pointer to hardware device instance data - * @param status - * - * @return void - */ -static void program_plane_plb(igd_display_context_t *display, - unsigned long status) -{ - unsigned long stereo; - unsigned long stride; - unsigned long size; - unsigned long plane_control; - igd_timing_info_t *timing; - igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; - unsigned long plane_reg = PLANE(display)->plane_reg; - unsigned long start_addr_reg = DSPAADDR; - - EMGD_TRACE_ENTER; - - EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE"); - EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display)); - - igd_wait_vblank_plb((igd_display_h)display); - - plane_control = EMGD_READ32(MMIO(display) + plane_reg); - if(PLANE(display)->plane_reg == DSPACNTR) { - plane_control &= device_data->plane_a_preserve; - } - else { /* if it's plane b or plane c */ - plane_control &= device_data->plane_b_c_preserve; - start_addr_reg = 0x71184; - } - - if((status == FALSE) || - (GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) { - - /* - * Note: The vga programming code does not have an "off". So - * when programming the plane to off we make sure VGA is off - * as well. - */ - disable_vga_plb(MMIO(display)); - - /* - * To turn off plane A or B, the program have to triger the plane A or B - * start register. Or else, it will not work. - */ - EMGD_WRITE32(plane_control, MMIO(display) + plane_reg); - EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg), - MMIO(display) + start_addr_reg); - - igd_wait_vblank_plb((igd_display_h)display); - return; - } - /* - * Note: The very first pass through this function will be with - * status false and timings == NULL. Don't use the timings before - * the check above. - */ - timing = PIPE(display)->timing; - /* There is a special case code for legacy VGA modes */ - while (timing->extn_ptr) { - timing = (igd_timing_info_t *)timing->extn_ptr; - } - if(MODE_IS_VGA(timing)) { - program_plane_vga(display, timing); - return; - } - - disable_vga_plb(MMIO(display)); - - size = (((unsigned long)timing->height - 1)<<16) | - (unsigned long)(timing->width - 1); - - /* enable plane, select pipe, enable gamma correction logic */ - plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24); - PIPE(display)->plane = PLANE(display); -#ifndef CONFIG_MICRO - plane_control |= (1<<30); -#endif - - /* Here the settings: - * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply - * If line dbling only, set 21,20 to 11b - * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply - * If no doubling, set 21,20 to 00b (no Horz Multiply) - * For pixel doubling - * --> both progressive/interlaced modes - * For Line doubling - * --> progressive modes only - */ - - if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) { - /* Line doubling in progressive mode requires special bits */ - if (timing->mode_info_flags & IGD_LINE_DOUBLE) { - /* BIT 20 for line & pixel doubling*/ - plane_control |= BIT20; - /* check later, if no pixel doubling, set bit 21 too*/ - } - } - if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) { - /* Horz pixel multiply must be set for double */ - plane_control |= BIT11; - /* TODO -> Plba can more than double, - It can 3X, 4X etc. These arent exposed now */ - } - else if(plane_control & BIT20){ - /* For line ONLY doubling, set bit 21 also '1' */ - plane_control |= BIT21; - } - - mode_get_stride_stereo_plb(display, &stride, &stereo, 0); - - /* set color depth */ - switch (IGD_PF_DEPTH(fb_info->pixel_format)) { - case PF_DEPTH_8: - plane_control |= BIT27 | BIT30; - break; - case PF_DEPTH_16: - plane_control |= BIT28 | BIT26; - break; - default: - case PF_DEPTH_32: - plane_control |= BIT28 | BIT27; - break; - } - - if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) { - plane_control |= (BIT30); - } - - EMGD_DEBUG(" Plane Control = 0x%lx", plane_control); - EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset); - EMGD_DEBUG(" Plane Pitch = 0x%lx", stride); - EMGD_DEBUG(" Plane Size = 0x%lx", size); - - EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET); - /* - * In reality this only exists for plane B. It doesn't seem to hurt - * plane A so just do it anyway and save us another case. - */ - EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET); - - /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET); - - This register is Reserved ON plba */ - EMGD_WRITE32(fb_info->visible_offset, - MMIO(display) + plane_reg + DSP_START_OFFSET); - - /* It seems we need push or trigger plane A/B to start to work - * on Poulsbo, especially for sDVO port. Let's write plane control - * register and start address register at last. - */ - EMGD_WRITE32(plane_control, MMIO(display) + plane_reg); - EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg), - MMIO(display) + start_addr_reg); - - igd_wait_vblank_plb((igd_display_h)display); - - EMGD_TRACE_EXIT; - return; -} - -/*! - * This function programs the Timing registers and clock registers and - * other control registers for PIPE. - * - * @param display - * @param status - * - * @return void - */ -static void program_pipe_plb(igd_display_context_t *display, - unsigned long status) -{ - unsigned long timing_reg; - unsigned long pipe_conf; - unsigned long hactive, vactive; - igd_timing_info_t *pTimings; - unsigned long temp; -#ifndef CONFIG_MICRO - igd_display_port_t *port; - int i; -#endif - - EMGD_TRACE_ENTER; - EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE"); - EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display)); - - pipe_conf = device_data->pipe_preserve & - EMGD_READ32(MMIO(display) + PIPE(display)->pipe_reg); - - /* Reset the plane of this pipe back to NULL, it will be set on the - * call to program_plane, which is ok, since program_pipe occurs - * before program_plane */ - PIPE(display)->plane = NULL; - - if((status == FALSE) || - (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) { - /* Disable pipe */ - EMGD_WRITE32(pipe_conf & (~0x80000000), - MMIO(display) + PIPE(display)->pipe_reg); - - return; - } - - pTimings = PIPE(display)->timing; - - /* - * If the mode is VGA and the PD says it handles all VGA modes without - * reprogramming then just set the mode and leave centering off. - */ - if(pTimings->mode_info_flags & IGD_MODE_VESA) { - if (pTimings->mode_number <= VGA_MODE_NUM_MAX) { - /* Pipe timings and clocks are not used but it must be on anyway */ - EMGD_WRITE32(pipe_conf | 0x80000000, - MMIO(display) + PIPE(display)->pipe_reg); - program_pipe_vga_plb(display); - return; - } else { -#ifdef CONFIG_MICRO - set_256_palette(MMIO(display)); -#endif - } - } - - /* Program dot clock divisors. */ - program_clock_plb(display, PIPE(display)->clock_reg, pTimings->dclk); - - /* Program timing registers for the pipe */ - timing_reg = PIPE(display)->timing_reg; - if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) { - hactive = (unsigned long)pTimings->width*2 - 1; - } else { - hactive = (unsigned long)pTimings->width - 1; - } - - if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) { - if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) { - vactive = (unsigned long)pTimings->height - 1; - } else { - vactive = (unsigned long)pTimings->height*2 - 1; - } - } else { - if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) { - vactive = (unsigned long)pTimings->height/2 - 1; - } else { - vactive = (unsigned long)pTimings->height - 1; - } - } - - /* - * DPLL should be on at this point which is required for touching - * the palette. - */ -#ifndef CONFIG_MICRO - /* reset the palette */ - for (i = 0; i < 256; i++) { - EMGD_WRITE32(((i<<16) | (i<<8) | i), - MMIO(display) + PIPE(display)->palette_reg + i*4); - } - - /* apply color correction */ - port = PORT_OWNER(display); - for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) { - - if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) || - (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) || - (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) { - - mode_context->dispatch->full->set_color_correct(display); - } - } -#endif - - /* - * NOTE: For size reasons the timng table contains unsigned short - * values. Don't shift them past 16. Use a temp instead. - * All register offsets and bit shift are verified for Napa - */ - temp = ((unsigned long)pTimings->htotal << 16) | hactive; - EMGD_WRITE32(temp, MMIO(display) + timing_reg); - - temp = ((unsigned long)pTimings->hblank_end << 16) | - (unsigned long)pTimings->hblank_start; - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x04); - - temp = ((unsigned long)pTimings->hsync_end << 16) | - (unsigned long)pTimings->hsync_start; - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x08); - - temp = ((unsigned long)pTimings->vtotal << 16) | vactive; - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x0C); - - temp = ((unsigned long)pTimings->vblank_end << 16) | - (unsigned long)pTimings->vblank_start; - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x10); - - temp = ((unsigned long)pTimings->vsync_end << 16) | - (unsigned long)pTimings->vsync_start; - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x14); - - /* - * If there is a linked mode it is either the VGA or a scaled - * mode. If it is scaled then we need to use it as the source size. - */ - if(pTimings->extn_ptr) { - igd_timing_info_t *scaled_timings = - (igd_timing_info_t *)pTimings->extn_ptr; - if((scaled_timings->mode_info_flags & IGD_MODE_VESA) && - (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) { - temp = (hactive << 16) | vactive; - } else { - temp = (unsigned long)scaled_timings->width - 1; - temp = (temp << 16) | - (unsigned long)(scaled_timings->height - 1); - } - } else { - temp = (hactive << 16) | vactive; - } - EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x1C); - - /* Set other registers */ - - /* - * FIXME: max_dclk needs to be determined from core clock - * at init time. 915 etc has several skus with different - * clocks for the same device ID. - * - */ - - /* These values are derived from the Poulsbo B-Spec as - * the suggested values */ - WRITE_MMIO_REG (display, FW_BLC1, device_data->fw_blc1); - WRITE_MMIO_REG (display, FW_BLC2, device_data->fw_blc2); - WRITE_MMIO_REG (display, FW_BLC3, device_data->fw_blc3); - WRITE_MMIO_REG (display, FW_BLC_SELF, device_data->fw_self); - WRITE_MMIO_REG (display, DSP_ARB, device_data->dsp_arb); - - /* The SGX 2D engine can saturate the memory bus and starve - * the display engine causing visible screen tearing. - * This reduces the priority of the SGX vs. display engine - */ - temp = READ_MMIO_REG (display, G_DEBUG); - WRITE_MMIO_REG (display, G_DEBUG, (temp | (1 << 11))); - - pipe_conf |= PIPE_ENABLE; - WRITE_MMIO_REG(display, PIPE(display)->pipe_reg, pipe_conf); - - /* - * Set the VGA address range to 0xa0000 so that a normal (not VGA) - * mode can be accessed through 0xa0000 in a 16bit world. - */ - WRITE_AR(MMIO(display), 0x10, 0xb); - WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5); - WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1); - - if(pTimings->extn_ptr) { - /* This means either internal scaling (LVDS) or centered VGA */ - pTimings = pTimings->extn_ptr; - if(pTimings->extn_ptr) { - /* This is both the scaled and centered VGA */ - pTimings = pTimings->extn_ptr; - } - if(pTimings->mode_info_flags & IGD_MODE_VESA) { - if (pTimings->mode_number <= VGA_MODE_NUM_MAX) { - program_pipe_vga_plb(display); - } else { -#ifdef CONFIG_MICRO - set_256_palette(MMIO(display)); -#endif - } - } - } - - EMGD_TRACE_EXIT; - return; -} - -/*! - * - * @param context - * - * @return void - */ -static void reset_plane_pipe_ports_plb(igd_context_t *context) -{ - igd_plane_t *plane; - igd_display_pipe_t *pipe; - igd_display_port_t *port,*tv_port=NULL; - unsigned long temp; - unsigned long i; - unsigned char *mmio; - inter_module_dispatch_t *md; - - EMGD_TRACE_ENTER; - - /* - * Disable all plane, pipe and port registers because the - * bios may have been using a different set. Only unset the - * enable bit. - */ - mmio = EMGD_MMIO(context->device_context.virt_mmadr); - md = &context->mod_dispatch; - - disable_vga_plb(EMGD_MMIO(mmio)); - - /* Turn off ports */ - port = NULL; - while((port = md->dsp_get_next_port(context, port, 0)) != NULL) { - /* if the port is TV, then don't set the power to S3 as this causes - * blank screen on analog port after killx or cosole mode, - * probably because the external clock needs to be on till the pipes and - * DPLLs are off - */ - if (port->pd_driver) { -#ifndef CONFIG_FASTBOOT - if(port->pd_type == PD_DISPLAY_TVOUT) { - tv_port = port; - }else { - port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3); - } -#endif - } - - /* Disable WRITE protection on PIPE B for parts with Int-LVDS*/ - /* This should never happen as the panel power was set to D3 above */ - if (port->port_reg == LVDSCNTR) { - if(EMGD_READ32(EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL) & 0x1) { - EMGD_WRITE32(0xABCD0000, EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL); - i=0; - while(i++ < 0x10) { - OS_SLEEP(10); - if((EMGD_READ32(EMGD_MMIO(mmio)+LVDS_PNL_PWR_STS)&BIT(31))==0) { - break; - } - } - } - } - - temp = EMGD_READ32(EMGD_MMIO(mmio) + port->port_reg); - EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + port->port_reg); - } - - plane = NULL; - while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) { - /* Only display display planes. - * Leave cursor, VGA, overlay, sprite planes alone since they will - * need a different disable bit/sequence. - */ - temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg); - if ((plane->plane_features & IGD_PLANE_DISPLAY)) { - if ( temp & BIT31 ) { - if(plane->plane_reg == DSPACNTR) { - EMGD_WRITE32((temp & device_data->plane_a_preserve), - EMGD_MMIO(mmio) + plane->plane_reg); - } - else { /* if it's plane b or plane c */ - EMGD_WRITE32((temp & device_data->plane_b_c_preserve), - EMGD_MMIO(mmio) + plane->plane_reg); - } - EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4); - } - } else if ((plane->plane_features & IGD_PLANE_CURSOR)) { - EMGD_WRITE32((temp & 0xffffffe8), - EMGD_MMIO(mmio) + plane->plane_reg); - EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4); - } - } - - /* Turn off pipes */ - pipe = NULL; - while ((pipe = md->dsp_get_next_pipe(context, pipe, 0))) { - wait_for_vblank_plb(EMGD_MMIO(mmio), pipe->pipe_reg); - temp = EMGD_READ32(EMGD_MMIO(mmio) + pipe->pipe_reg); - if ( temp & BIT31 ) { - EMGD_WRITE32((temp & device_data->pipe_preserve), - EMGD_MMIO(mmio) + pipe->pipe_reg); - } - } - /* pipes and DPLLs are off, now set the power for TV */ - if(tv_port && tv_port->pd_driver) { - tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3); - } - EMGD_TRACE_EXIT; - -} /* end reset_plane_pipe_ports */ - -/*! - * - * @param display - * @param port_number - * @param status - * - * @return 0 on success - * @return -IGD_ERROR_INVAL on failure - */ -static int program_port_plb(igd_display_context_t *display, - unsigned short port_number, - unsigned long status) -{ - unsigned long pipe_number; - unsigned long port_control; - unsigned long port_control_analog = 0; - unsigned long mult_port_control; - unsigned long pd_powerstate = 0; - unsigned long upscale = 0; - pd_timing_t *timing; - pd_timing_t local_timing; - unsigned long port_type; - int ret; - - /* get the pipe number */ - pipe_number = PIPE(display)->pipe_num; - - /* get the timings */ - timing = PIPE(display)->timing; - - /* keep the port type as local as we access it frequently */ - port_type = PORT(display, port_number)->port_type; - - /* Reading the preservation bits */ - port_control = PORT(display, port_number)->preserve & - READ_MMIO_REG(display, PORT(display, port_number)->port_reg); - - /* Reading the preservation bits for SDVO Gang Mode */ - mult_port_control = PORT(display, port_number)->mult_preserve & - READ_MMIO_REG(display, PORT(display, port_number)->port_reg); - - /* If status is false, quickly disable the display */ - if(status == FALSE) { - ret = PORT(display, port_number)->pd_driver->set_power( - PORT(display, port_number)->pd_context, PD_POWER_MODE_D3); - - if (ret) { - EMGD_ERROR_EXIT("PD set_power() returned: 0x%x", ret); - return -IGD_ERROR_INVAL; - } - - if(port_type == IGD_PORT_DIGITAL) { - WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg, - port_control); - - if(PORT(display, port_number)->mult_port) { - /* either gang mode or RGBA */ - WRITE_MMIO_REG(display, - PORT(display, port_number)->mult_port->port_reg, - mult_port_control); - } - } else if (port_type == IGD_PORT_ANALOG) { - port_control |= (BIT11 | BIT10); /* put in D3 state */ - WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg, - port_control); - - return 0; - } - return 0; - } - - EMGD_DEBUG("status isn't false, Check port enabled"); - - if(! (PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) { - return 0; - } - - /* - * Is this is the magic mode then turn on VGA syncs - */ - EMGD_DEBUG("Check vga_sync"); - if(PORT(display, port_number)->vga_sync == 1) { - /* - * Is this is the magic mode then turn on VGA syncs - */ - EMGD_DEBUG("VGA sync true, is width x height 720 x 400?"); - if((timing->width == 720) && (timing->height == 400)) { - EMGD_DEBUG("Modify port control and multi_port_control"); - port_control |= (1L<<15); - mult_port_control |= (1L<<15); - } - } - - EMGD_DEBUG("Check analog port"); - if(port_type == IGD_PORT_ANALOG) { - port_control |= (0x80000000 | (pipe_number<<30)); - if(timing->mode_info_flags & IGD_VSYNC_HIGH) { - port_control |= (1L<<4); - } - if(timing->mode_info_flags & IGD_HSYNC_HIGH) { - port_control |= (1L<<3); - } - /* To differentiate between analog and other ports */ - port_control_analog = port_control; - } - - EMGD_DEBUG("Get power state"); - EMGD_DEBUG("power state = %ld ", GET_DISPLAY_POWER_STATE(display, port_number)); - switch(GET_DISPLAY_POWER_STATE(display, port_number)) { - case IGD_POWERSTATE_D0: - EMGD_DEBUG("Power State is D0"); - pi_pd_find_attr_and_value(PORT(display, port_number), - PD_ATTR_ID_PANEL_FIT, - 0, /*no PD_FLAG for UPSCALING */ - NULL, /* dont need the attr ptr*/ - &upscale); - if(port_type == IGD_PORT_DIGITAL) { - /* Reach the end timing if upscaling is enabled */ - if (timing->extn_ptr && upscale) { - timing = (pd_timing_t *)timing->extn_ptr; - } - - local_timing = *timing; - if (upscale) { - /* For timings smaller than width 360 and height 200, - * double the size. This is because the active area of the mode - * is double the size of the resolution for these modes - * - Very tricky huh */ - if (local_timing.width <= 360) { - local_timing.width <<= 1; - } - if (local_timing.height <= 200) { - local_timing.height <<= 1; - } - } - - ret = PORT(display, port_number)->pd_driver->set_mode( - PORT(display, port_number)->pd_context, &local_timing, 0); - if (ret) { - EMGD_ERROR_EXIT("PD set_mode returned: 0x%x", ret); - return -IGD_ERROR_INVAL; - } - - /* in Plba B-Speecs, there are no bits, * - * for the polarity of the H-sync/V-sync */ - - /* in Plba B-Speecs, there are no bits, * - * for data ordering/format for DVO data */ - /* Gang-Mode and RGBA models are "exclusive-or" */ - if((PORT(display, port_number)->pd_driver->flags) & - PD_FLAG_GANG_MODE) { - mult_port_control |= (1L<<16); - } else if(PORT(display, port_number)->pd_type == PD_DISPLAY_RGBA) { - mult_port_control |= (1L<<2); - } - - timing = PIPE(display)->timing; - - if(timing->dclk > 100000) { - /* 100MPs < pixel rate < 200MPs */ - /* SDVO clock rate multiplier = 1x */ - /* - port_control &= ~BIT23; - mult_port_control |= ~BIT23; - redundant code since BIT23 is - already 0 at this point - */ - } else if(timing->dclk > 50000) { - /* 50MPs < pixel rate < 100MPs */ - /* SDVO clock rate multiplier = 2x */ - port_control |= (1L<<23); - mult_port_control |= (1L<<23); - } else { - /* 25MPs < pixel rate < 50MPs */ - /* SDVO clock rate multiplier = 4x */ - port_control |= (3L<<23); - mult_port_control |= (3L<<23); - } - - /* - * BIT7 = enable the border - * Do we need to disable the SDVO border for native - * VGA timings(i.e., use DE)? - * BIT22->BIT19 = setup the clock phase-9 - * BIT29 = enable the stall - * Only set stall on DVO-B for gang mode - * BIT30 = pipe number - * BIT31 = port enable - */ - port_control |= ( ( pipe_number<<30 ) | (BIT31) | ((0x9l) << 19) | - (BIT29) | (BIT7) ); - mult_port_control |= ( (BIT31) | ((0x9l) << 19) | (BIT7) ); - - WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg, - port_control); - - if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/ - WRITE_MMIO_REG(display, - PORT(display, port_number)->mult_port->port_reg, - mult_port_control); - } - return 0; - } else if(port_type == IGD_PORT_LVDS) { - /* - * There is a special case for LVDS scaling. If the timing is - * the native one and the extension points to another non-vga - * mode then send the extension pointer. - */ - /* Reach the end timing to get user requested mode */ - if(timing->extn_ptr) { - timing = (pd_timing_t *)timing->extn_ptr; - } - } - /* set mode will take care of port control */ - ret = PORT(display, port_number)->pd_driver->set_mode( - PORT(display, port_number)->pd_context, (pd_timing_t *)timing, - 1<<PIPE(display)->pipe_num); - if (ret) { - EMGD_ERROR_EXIT("PD set_mode returned: 0x%x",ret); - return -IGD_INVAL; - } - break; - case IGD_POWERSTATE_D1: - port_control_analog &= ~0x80000000; - port_control_analog |= 0x00000800 & - ~(PORT(display, port_number)->preserve); - pd_powerstate =PD_POWER_MODE_D1; - break; - case IGD_POWERSTATE_D2: - port_control_analog &= ~0x80000000; - port_control_analog |= 0x00000400 & - ~(PORT(display, port_number)->preserve); - pd_powerstate = PD_POWER_MODE_D2; - break; - case IGD_POWERSTATE_D3: - port_control_analog &= ~0x80000000; - port_control_analog |= 0x00003c00 & - ~(PORT(display, port_number)->preserve); - pd_powerstate = PD_POWER_MODE_D3; - break; - default: - EMGD_ERROR_EXIT("Invalid power state: 0x%lx", - GET_DISPLAY_POWER_STATE(display, port_number)); - return -IGD_ERROR_INVAL; - } - - ret = PORT(display, port_number)->pd_driver->set_power( - PORT(display, port_number)->pd_context, pd_powerstate); - if (ret) { - EMGD_ERROR_EXIT("PD set_power returned: 0x%x", ret); - return -IGD_ERROR_INVAL; - } - - if(port_type == IGD_PORT_DIGITAL) { - EMGD_DEBUG("Port_control = 0x%lx", port_control); - - WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg, - port_control); - if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/ - WRITE_MMIO_REG(display, - PORT(display, port_number)->mult_port->port_reg, - mult_port_control); - } - } - - EMGD_TRACE_EXIT; - return 0; -} - -/*! - * Status is currently not used - * - * @param display - * @param port_number - * @param status - * - * @return 0 on success - * @return 1 on failure - */ -static int post_program_port_plb(igd_display_context_t *display, - unsigned short port_number, - unsigned long status) -{ - int ret; - igd_display_port_t *port; - igd_timing_info_t *timings; - unsigned long portreg; - - EMGD_TRACE_ENTER; - - port = PORT(display, port_number); - timings = PIPE(display)->timing; - - /* - * Writing the sDVO control register here works around a problem - * where the sDVO port is not turning on when using a CH7308 - * card in a 915 GM based system and the port order is 5200. - * - * In addition, post_set_mode() below, will report that the - * "inputs are not trained", however, this does not seem to - * have any negative effects. - */ - portreg = READ_MMIO_REG(display, port->port_reg); - WRITE_MMIO_REG(display, port->port_reg, (portreg & ~BIT31)); - WRITE_MMIO_REG(display, port->port_reg, portreg); - - /* Reenable/Redisable other port */ - if (port->port_reg == 0x61140) { - WRITE_MMIO_REG(display, 0x61160, READ_MMIO_REG(display, - 0x61160)); - } else { - WRITE_MMIO_REG(display, 0x61140, - READ_MMIO_REG(display, 0x61140)); - } - - /* - * Added for Lakeport A0 - * Port clock multiplier bits 4-7, needs to be rewritten - */ - WRITE_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control, - READ_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control)); - - /* We must wait for 150 us for the dpll clock to warm up */ - OS_SLEEP(150); - - ret = 0; - /* call post_set_mode() if exists */ - if (port->pd_driver->post_set_mode) { - ret = port->pd_driver->post_set_mode(port->pd_context, timings, - 1<<PIPE(display)->pipe_num); - if (ret) { - EMGD_ERROR("PD post_set_mode returned: 0x%x", ret); - } - } - - EMGD_TRACE_EXIT; - return ret; -} - -/*! - * - * @param gpio - * - * @return size - */ -static unsigned long get_gpio_sets_plb(unsigned long **gpio) -{ - *gpio = gpio_plb; - return sizeof(gpio_plb)/sizeof(unsigned long); -} - -/*! - * - * @param context - * @param in_list - * - * @return void - To small to trace - */ -static void filter_modes_plb(igd_context_t *context, igd_display_port_t *port, - pd_timing_t *in_list) -{ - - return; -} - -#ifndef CONFIG_MICRO -int check_display_plb(igd_display_context_t *display, - unsigned short port_number, unsigned long status){ - /* For poulsbo display should be working fine */ - return TRUE; -} -#endif - -mode_dispatch_t mode_dispatch_plb = { - igd_set_palette_entry_plb, - igd_get_palette_entry_plb, - igd_wait_vblank_plb, - program_plane_plb, - program_pipe_plb, - program_port_plb, - post_program_port_plb, - program_clock_plb, - reset_plane_pipe_ports_plb, - get_gpio_sets_plb, - filter_modes_plb, - OPT_MICRO_VALUE(&check_display_plb, NULL), - NULL, - NULL, - NULL, - OPT_MICRO_VALUE(&mode_full_dispatch_plb, NULL) -}; - -#endif |