diff options
Diffstat (limited to 'drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c')
-rw-r--r-- | drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c | 2301 |
1 files changed, 0 insertions, 2301 deletions
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c deleted file mode 100644 index e18f07ca2625..000000000000 --- a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c +++ /dev/null @@ -1,2301 +0,0 @@ -/* -*- pse-c -*- - *----------------------------------------------------------------------------- - * Filename: micro_mode_tnc.c - * $Revision: 1.28 $ - *----------------------------------------------------------------------------- - * 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: - * 1) Atom E6xx Core implementations for the mode dispatch functions. - * 2) 0:2:0 = Device2 = LNC VGA - * 0:3:0 = Device3 = Atom E6xx overlay - * 3) For MMIO access: - * Dev2 only: Use EMGD_READ32(), EMGD_WRITE32(): less code - * Dev2/3: Use READ_MMIO_REG_TNC(), WRITE_MMIO_REG_TNC(): more code - * For code optimization sake use the right macro. - *----------------------------------------------------------------------------- - */ - -#define MODULE_NAME hal.mode - -#include <io.h> - -#include <igd.h> -#include <igd_pwr.h> - -#include <context.h> -#include <mode.h> -#include <utils.h> -#include <dsp.h> -#include <vga.h> -#include <intelpci.h> -#include <math_fix.h> -#include <mode_access.h> -#include <rb.h> -#include <pi.h> -#include <dispatch.h> - -#include <tnc/regs.h> -#include <tnc/context.h> -#include <tnc/mi.h> -#include <tnc/instr.h> -#include <tnc/igd_tnc_wa.h> - -#include "../cmn/match.h" -#include "../cmn/mode_dispatch.h" - -/* - Turning on FIB part workaround for all IALs, for vBIOS this will limit - the port drivers to one at a time (SDVO or LVDS)due to code size - */ - -/*! - * @addtogroup display_group - * @{ - */ - -/* - * Exports from the other components of this module. - */ - -#ifdef CONFIG_TNC - -extern int program_clock_tnc(igd_display_context_t *display, - igd_clock_t *clock, unsigned long dclk); - -extern mode_full_dispatch_t mode_full_dispatch_tnc; - -int wait_for_vblank_tnc(unsigned long pipe_reg); -static void wait_pipe(unsigned long pipe_reg, unsigned long check_on_off); - - -static void cdvo_signal(void); - -typedef struct _mode_data_tnc { - unsigned long plane_a_preserve; - unsigned long plane_b_c_preserve; - unsigned long pipe_preserve; - unsigned long dsp_arb; - unsigned long fifo_watermark1; - unsigned long fifo_watermark2; - unsigned long fifo_watermark3; - unsigned long fifo_watermark4; - unsigned long fifo_watermark5; - unsigned long fifo_watermark6; -} mode_data_tnc_t; - -static mode_data_tnc_t device_data[1] = { - { - 0x000b0000, /* plane a preservation */ - 0x00000000, /* plane b c preservation */ - 0x60000000, /* pipe preservation */ - 0x00003232, /* DSP FIFO Size A=50 B=50 C=28 May require fine tuning*/ - 0x3f8f0404, /* FIFO watermark control1 */ - 0x04040f04, /* FIFO watermark control2 */ - 0x00000000, /* FIFO watermark control3 */ - 0x04040404, /* FIFO watermark1 control4 */ - 0x04040404, /* FIFO watermark1 control5 */ - 0x00000078, /* FIFO watermark1 control6 */ - } -}; - -/* Do not change the order */ -static const unsigned long ports_tnc[2] = {IGD_PORT_LVDS, IGD_PORT_SDVO}; - -/* Extern defines for Device2, device3 and device31 iobases. - * For Atom E6xx all devices are always io_mapped. */ -extern unsigned char io_mapped; -extern unsigned short io_base; -extern unsigned char io_mapped_lvds; -extern unsigned short io_base_lvds; -extern unsigned char io_mapped_sdvo; -extern unsigned short io_base_sdvo; -extern unsigned char io_mapped_lpc; -extern unsigned short io_base_lpc; - - -#ifndef CONFIG_MICRO -#define CHECK_VGA(a) MODE_IS_VGA(a) -#ifdef DEBUG_BUILD_TYPE -#define FLAG(a) a -/* Debug configuration flag for B0 workaround. Workaround is turned on by default */ -static int flag_turn_off_port_wa = 1; /* Turn off port when sweeping */ -static int flag_enable_tuning_wa = 1; /* Disable sweeping flag */ -static int flag_basic_htotal_formula_wa = 1; /* Enable formula workaround flag */ -#else -/* Turn all workaround for release driver */ -#define FLAG(a) 1 -#endif - -/* VPhase variable */ -static int vphase = 0; /* The current value to enable vphase is 5 */ - -/* Temporary frame buffer */ -static igd_framebuffer_info_t fb_info_tmp = {0,0,0,0,0,0,0}; - -#else -#define CHECK_VGA(a) 1 -#endif - -pixel_crc_t compute_pixel_crc( pixel_crc_t pixel, pixel_crc_t new_pixel) -{ - pixel_crc_t pixel_crc_new; - - pixel_crc_new.pixel = 0x0; - - pixel_crc_new.bit.bit22 = pixel.bit.bit14; - pixel_crc_new.bit.bit21 = pixel.bit.bit13; - pixel_crc_new.bit.bit20 = pixel.bit.bit12; - pixel_crc_new.bit.bit19 = pixel.bit.bit11; - pixel_crc_new.bit.bit18 = pixel.bit.bit10; - pixel_crc_new.bit.bit17 = pixel.bit.bit9; - pixel_crc_new.bit.bit16 = pixel.bit.bit22 ^ pixel.bit.bit8; - pixel_crc_new.bit.bit15 = pixel.bit.bit21 ^ pixel.bit.bit7; - pixel_crc_new.bit.bit14 = pixel.bit.bit20 ^ pixel.bit.bit6; - pixel_crc_new.bit.bit13 = pixel.bit.bit19 ^ pixel.bit.bit5; - pixel_crc_new.bit.bit12 = pixel.bit.bit18 ^ pixel.bit.bit4; - pixel_crc_new.bit.bit11 = pixel.bit.bit17 ^ pixel.bit.bit3; - pixel_crc_new.bit.bit10 = pixel.bit.bit16 ^ pixel.bit.bit2; - pixel_crc_new.bit.bit9 = pixel.bit.bit15 ^ pixel.bit.bit1; - pixel_crc_new.bit.bit8 = pixel.bit.bit0; - pixel_crc_new.bit.bit7 = pixel.bit.bit22 ^ new_pixel.bit.bit0; - pixel_crc_new.bit.bit6 = pixel.bit.bit21 ^ new_pixel.bit.bit1; - pixel_crc_new.bit.bit5 = pixel.bit.bit20 ^ new_pixel.bit.bit2; - pixel_crc_new.bit.bit4 = pixel.bit.bit19 ^ new_pixel.bit.bit3; - pixel_crc_new.bit.bit3 = pixel.bit.bit18 ^ new_pixel.bit.bit4; - pixel_crc_new.bit.bit2 = pixel.bit.bit17 ^ new_pixel.bit.bit5; - pixel_crc_new.bit.bit1 = pixel.bit.bit16 ^ new_pixel.bit.bit6; - pixel_crc_new.bit.bit0 = pixel.bit.bit15 ^ new_pixel.bit.bit7; - - return (pixel_crc_new); -} - -#ifndef CONFIG_MICRO -int check_display_tnc(igd_display_context_t *display, - unsigned short port_number,unsigned long status) -{ - pixel_crc_t red_val, green_val, blue_val; - pixel_crc_t blue_crc, green_crc, red_crc; - int i, j, bps = 4, ret_val = 0; - unsigned long *curr_pixel, sync = 0, size = 0, dc; - unsigned long tnc_crc_red, tnc_crc_green, tnc_crc_blue, temp; - unsigned long temp_plane, temp_pitch, temp_control, plane_control; - unsigned long pt = PORT_TYPE(display); - igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; - igd_timing_info_t pTimings_tmp, *pTimings_ext,*pTimings = PIPE(display)->timing; - /* igd_display_port_t *port = PORT_OWNER(display); */ - igd_rect_t dst_rect; - igd_surface_t front_buffer; - tnc_wa_timing_t *wa = WA_TUNE; - os_alarm_t timeout; - - EMGD_TRACE_ENTER; - - dc = *(display->context->mod_dispatch.dsp_current_dc); - pTimings_tmp = *pTimings; - pTimings_ext = pTimings; - - /* Check to see if VGA plane was requested */ - while (pTimings_ext->extn_ptr) { - pTimings_ext = (igd_timing_info_t *)pTimings_ext->extn_ptr; - } - if((pt != IGD_PORT_SDVO) || (display->context->device_context.rid != TNC_B0_RID) - || (pTimings->reserved_dd & TNC_HTOTAL_TUNED) || (!FLAG(flag_enable_tuning_wa)) - || wa->counter > LIMIT_TOTAL_CHECK_DISPLAY - || (MODE_IS_VGA(pTimings_ext)) - || (!IGD_DC_CLONE(dc) && !IGD_DC_EXTENDED(dc))){ - /* Workaround is specific for SDVO display - * Dont tuned if it isnt B0 silicon - * Dont tuned if it is already tuned - * Dont tuned if bypass is turned on (debug) - * No tuning for VGA modes - * Stop Tuning if above limit LIMIT_TOTAL_CHECK_DISPLAY - */ - if(pt != IGD_PORT_SDVO || - (MODE_IS_VGA(pTimings_ext))){ - EMGD_DEBUG("Unsupported tuning"); - }else if((wa->counter > LIMIT_TOTAL_CHECK_DISPLAY) && - !(pTimings->reserved_dd & TNC_HTOTAL_TUNED)){ - pTimings->reserved_dd = 0; - EMGD_ERROR("Unable to get tuned value!"); - } - - if(FLAG(flag_turn_off_port_wa)){ - /* Turn on SDVO source */ - temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG); - temp |= BIT13; - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp); - } - - if(fb_info_tmp.width){ - /* Free up the temporary frame buffer */ - display->context->dispatch.gmm_free(fb_info_tmp.fb_base_offset); - OS_MEMSET(&fb_info_tmp,0,sizeof (igd_framebuffer_info_t)); - } - OS_MEMSET(wa, 0, sizeof(tnc_wa_timing_t)); - EMGD_TRACE_EXIT; - return TRUE; - } - - /* Increment checking counter */ - wa->counter++; - - /* CRC starting value */ - blue_crc.pixel = 0x007FFFFF; - green_crc.pixel = 0x007FFFFF; - red_crc.pixel = 0x007FFFFF; - - if(FLAG(flag_turn_off_port_wa)){ - /* Turn of port source. - * */ - temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG); - temp &= ~BIT13; - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp); - } - - /* Allocate temporary 32 bpp frame buffer for CRC calculation. - * SV only provided codes for 32bpp CRC calculation so we would - * only calculate CRC for 32bpp. Once CRC is calculated EMGD - * would revert back to original plane. A temporary place is also - * neede so no corruption is seen on lvds for clone display - */ - if(fb_info_tmp.width != (unsigned short)pTimings_tmp.width && - fb_info_tmp.height != (unsigned short)pTimings_tmp.height){ - if(fb_info_tmp.width){ - EMGD_ERROR("Memory leak! Previous framebuffer is not freed!"); - } - fb_info_tmp.width = pTimings_tmp.width; - fb_info_tmp.height = pTimings_tmp.height; - fb_info_tmp.screen_pitch = fb_info->screen_pitch; - fb_info_tmp.fb_base_offset = 0; - fb_info_tmp.pixel_format = IGD_PF_xRGB32; - fb_info_tmp.flags = IGD_SURFACE_DISPLAY | IGD_SURFACE_RENDER; - - ret_val = display->context->dispatch.gmm_alloc_surface( - &fb_info_tmp.fb_base_offset, - fb_info_tmp.pixel_format, - &fb_info_tmp.width, - &fb_info_tmp.height, - &fb_info_tmp.screen_pitch, - &size, - IGD_GMM_ALLOC_TYPE_NORMAL, - &fb_info_tmp.flags); - } - /* Temp plane is always 32 bpp */ - temp_control = EMGD_READ32(MMIO(display) - + PLANE(display)->plane_reg); - plane_control = temp_control; - plane_control &= ~(BIT30 | BIT29 | BIT28 | BIT27); - plane_control |= BIT28 | BIT27; - EMGD_WRITE32(plane_control, MMIO(display) - + PLANE(display)->plane_reg); - temp_pitch = EMGD_READ32(MMIO(display) - + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET); - EMGD_WRITE32(fb_info_tmp.screen_pitch, MMIO(display) - + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET); - temp_plane = EMGD_READ32(MMIO(display) - + PLANE(display)->plane_reg + DSP_START_OFFSET); - EMGD_WRITE32(fb_info_tmp.fb_base_offset, - MMIO(display) + PLANE(display)->plane_reg + DSP_START_OFFSET); - /* Setup front buffer */ - OS_MEMSET(&front_buffer,0,sizeof (igd_surface_t)); - front_buffer.width = fb_info_tmp.width; - front_buffer.height = fb_info_tmp.height; - front_buffer.pitch = fb_info_tmp.screen_pitch; - front_buffer.offset = fb_info_tmp.fb_base_offset; - front_buffer.pixel_format = fb_info_tmp.pixel_format; - front_buffer.flags = fb_info_tmp.flags; - /* Draw 2 color bars for CRC calculation. This is simple and sufficient - * to detect clipping. Will consider complicated color bar if an issue - * is found for now go for quickest methodColor bar. Red and Blue */ - dst_rect.x1 = dst_rect.y1 = 0; - dst_rect.x2 = fb_info_tmp.width/2; - dst_rect.y2 = fb_info_tmp.height; - - /* - // NOT supported in koheo, using software for now - display->context->dispatch.color_blt((igd_display_h)display, - IGD_PRIORITY_NORMAL, - &front_buffer, - &dst_rect, - IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL, - 0x00FF0000, - 0xF0, - (igd_appcontext_h)0, IGD_RENDER_BLOCK); - */ - - { - unsigned long row, col; - unsigned char *buf = NULL; - unsigned long height = fb_info_tmp.height; - unsigned long width = fb_info_tmp.width/2; - unsigned long pitch = fb_info_tmp.screen_pitch; - - buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset); - for (row = 0; row < (height); row++) { - for (col = 0; col < (width); col++) { - EMGD_WRITE32(0x00FF0000, (buf + (col*4))); - } - buf = buf + pitch; - } - display->context->dispatch.gmm_unmap(buf); - } - - dst_rect.x1 = fb_info_tmp.width/2; - dst_rect.y1 = 0; - dst_rect.x2 = fb_info_tmp.width; - dst_rect.y2 = fb_info_tmp.height; - - /* - // NOT supported in koheo, using software for now - display->context->dispatch.color_blt((igd_display_h)display, - IGD_PRIORITY_NORMAL, - &front_buffer, - &dst_rect, - IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL, - 0x000000FF, - 0xF0, - (igd_appcontext_h)0, IGD_RENDER_BLOCK); - wa->flag |= TNC_HTOTAL_TUNED; - pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED); - return FALSE; - - display->context->dispatch.sync((igd_display_h)display, IGD_PRIORITY_NORMAL, - &sync, - IGD_SYNC_NONBLOCK); - */ - - { - unsigned long row, col; - unsigned char *buf = NULL; - unsigned long height = fb_info_tmp.height; - unsigned long width = fb_info_tmp.width; - unsigned long pitch = fb_info_tmp.screen_pitch; - - buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset); - for (row = 0; row < (height); row++) { - for (col = fb_info_tmp.width/2; col < (width); col++) { - EMGD_WRITE32(0x000000FF, (buf + (col*4))); - } - buf = buf + pitch; - } - display->context->dispatch.gmm_unmap(buf); - } - - - ret_val = -IGD_ERROR_BUSY; - timeout = OS_SET_ALARM(500); - while (-IGD_ERROR_BUSY == ret_val && (!OS_TEST_ALARM(timeout))){ - ret_val = display->context->dispatch.sync( - (igd_display_h)display, - IGD_PRIORITY_NORMAL, - &sync, - IGD_SYNC_BLOCK); - OS_SCHEDULE(); - if (0 == ret_val) { - break; - } - } - - /* Turn on HW CRC */ - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x80000000); - /* Reset Status Bit */ - temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024); - temp |= 0x00001000; - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024, temp); - temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024); - temp |= 0x00001000; - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024, temp); - - /* Calculate CRC pixel by reading every single pixel. - * Pixel that is more than the timing range is ignore which happens - * during panning. To save time CRC is only calculated once per timing - * change and kept inside a scratch global variable wa. - */ - if(wa->crc_red == 0 || wa->crc_green == 0 || - wa->crc_blue == 0 ){ - unsigned char *fb_adr; - - fb_adr = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset); - - /* Calculate CRC for this timing */ - for(i=0; i<(int)pTimings_tmp.height; i++){ - for(j=0; j<(int)pTimings_tmp.width; j++){ - if(i < (int)fb_info_tmp.height && j < (int)fb_info_tmp.width){ - /* virt_fb_adr not available anymore */ - /* - curr_pixel = (unsigned long*)( - mode_context->context->device_context.virt_fb_adr + - fb_info_tmp.fb_base_offset + j*bps + (i*fb_info_tmp.screen_pitch)); - */ - - curr_pixel = (unsigned long*)(fb_adr + (j*bps) + (i*fb_info_tmp.screen_pitch)); - - if(curr_pixel == NULL){ - EMGD_DEBUG("FB not valid return true for now util FB is allocated"); - return TRUE; - } - - - - /* - blue_val.pixel = (0x0000ff & *curr_pixel) >> 0; - green_val.pixel = (0x00ff00 & *curr_pixel) >> 8; - red_val.pixel = (0xff0000 & *curr_pixel) >> 16; - */ - - blue_val.pixel = (0x0000ff & EMGD_READ32(curr_pixel)) >> 0; - green_val.pixel = (0x00ff00 & EMGD_READ32(curr_pixel)) >> 8; - red_val.pixel = (0xff0000 & EMGD_READ32(curr_pixel)) >> 16; - - }else{ - red_val.pixel = green_val.pixel = blue_val.pixel = 0; - } - - blue_crc = compute_pixel_crc(blue_crc, blue_val); - green_crc = compute_pixel_crc(green_crc, green_val); - red_crc = compute_pixel_crc(red_crc, red_val); - } - } - display->context->dispatch.gmm_unmap(fb_adr); - - /* Save calculated value */ - wa->crc_red = red_crc.pixel; - wa->crc_green = green_crc.pixel; - wa->crc_blue = blue_crc.pixel; - }else{ - /* Reuse CRC value calculated before */ - red_crc.pixel = wa->crc_red; - green_crc.pixel = wa->crc_green; - blue_crc.pixel = wa->crc_blue; - } - - timeout = OS_SET_ALARM(70); - do { - temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024); - if(temp & 0x00002000){ - break; - } - OS_SCHEDULE(); - } while ((!OS_TEST_ALARM(timeout))); - /* Give some time for CRC to be stable */ - OS_SLEEP(500); - /* Read CRC on LNC and OVL */ - tnc_crc_red = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61060); - tnc_crc_green = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61064); - tnc_crc_blue = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61068); - - /* Revert back to original plane */ - EMGD_WRITE32(temp_control, MMIO(display) - + PLANE(display)->plane_reg); - EMGD_WRITE32(temp_pitch, MMIO(display) - + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET); - EMGD_WRITE32(temp_plane, MMIO(display) - + PLANE(display)->plane_reg + DSP_START_OFFSET); - - /* Turn off CRC */ - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x00000000); - /* Compare CRC calculation with Atom E6xx CRC, return false if a mismatch and - * tuning continues. If it matches indicate the flag as tuned and return - * false anyway so pipe programming would program based on the correct - * timing spec. - */ - if((red_crc.pixel != (unsigned int)tnc_crc_red) || - (green_crc.pixel != (unsigned int)tnc_crc_green) || - (blue_crc.pixel != (unsigned int)tnc_crc_blue)){ - - /* Step by step tuning */ - wa->delta = 1; - - /* Calculate the delta value */ - wa->htotal = (wa->htotal + wa->delta); - - EMGD_DEBUG("Counter %d",wa->counter); - EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red); - EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green); - EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue); - EMGD_DEBUG("CRC does not match, tuning...."); - EMGD_TRACE_EXIT; - return FALSE; - } - EMGD_ERROR("Tuned value found."); - EMGD_ERROR("Total tuning required %d",wa->counter); - EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red); - EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green); - EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue); - wa->flag |= TNC_HTOTAL_TUNED; - pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED); - - EMGD_TRACE_EXIT; - /* We are tuned but lets do another sequence since we may have changed - * the blanks to get a valid CRC. This happens on certain modes that has - * weird blanks value like VESA's 640x480@60 - */ - return FALSE; -} -#endif - -/* Setting the CDVO Signal */ -static void cdvo_signal() -{ - // Low - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x00008000); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x0008B400); - - OS_SLEEP(25); - - // High - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x0008B4FF); - OS_SLEEP(25); -} - -/* This is the initialization code for B0 stepping */ -void program_cdvo(igd_display_context_t *display, unsigned long pipe_reg) -{ - /* unsigned long pipe_conf; */ - int i; - - EMGD_TRACE_ENTER; - - //if(READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) != 0x50){ - - //programmable cdvo stall - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x6102c, 0xf); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x40); - - //reset - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50); - - // High - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x000BB4FF); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x06000200); - - /* loop 3 pixels, 6 calls to cdvo_signal() */ - for(i=0;i<6;i++){ - cdvo_signal(); - } - - //reset - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50); - - // High - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x000BB4FF); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x06000200); - - /* loop 3 pixels, 6 calls to cdvo_signal() */ - for(i=0;i<6;i++){ - cdvo_signal(); - } - - //reset - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50); - - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x02000200); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004000); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x02000200); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00000800); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00000000); - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50); - - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004000); - - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160);//enable sdvo - - //WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x70400, 0x4088);//enable sdvo - //} - - EMGD_TRACE_EXIT; -} - -/*! - * - * @param mmio dev2 mmio - * - * @return void - */ -static void disable_vga_tnc (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, SR01, sr01); - - /* Turn on SR01 bit 5 */ - WRITE_VGA(mmio, SR_PORT, SR01, 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); - - } - - EMGD_TRACE_EXIT; -} - -/*! - * - * @param display_handle - * @param palette_entry - * @param palette_color - * - * @return 0 on success - * @return -IGD_INVAL on failure - */ -int igd_set_palette_entry_tnc( - igd_display_h display_handle, - unsigned long palette_entry, - unsigned long palette_color) -{ - /* Return if Pipe is not on */ - if(!((1L<<31) & READ_MMIO_REG_TNC(PORT_TYPE_DH(display_handle), - PIPE(display_handle)->pipe_reg))) { - return -IGD_INVAL; - } - /* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */ - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, - PIPE(display_handle)->palette_reg + palette_entry * 4, - palette_color); - - return 0; -} - -/*! - * - * @param display_handle - * @param palette_entry - * @param palette_color - * - * @return 0 on success - * @return -IGD_INVAL on failure - */ -int igd_get_palette_entry_tnc( - igd_display_h display_handle, - unsigned long palette_entry, - unsigned long *palette_color) -{ - /* Return if Pipe is not on */ - if(!((1L<<31) & READ_MMIO_REG_TNC( - PORT_TYPE_DH(display_handle), - PIPE(display_handle)->pipe_reg))) { - return -IGD_INVAL; - } - /* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */ - *palette_color = 0xffffff & READ_MMIO_REG_TNC( - IGD_PORT_LVDS, - PIPE(display_handle)->palette_reg + palette_entry * 4); - return 0; -} - -/*! - * - * @param mmio - * @param pipe_reg - * - * @return 0 on success - * @return 1 on failure - */ -int wait_for_vblank_tnc(unsigned long pipe_reg) -{ - unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET; - unsigned long tmp; - unsigned long port_type = IGD_PORT_LVDS; - os_alarm_t timeout; - int ret; - unsigned long request_for; - - EMGD_TRACE_ENTER; - - EMGD_DEBUG("Parameter: pipe_reg = %lx", pipe_reg); - - /* If pipe is off then just return */ - if(!((1L<<31) & READ_MMIO_REG_TNC(port_type, 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. VGA plane is on 0:2:0 so no need to use _TNC macros. - */ - if(!(EMGD_READ32(MMIO_TNC(port_type) + 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_TNC(port_type)); - - /* 2. Wait (about 50 msec, 20Hz) & poll for the next VBlank: */ - timeout = OS_SET_ALARM(50); - 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_TNC(port_type)); - - - EMGD_TRACE_EXIT; - return ret; -} /* wait_for_vblank_tnc */ - -/*! - * 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 - */ -int igd_wait_vblank_tnc(igd_display_h display_handle) -{ - - return wait_for_vblank_tnc(PIPE(display_handle)->pipe_reg); - -} - -/*! - * 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 flags Should the stereo be for the frontbuffer or backbuffer? - * - * @return stride - Stride of the display - * @return stereo - Stereo address of the display - */ -int mode_get_stride_stereo_tnc(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; - - EMGD_TRACE_ENTER; - - 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; - } - } - - EMGD_TRACE_EXIT; - return 0; -} - -/* - * Atom E6xx LVDS display: Mode switch sequence - * - * 1. Enable sequence - * - * Program power on delay, power off delay, power cycle delay registers - * Program backlight control register to set appropriate backlight value - * Pipe A must be completely off at this point - * Write PIPEACONF bits[19:18] = 00 - * Write DSPACNTR bit[31] = 1 - * Write DSPASURF = 0x00000000 - * Write DSPACNTR bit[31] = 0 - * Write DSPASURF = 0x00000000 - * Restore PIPEACONF bits[19:18] to original value - * Program DPLL - * Enable DPLL - * Wait for DPLL warm up 10us and check for DPLL lock bit in Pipe A config reg - * (Wait ensures clock is running smoothly before enabling pipe) - * Program pipe timings (Can be done before DPLL programming) - * Enable panel fitter as needed (Can be done before DPLL and/or - * pipe timing programming) - * Enable pipe - * Enable planes (VGA or HiRes) - * Enable ports - * Enable panel power (Can be done before DPLL programming) - * - * 2. Disable sequence - * - * Disable panel backlight - * Disable panel power (for AOAC standby) - * Disable ports - * Disable planes (VGA or hires) - * Disable pipe - * Disable VGA display in 0x71400 bit 31 - * (Disable VGA display done after disable pipe to allow pipe to turn off - * when no vblank is available in native VGA mode) - * Wait for pipe off status - * (Wait ensures planes and pipe have completely turned off prior to - * disabling panelfitter then DPLL) - * Disable panelfitter - * Disable DPLL - * Pipe timings change or change between VGA native or VGA center/upperleft - * or HiRes - * Use complete disable sequence followed by complete enable sequence with - * new mode programmings. - * - * - * Atom E6xx SDVO display: Display Pipe B Enable/Disable sequence: - * - * 1. Enable sequence - * - * Program LNC and LNW DPLL - * Write all planes, port, power control registers on both LNC and LNW - * 1st Enable LNC pipe - * 2nd Enable LNW pipe - * - * 2. Disable Sequence - * - * Disable panel power - * Disable ports - * Disable planes - * 1st Disable LNC pipe - * 2nd Disable TNC_SDVO pipe - * Disable panel fitter - * Disable DPLL - */ - -/*! - * - * @param display Pointer to hardware device instance data - * - * @return void - */ -void program_pipe_vga_tnc( - igd_display_context_t *display) -{ - igd_timing_info_t *timing; - unsigned long vga_control; - unsigned long upscale = 0; - int centering = 1; - - EMGD_TRACE_ENTER; - - /* - * 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. (Napa 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 = EMGD_READ32(MMIO(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_tnc"); - return; - } - - /* 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 || native->vga cases, centering isn't required */ - if ((timing->width == 720 && timing->height == 400) || upscale) { - EMGD_DEBUG("Centering = 0"); - 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); - EMGD_WRITE32(vga_control, MMIO(display) + 0x71400); - - EMGD_TRACE_EXIT; - return; -} - -/*! - * Program Display Plane Values. - * - * @param display Pointer to hardware device instance data - * @param status - * - * @return void - */ -void program_plane_tnc(igd_display_context_t *display, - unsigned long status) -{ - unsigned long stride; - unsigned long stereo; - unsigned long plane_control; - unsigned long other_plane_reg; - igd_timing_info_t *timing; - igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; - unsigned long plane_reg = PLANE(display)->plane_reg; - igd_timing_info_t *pipe_timing; - /* tnc_wa_timing_t *wa = WA_TUNE; */ - - 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_tnc((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; - } - - /* TODO: Bspec: For EagleLake this Trickle Feed must always disable */ - - 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_tnc(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) + plane_reg + DSP_START_OFFSET), - MMIO(display) + plane_reg + DSP_START_OFFSET); - - igd_wait_vblank_tnc((igd_display_h)display); - EMGD_TRACE_EXIT; - 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; - pipe_timing = 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) && CHECK_VGA(pipe_timing)) { - program_plane_vga(display, timing); - EMGD_TRACE_EXIT; - return; - } - - disable_vga_tnc(MMIO(display)); - - /* 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) { - /* For line ONLY doubling, set bit 21 also '1' */ - plane_control |= BIT21; - } - - mode_get_stride_stereo_tnc(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); - } - - if(fb_info->flags & IGD_SURFACE_TILED) { - plane_control |= (BIT10); - } - - /* Set watermark for Atom E6xx */ -#ifndef CONFIG_MICRO - - if (plane_reg == DSPACNTR) { - other_plane_reg = DSPBCNTR; - } else { - other_plane_reg = DSPACNTR; - } - - if (EMGD_READ32(MMIO(display) + other_plane_reg) & 0x80000000) { - EMGD_WRITE32(device_data->dsp_arb, MMIO(display) + DSP_ARB); - } else if (plane_reg == DSPACNTR) { - EMGD_WRITE32(0x00003fff, MMIO(display) + DSP_ARB); - } else { - EMGD_WRITE32(0x00003f80, MMIO(display) + DSP_ARB); - } - - EMGD_WRITE32(device_data->fifo_watermark1, MMIO(display) + FW_1); - EMGD_WRITE32(device_data->fifo_watermark2, MMIO(display) + FW_2); - EMGD_WRITE32(device_data->fifo_watermark3, MMIO(display) + FW_3); - EMGD_WRITE32(device_data->fifo_watermark4, MMIO(display) + FW_4); - EMGD_WRITE32(device_data->fifo_watermark5, MMIO(display) + FW_5); - EMGD_WRITE32(device_data->fifo_watermark6, MMIO(display) + FW_6); - -#else - /* ITP Script is doing this and so go ahead */ - /* The DSP_ARB set fixed the issue with 32bit vesa modes */ - EMGD_WRITE32(0x00001FBF, MMIO(display) + DSP_ARB); - EMGD_WRITE32(0x3F8F0F18, MMIO(display) + FW_1); -#endif - /* FIXME: Not required for TNC. - * The B-Spec states that rendering will be slower if the fences are not - * a power of 2. So for now, always use a power of 2. */ - /* EMGD_WRITE32(0x04000400, MMIO(display) + 0x209c); */ - - 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_WRITE32(plane_control, MMIO(display) + plane_reg); - EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET); - /* Both of these registers are Reserved on Gen4 */ - /*EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);*/ - /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);*/ - EMGD_WRITE32(0, MMIO(display) + plane_reg + DSP_LINEAR_OFFSET); - EMGD_WRITE32(0, MMIO(display) + plane_reg + 0x24); - EMGD_WRITE32(fb_info->visible_offset, - MMIO(display) + plane_reg + DSP_START_OFFSET); - - igd_wait_vblank_tnc((igd_display_h)display); - - EMGD_TRACE_EXIT; -} - -/*! - * PGen4 can check when the pipe is enabled or disabled. - * This function waits for the pipe to be enabled or disabled. - * check_on_off = 0 to wait for the pipe to disable. - * check_on_off = 0x40000000 to wait for the pipe to enable. - * - * @param mmio - * @param pipe_reg - * @param check_on_off - * - * @return void - */ -static void wait_pipe(unsigned long pipe_reg, unsigned long check_on_off) -{ - unsigned long temp; - os_alarm_t timeout; - - EMGD_TRACE_ENTER; - - /* 0:3:0 doesn't wait pipe, only LNC device does. */ - if (pipe_reg == 0x71008) { - return; - } - - /* Wait for Pipe enable/disable, about 50 msec (20Hz). */ - timeout = OS_SET_ALARM(50); - do { - OS_SCHEDULE(); - temp = EMGD_READ32(MMIO_TNC(IGD_PORT_LVDS) + pipe_reg) & 0x40000000; - /* Check for timeout */ - } while ((temp != check_on_off) && (!OS_TEST_ALARM(timeout))); - - if (temp != check_on_off) { - EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable"); - } - - 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 - */ -void program_pipe_tnc(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; - igd_timing_info_t pTimings_tmp; - igd_display_port_t *port; - unsigned long temp; - unsigned long pt = PORT_TYPE(display); - unsigned long dc; - unsigned long calc; - short hactive_tmp, vactive_tmp; - int i; - tnc_wa_timing_t *wa; - /* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */ - - 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 & - READ_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg); - - if((status == FALSE) || - (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) { - /* For SDVO disable both pipe Bs in 0:2:0 and 0:3:0 */ - if (pt == IGD_PORT_SDVO) { - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg, - pipe_conf & (~0x80000000L)); - } - /* Disable pipe */ - WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg, - pipe_conf & (~0x80000000L)); - - /* check when the pipe is disabled. */ - wait_pipe(PIPE(display)->pipe_reg, 0); - - /* Disable DPLL */ - WRITE_MMIO_REG_TNC(pt, PIPE(display)->clock_reg->dpll_control, - READ_MMIO_REG_TNC(pt, - PIPE(display)->clock_reg->dpll_control) & ~0x80000000L); - - EMGD_TRACE_EXIT; - return; - } - - if(pt == IGD_PORT_SDVO){ - /* Disable pipe */ - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg, - pipe_conf & (~0x80000000L)); - - /* check when the pipe is disabled. */ - wait_pipe(PIPE(display)->pipe_reg, 0); - - /* Disable DPLL */ - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->clock_reg->dpll_control, - READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->clock_reg->dpll_control) & ~0x80000000L); - - program_cdvo(display,PIPE(display)->pipe_reg); - } - - port = PORT_OWNER(display); - pTimings = PIPE(display)->timing; - - { - /* Debug messages */ - pd_timing_t *vga_timing = (pd_timing_t *)pTimings->extn_ptr; - EMGD_DEBUG("pTimings %ux%u mode_number = %u mode_info_flags = 0x%lx, dclk = %lu", - pTimings->width, - pTimings->height, - pTimings->mode_number, - pTimings->mode_info_flags, - pTimings->dclk); - if (vga_timing) { - EMGD_DEBUG("ext_timing %ux%u mode_number = %u mode_info_flags= 0x%lx, dclk = %lu", - vga_timing->width, - vga_timing->height, - vga_timing->mode_number, - vga_timing->mode_info_flags, - vga_timing->dclk); - } - } - - /* - * 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) { - EMGD_DEBUG("IGD_MODE_VESA"); - if (pTimings->mode_number <= VGA_MODE_NUM_MAX) { - /* Pipe timings and clocks no longer need to be set since - * the VGA timings will be used. - WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg, - pipe_conf | 0x80000000); */ - - /* Gen4 can check when the pipe is enabled. No longer needed - * since pipe not enabled and VGA timings are used. - wait_pipe(PIPE(display)->pipe_reg, 0x40000000);*/ - - EMGD_DEBUG("pTimings->mode_number <= VGA_MODE_NUM_MAX"); - program_pipe_vga_tnc(display); - EMGD_TRACE_EXIT; - return; - } else { -#ifdef CONFIG_MICRO - set_256_palette( - MMIO_TNC(PORT(display, display->port_number)->port_type)); -#endif - } - } - - /* Program dot clock divisors. */ - program_clock_tnc(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) { - vactive = (unsigned long)pTimings->height*2 - 1; - } else { - /* For Atom E6xx Hardware will automatically divide by 2 to - get the number of line in each field */ - vactive = (unsigned long)pTimings->height - 1; - } - -#ifndef CONFIG_MICRO - /* reset the palette */ - for (i = 0; i < 256; i++) { - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->palette_reg, - ((i<<16) | (i<<8) | i)); - } - - - /* apply color correction */ - 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 Gen4 - * - * For SDVO display: - * Write values into pipe B registers in both 0:2:0 and 0:3:0 - */ - - dc = *(display->context->mod_dispatch.dsp_current_dc); - - wa = WA_TUNE; - - for (i=0; i<2; i++) { - /* Temp variable */ - pTimings_tmp = *pTimings; - hactive_tmp = (short) hactive; - vactive_tmp = (short) vactive; -#ifndef CONFIG_MICRO - /* Clone and Exteded not Supported in VBIOS for TNC - * This work around is only for Atom E6xx B0 - */ - if((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc)) - && pt == IGD_PORT_SDVO && (display->context->device_context.rid == TNC_B0_RID) - && FLAG(flag_basic_htotal_formula_wa)){ - - if(!(pTimings->reserved_dd & TNC_HTOTAL_TUNED)){ - /* Modify blanks so it always begin after active pixel and ends at the - * end. Do not change it if we are already tuned to maintain - * original timing specification - */ - pTimings_tmp.hblank_start = (short) (pTimings->width - 1); - pTimings_tmp.vblank_start = (short) (pTimings->height - 1); - pTimings_tmp.hblank_end = (short) (pTimings->htotal); - pTimings_tmp.vblank_end = (short) (pTimings->vtotal); - } - - if(i==0){ - if(pTimings->reserved_dd == 0 || (wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){ - /* First time tuning */ - calc = (pTimings->htotal * LNC_CLOCK); - calc = (calc / (PIPE(display)->clock_reg->actual_dclk)); - calc *= (pTimings->vtotal -1); - calc /= pTimings->vtotal; - pTimings_tmp.htotal = (short)calc; - pTimings->reserved_dd = wa->htotal = pTimings_tmp.htotal; - EMGD_DEBUG("Delta = %d", wa->htotal); - }else if (pTimings->reserved_dd & TNC_HTOTAL_TUNED){ - pTimings_tmp.htotal = (short)(pTimings->reserved_dd & (~TNC_HTOTAL_TUNED)); - }else{ - if(wa->htotal == 0) - wa->htotal = (short)pTimings->reserved_dd; - pTimings_tmp.htotal = wa->htotal; - } - /* Use vphase formula if available */ - if(vphase){ - pTimings_tmp.vtotal -= (short)vphase; - pTimings_tmp.vsync_start -= (short)vphase; - pTimings_tmp.vsync_end -= (short)vphase; - pTimings_tmp.vblank_end -= (short)vphase; - }else{ - //pTimings_tmp.hblank_start += (short) (pTimings_tmp.htotal - pTimings->htotal); - pTimings_tmp.hblank_end += (short) (pTimings_tmp.htotal - pTimings->htotal); - } - } - } -#endif - - temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp; - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp); - - temp = ((unsigned long) pTimings_tmp.hblank_end << 16) | - (unsigned long)(pTimings_tmp.hblank_start); - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp); - - temp = ((unsigned long)(pTimings->hsync_end) << 16) | - (unsigned long)(pTimings->hsync_start); - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp); - - temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp; - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp); - - temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) | - (unsigned long)(pTimings_tmp.vblank_start); - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp); - - temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) | - (unsigned long)(pTimings_tmp.vsync_start); - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp); - - /* - * 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 { - EMGD_DEBUG("scaled_timings->width [%d], scaled_timings->height [%d]\n", scaled_timings->width, scaled_timings->height); - temp = (unsigned long)scaled_timings->width - 1; - temp = (temp << 16) | - (unsigned long)(scaled_timings->height - 1); - } - } else { - temp = (hactive_tmp << 16) | vactive_tmp; - } - WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp); - - /* Enable pipe */ - pipe_conf |= PIPE_ENABLE; - - /* Put pipe in interlaced mode if requested: - * should only happen for LVDS display if at all. */ - if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) { - pipe_conf |= (INTERLACE_EN); - } else { - pipe_conf &= ~(INTERLACE_EN); - } - -#ifdef CONFIG_MICRO - if (pt == IGD_PORT_SDVO) { - /* - Enable the panel fitter as VGA controller in Lincroft - is a Panel Fitted VGA controller. - LNC only supports panel fitted VGA mode - (upper left VGA mode). You need to enable the panel fitter. - The timing control will be from the pipe timing generator - but not from the VGA timing generator CRTC registers - as in the centering mode. - - */ - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PFIT_CONTROL, 0xA2000000); - } -#endif - - WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf); - - if(pt == IGD_PORT_SDVO){ - /* Disable pipe */ - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg, - pipe_conf & (~0x80000000L)); - - /* check when the pipe is disabled. */ - wait_pipe(PIPE(display)->pipe_reg, 0); - - program_cdvo(display,PIPE(display)->pipe_reg); - } - - WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf); - /* For LVDS port, don't touch dev3 registers stop after 1st iteration */ - if (pt == IGD_PORT_LVDS) { - break; - } - } - -#ifdef CONFIG_MICRO - if (pt == IGD_PORT_SDVO) { - /* - Enable the panel fitter as VGA controller in Lincroft - is a Panel Fitted VGA controller. - LNC only supports panel fitted VGA mode - (upper left VGA mode). You need to enable the panel fitter. - The timing control will be from the pipe timing generator - but not from the VGA timing generator CRTC registers - as in the centering mode. - - */ - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PFIT_CONTROL, 0xA2000000); - } -#endif - - /* Gen4 can check when the pipe is enabled. */ - wait_pipe(PIPE(display)->pipe_reg, 0x40000000); - - /* - * 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_tnc(display); - } else { -#ifdef CONFIG_MICRO - /* - * FIXME: This is not appropriate. This assumes that - * CONFIG_MICRO means "This is vBIOS" and programs - * the palette. vBIOS IAL should probably just set the - * palette itself?? - */ - set_256_palette( - MMIO_TNC(PORT(display, display->port_number)->port_type)); -#endif - } - } - } - - if (pt == IGD_PORT_SDVO) { - /* Enable Chicken Bit */ - /* Setting BIT6 enable Pipe B Palette Write - * to prevent hang during palette write */ - WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x70400, 0x4088 | BIT6); - } - - EMGD_TRACE_EXIT; - return; -} - -/*! - * - * @param context - * - * @return void - */ -void reset_plane_pipe_ports_tnc(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, j; - 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; - - /* Turn off LVDS and SDVO 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) { - if(port->pd_type == PD_DISPLAY_TVOUT) { - tv_port = port; - }else { - port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3); - } - } - - /* 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; - } - } - } - } - if (port->pd_driver) { - temp = READ_MMIO_REG_TNC(port->port_type, port->port_reg); - WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, (temp & ~BIT31)); - } - } - - /* - * Gen4 appears to require that plane B be shut off prior to - * shutting off plane A. The normal get_next_plane returns them - * in order. We need to read the list backwards. - */ - plane = NULL; - while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) { - /* This section only deals with 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)) { - i = 0x71008; /* PIPE B */ - if (temp & BIT31) { - if(plane->plane_reg == DSPACNTR) { - temp = temp & device_data->plane_a_preserve; - i = 0x70008; /* use i as pipe_reg */ - } - EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + plane->plane_reg); - - /* The B-Spec is ambiguous on which register is the trigger. - * Testing has shown the the surface start address is the - * correct trigger to disable the plane. - */ - EMGD_WRITE32(0, EMGD_MMIO(mmio)+plane->plane_reg+DSP_START_OFFSET); - - /* Wait for VBLANK to ensure that the plane is really off */ - wait_for_vblank_tnc(i); - - EMGD_DEBUG("Plane disabled 0x%lx", plane->plane_reg); - } - } 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)) != NULL) { - j = 0; - - /* Is this really required? Just waited for vblank above 2 times */ - wait_for_vblank_tnc(pipe->pipe_reg); - - for (i = 0; i < 2; i++) { - temp = READ_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg); - - if (temp & BIT31) { - /* Do not turn off Pipe B when shutting down */ - if((context->device_context.power_state - == IGD_POWERSTATE_UNDEFINED) && - (pipe->pipe_reg == PIPEB_CONF)){ - continue; - } - WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg, - (temp & device_data->pipe_preserve)); - - /* Gen4 can check when the pipe is disabled. */ - wait_pipe(pipe->pipe_reg, 0); - - /* Disable VGA display */ - disable_vga_tnc(EMGD_MMIO(mmio)); - - } - - /* If current pipe is for sDVO, then iterate for PIPE B in - * both 0:2:0 LNC and 0:3:0 Atom E6xx devices */ - if (pipe->pipe_reg == 0x70008L) { - break; - } - } - /* Disable DPLL: - * LVDS: LNC 0xF014 - * SDVO: Atom E6xx 0x6018 */ - temp = READ_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control); - - if (temp & BIT31) { - WRITE_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control, - temp & ~BIT31); - } - j++; - } - /* 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 */ - -/*! - * Status is currently not used - * - * @param display - * @param port_number - * @param status - * - * @return 0 on success - * @return 1 on failure - */ -int post_program_port_tnc(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; /* temp; */ - /*unsigned long pt = PORT_TYPE(display); */ - - EMGD_TRACE_ENTER; - - port = PORT(display, port_number); - timings = PIPE(display)->timing; - - /* - * The programming found in the common code for all chipsets - * has the device programming sequence as follows: - * Port - * Pipe - * Post Port - * Plane - * On Gen4, if the port is enabled before the pipe, there is a 10% - * chance that the port will not turn on properly. - * Due to compatability requires with other chipsets, this workaround - * fixes this issue - */ - portreg = READ_MMIO_REG_TNC(port->port_type, port->port_reg); - WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg & ~BIT31); - WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg); - - 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_EXIT("PD post_set_mode returned: 0x%x", ret); - } - } - - EMGD_TRACE_EXIT; - return ret; -} - -/*! - * - * @param display - * @param port_number - * @param status - * - * @return 0 on success - * @return -IGD_ERROR_INVAL on failure - */ -int program_port_sdvo_tnc(igd_display_context_t *display, - unsigned short port_number, - unsigned long status) -{ - unsigned long port_control; - unsigned long pd_powerstate = PD_POWER_MODE_D3; - unsigned long preserve = 0; - unsigned long upscale = 0; - igd_timing_info_t local_timing; - igd_timing_info_t *timing; - unsigned long temp; - int ret; - - EMGD_TRACE_ENTER; - - EMGD_DEBUG("Program Port: (%s)", status?"ENABLE":"DISABLE"); - EMGD_DEBUG("pd_flags: 0x%lx", PORT(display, port_number)->pd_flags); - - timing = PIPE(display)->timing; - - port_control = preserve & READ_MMIO_REG_TNC(IGD_PORT_SDVO, - PORT(display, port_number)->port_reg); - - if (status == TRUE) { - if (!(PORT(display, port_number)->pt_info->flags & - IGD_DISPLAY_ENABLE)) { - EMGD_TRACE_EXIT; - return 0; - } - - /* Enable VGA syncs for native vga modes */ - if (PORT(display, port_number)->vga_sync == 1) { - 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); - } - } - - /* Fact that both IGD_ powerstates and PD_ powermodes have - * same definitions */ - pd_powerstate = GET_DISPLAY_POWER_STATE(display, port_number); - - if (pd_powerstate == IGD_POWERSTATE_D0) { - EMGD_DEBUG("Power State: D0"); - /* Upscale */ - 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); - - /* 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; - } - } - - /* BIT31 - Enable - * BIT30 - PIPE B - * BIT29 - Stall - * BIT7 - Border - */ - port_control |= BIT31|BIT30|BIT29|BIT7; - - /* Program cDVO registers: - * Keep default values for - * 7000h - cDVO control register - * 7004h - cDVO slew rate register - * 7008h - cDVO strength register - * 700Ch - cDVO RCOMP update register - * 6102Ch - cDVO stall register = 0xA. - * Note: Though EAS says 6102Ch default value is 6, it is a typo - * in the spec, based on Si DE hw default value is 10 (0xA), - * so no need to program explicitly. This saves few bytes for - * micro. - */ - - /* Enable Current Source */ - temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG); - temp |= 0x2000; - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp); - } - } - - if (pd_powerstate == PD_POWER_MODE_D0) { - ret = PORT(display, port_number)->pd_driver->set_mode( - PORT(display, port_number)->pd_context, &local_timing, 0); - } else { - ret = PORT(display, port_number)->pd_driver->set_power( - PORT(display, port_number)->pd_context, pd_powerstate); - } - - if (ret) { - EMGD_ERROR_EXIT("PD set_%s returned: 0x%x", - (pd_powerstate == PD_POWER_MODE_D0)?"mode":"power", ret); - return -IGD_ERROR_INVAL; - } - - EMGD_DEBUG("Port_control: 0x%lx", port_control); - - WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, - PORT(display, port_number)->port_reg, port_control); - - EMGD_TRACE_EXIT; - return 0; -} - -/*! - * - * @param display - * @param port_number - * @param status - * - * @return 0 on success - * @return -IGD_ERROR_INVAL on failure - */ -int program_port_lvds_tnc(igd_display_context_t *display, - unsigned short port_number, - unsigned long status) -{ - int ret = 0; - unsigned long powerstate = PD_POWER_MODE_D3; - pd_timing_t *timing; - - EMGD_TRACE_ENTER; - - EMGD_DEBUG("Program LVDS: (%s)", status?"ENABLE":"DISABLE"); - - if (status == TRUE) { - if(!(PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) { - EMGD_TRACE_EXIT; - return 0; - } - - powerstate = GET_DISPLAY_POWER_STATE(display,port_number); - if (powerstate == IGD_POWERSTATE_D0) { - EMGD_DEBUG("Power State: D0"); - timing = (pd_timing_t *)PIPE(display)->timing; - /* Reach end timing to get user resolution and pass it to pd */ - 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, - timing, - 1<<PIPE(display)->pipe_num); - } - } - - /* either status == FALSE, or status == TRUE, but powerstate is D1/D2/D3 */ - if (powerstate != IGD_POWERSTATE_D0) { - 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_%s returned: 0x%x", - (powerstate == IGD_POWERSTATE_D0)?"mode":"power", ret); - return -IGD_ERROR_INVAL; - } - - EMGD_TRACE_EXIT; - return ret; -} - - -/*! - * - * @param display - * @param port_number - * @param status - * - * @return program_port_lvds_gen4() - * @return program_port_sdvo_gen4() - * @return -IGD_ERROR_INVAL on failure - */ -int program_port_tnc(igd_display_context_t *display, - unsigned short port_number, - unsigned long status) -{ - EMGD_TRACE_ENTER; - - if (PORT(display, port_number)->port_type == IGD_PORT_LVDS) { - EMGD_TRACE_EXIT; - return program_port_lvds_tnc(display, port_number, status); - } else { - EMGD_TRACE_EXIT; - return program_port_sdvo_tnc(display, port_number, status); - } -} - -/*! - * - * @param gpio - * - * @return size - */ -unsigned long get_gpio_sets_tnc(unsigned long **gpio) -{ - /* To small to trace */ - return 0; -} - -/*! - * - * @param context - * @param in_list - * - * @return void - To small to trace - */ -void filter_modes_tnc(igd_context_t *context, igd_display_port_t *port, - pd_timing_t *in_list) -{ - while (in_list->width != IGD_TIMING_TABLE_END) { - /* TC LVDS: - * supports from 19.75MHz to 79.MHz - * TC SDVO: - * supports from 25 MHz to 160 MHz and progressive only. - */ - if (port->port_type == IGD_PORT_SDVO) { - if (in_list->mode_info_flags & IGD_SCAN_INTERLACE || - in_list->dclk < 25000 || in_list->dclk > 160000) { - in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED; - } - } - /* No clock check is required for LVDS port as LVDS port driver - * already taken care of this. - if (port->port_type == IGD_PORT_LVDS) { - if (in_list->dclk < 19750 || in_list->dclk > 79500) { - in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED; - } - }*/ - in_list++; - if (in_list->width == IGD_TIMING_TABLE_END && in_list->extn_ptr) { - in_list = in_list->extn_ptr; - } - } - return; -} -#ifndef CONFIG_MICRO -int get_timing_tnc(igd_display_context_t *display, pd_timing_t *in_list) -{ - //int ret = TRUE; - igd_timing_info_t *pTimings_ori; - pd_timing_t *timing = NULL; - timing = in_list; - - EMGD_TRACE_ENTER; - pTimings_ori = PIPE(display)->timing; - - if(display->port_number != 2){ - EMGD_DEBUG("Port does not need tuning"); - EMGD_TRACE_EXIT; - return FALSE; - } - - while(timing->width != PD_TIMING_LIST_END) { - - if((timing->width == pTimings_ori->width) && - (timing->height == pTimings_ori->height) && - (timing->refresh == pTimings_ori->refresh)){ - EMGD_DEBUG("Timing found"); - timing->reserved_dd = pTimings_ori->reserved_dd; - timing->mode_info_flags = pTimings_ori->mode_info_flags; - - /* also return the hblank_end so that ioctl can calculate - * the xblank_length. - */ - timing->hblank_end = pTimings_ori->hblank_end; - timing->vblank_end = pTimings_ori->vblank_end; - - - } - /* Go through the table list */ - timing++; - if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) { - timing = timing->extn_ptr; - } - } - - EMGD_TRACE_EXIT; - return TRUE; -} - -int check_port_supported(void *port_tmp) -{ - //igd_display_port_t *port = (igd_display_port_t *)port_tmp; - /* Determine which port driver is supported by Atom E6xx */ -#if 0 //Pendng confirmation from LNC architect - if(pd_driver->type & PD_DISPLAY_TVOUT){ - return 1; - } -#endif - return 0; -} -#endif - -/* Function checks if the incoming user DTD is one of the timings - * in the crt_timing_table that has border. Meaning that the - * h_blank_end is not the same as htotal. - * We only see this issue when reading a user DTD generated for - * harmonic which is derived from crt_timing_table. pi module - * only handles user DTD which does not have borders. - */ -int get_refresh_in_border(pd_timing_t *in_list) -{ - /* return 1 if refresh is obtained */ - - if(in_list->width == 640 && - in_list->height == 480 && - in_list->dclk == 25175 && - in_list->hsync_start == 655 && - in_list->hsync_end == 751 && - in_list->vsync_start == 489 && - in_list->vsync_end == 491){ - in_list->refresh = 60; - in_list->htotal = 799; - in_list->vtotal = 524; - in_list->hblank_start = 646; - in_list->vblank_start = 486; - return 1; - } - - if(in_list->width == 640 && - in_list->height == 480 && - in_list->dclk == 31500 && - in_list->hsync_start == 663 && - in_list->hsync_end == 703 && - in_list->vsync_start == 488 && - in_list->vsync_end == 491){ - - in_list->refresh = 72; - in_list->htotal = 831; - in_list->vtotal = 519; - in_list->hblank_start = 646; - in_list->vblank_start = 486; - return 1; - } - - - return 0; -} - -mode_dispatch_t mode_dispatch_tnc = { - igd_set_palette_entry_tnc, - igd_get_palette_entry_tnc, - igd_wait_vblank_tnc, - program_plane_tnc, - program_pipe_tnc, - program_port_tnc, - post_program_port_tnc, - program_clock_tnc, - reset_plane_pipe_ports_tnc, - get_gpio_sets_tnc, - filter_modes_tnc, - OPT_MICRO_VALUE(check_display_tnc, NULL), - OPT_MICRO_VALUE(get_timing_tnc, NULL), - OPT_MICRO_VALUE(check_port_supported, NULL), - OPT_MICRO_VALUE(get_refresh_in_border, NULL), - OPT_MICRO_VALUE(&mode_full_dispatch_tnc, NULL) -}; - -/* VBIOS does not use the virtual mapped address - * This function will return 0 for VBIOS anyway */ -#ifndef CONFIG_MICRO -unsigned char *get_mmio_tnc(unsigned long port_type) -{ - unsigned char *virt_mmio; - if (port_type == IGD_PORT_LVDS) { - virt_mmio = mode_context->context->device_context.virt_mmadr; - } else if (port_type == IGD_PORT_SDVO) { - virt_mmio = mode_context->context->device_context.virt_mmadr_sdvo; - } else { - /* i2c_bitbash will use the else condition by passing in port_type - * as '0' */ - virt_mmio = mode_context->context->device_context.virt_gpio_bar; - } - return virt_mmio; -} -#endif - -/* Function to read Atom E6xx 0:2:0, 0:3:0 and 0:31:0 mmio registers */ -unsigned long read_mmio_reg_tnc(unsigned long port_type, unsigned long reg) -{ - unsigned long value; -#ifndef CONFIG_MICRO - unsigned char *mmio; -#endif - - /* to avoid updating or having another set of read/write macros for - * vbios, overwrite io_base to properly read from 0:2:0/0:3:0/0:31:0 - * io_base and set it back after reading */ - if (port_type == IGD_PORT_LVDS) { - io_base = io_base_lvds; - } else if (port_type == IGD_PORT_SDVO) { - io_base = io_base_sdvo; - } else if (port_type == IGD_PORT_LPC) { - io_base = io_base_lpc; - } - OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type)); - if (port_type == IGD_PORT_LPC) { - value = EMGD_READ_PORT32(io_base_lpc + reg); - } else { - value = EMGD_READ32(EMGD_MMIO(mmio) + reg); - } - - io_base = io_base_lvds; - return value; -} - -/* Function to write Atom E6xx 0:2:0 and 0:3:0 mmio registers */ -void write_mmio_reg_tnc(unsigned long port_type, unsigned long reg, - unsigned long value) -{ -#ifndef CONFIG_MICRO - unsigned char *mmio; -#endif - - /* to avoid updating or having another set of read/write macros for - * vbios, overwrite io_base to properly read from 0:2:0/0:3:0 io_base - * and set it back after writing */ - if (port_type == IGD_PORT_LVDS) { - io_base = io_base_lvds; - } else if (port_type == IGD_PORT_SDVO) { - io_base = io_base_sdvo; - } else if (port_type == IGD_PORT_LPC) { - io_base = io_base_lpc; - } - - OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type)); - if (port_type == IGD_PORT_LPC) { - EMGD_WRITE_PORT32(io_base_lpc + reg, value); - } else { - EMGD_WRITE32(value, EMGD_MMIO(mmio) + reg); - } - io_base = io_base_lvds; - return; -} - -#endif |