aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c')
-rw-r--r--drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c2198
1 files changed, 0 insertions, 2198 deletions
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
deleted file mode 100644
index 9d1c6f8f96af..000000000000
--- a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
+++ /dev/null
@@ -1,2198 +0,0 @@
-/* -*- pse-c -*-
- *-----------------------------------------------------------------------------
- * Filename: igd_mode.c
- * $Revision: 1.23 $
- *-----------------------------------------------------------------------------
- * 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:
- * Contains client interface support functions for display allocations
- *-----------------------------------------------------------------------------
- */
-
-#define MODULE_NAME hal.mode
-
-#include <config.h>
-#include <io.h>
-#include <memory.h>
-#include <sched.h>
-#include <gart.h>
-
-#include <igd.h>
-#include <igd_init.h>
-#include <igd_mode.h>
-#include <igd_render.h>
-#include <igd_pwr.h>
-#include <igd_errno.h>
-#include <igd_gmm.h>
-#include <igd_pd.h>
-
-#include <debug.h>
-#include <math_fix.h>
-#include <context.h>
-#include <rb.h>
-#include <pd.h>
-#include <intelpci.h>
-#include <dsp.h>
-#include <pi.h>
-#include <dispatch.h>
-#include <mode.h>
-#include <mode_access.h>
-#include <dsp.h>
-#include <utils.h>
-#include <general.h>
-
-#include "match.h"
-#include "mode_dispatch.h"
-
-/*!
- * @addtogroup display_group
- * @{
- */
-
-#define CURSOR_1_STATE 0x01
-#define CURSOR_2_STATE 0x02
-#define CURSOR_STATE(display) \
- ((display == &display_list[0]) ? CURSOR_1_STATE : CURSOR_2_STATE)
-
-/*!
- * This function is an exported utility function.
- * Its meant for calculating backbuffer to frontbuffer coordinates when in
- * rotation, render-scaling and / or flipping (in any combination).
- *
- * Eventually, this function will be only for HAL usage.
- *
- * @param rotation
- * @param do_flip
- * @param do_rscale
- * @param x_rnd_scale
- * @param y_rnd_scale
- * @param front_width
- * @param front_height
- * @param x
- * @param y
- * @param hotx
- * @param hoty
- *
- * @return void
- */
-void igd_fb_to_screen(unsigned short rotation,
- unsigned char do_flip, unsigned char do_rscale,
- unsigned long x_rnd_scale, unsigned long y_rnd_scale,
- unsigned short front_width, unsigned short front_height,
- unsigned short *x, unsigned short *y,
- unsigned short hotx, unsigned short hoty);
-
-/* Do not malloc the context */
-extern mode_context_t mode_context[];
-
-/* This symbol has to be in this file as it is part of
- * driver ONLY.
- */
-static fw_info_t global_fw_info;
-
-/*!
- * This function sets the per-port attribute to the values given in
- * the parameter. If the requested port is the PIPE master, then
- * this function will proceed to program the palette.
- *
- * @param display used to program palette, if necessary
- * @param attr_to_set contains the new color attribute to set
- *
- * @return 0 on success
- * @return -IGD_INVAL on failure
- */
-int set_color_correct(igd_display_context_t *display,
- const igd_range_attr_t *attr_to_set)
-{
- igd_display_port_t *port;
- igd_attr_t *hal_attr_list;
- mode_dispatch_t *dispatch = mode_context->dispatch;
- igd_range_attr_t *attr = NULL;
- unsigned int i = 0;
-
- EMGD_TRACE_ENTER;
-
- port = PORT_OWNER(display);
- hal_attr_list = port->attributes;
-
-
- /* update the HAL's own copy of attributes */
- while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
- if (attr_to_set->id == hal_attr_list[i].id) {
- attr = (igd_range_attr_t *) &hal_attr_list[i];
-
- /* make sure the value is within range */
- attr->current_value = OS_MAX(attr_to_set->current_value,
- attr->min);
-
- attr->current_value = OS_MIN(attr_to_set->current_value,
- attr->max);
-
- break;
- }
-
- i++;
- }
-
- /* if we didn't find anything, then quit with an error */
- if (PD_ATTR_LIST_END == hal_attr_list[i].id) {
- return -IGD_ERROR_INVAL;
- }
-
- /* If the current display is not the pipe master, then we're done */
- if (PIPE(display)->owner != display) {
- return 0;
- }
-
- /* Program palette */
- dispatch = mode_context->dispatch;
- dispatch->full->set_color_correct(display);
-
- EMGD_TRACE_EXIT;
- return 0;
-}
-
-/*!
- * This function is used to put the mode module into the
- * requested powerstate.
- *
- * @param context SS level igd_context
- * @param powerstate IGD_POWERSTATE_D*
- *
- * @return 0 on success
- * @return >0 on failure
- */
-int mode_pwr(igd_context_t *context,
- unsigned long powerstate)
-{
- igd_display_context_t *display_list[2];
- igd_display_context_t *display = NULL;
- int i,j;
-
- EMGD_TRACE_ENTER;
-
- context->mod_dispatch.dsp_get_dc(NULL, &display_list[0],
- &display_list[1]);
-
- for(j = 0; j < 2; j++) {
- display = display_list[j];
- /* if there is no display or display not allocated, continue */
- if(!display || !display->allocated) {
- continue;
- }
-
- switch(powerstate) {
- case IGD_POWERSTATE_D0:
- if (!PIPE(display)->timing) {
- /* if there is no pipe timing, cannot enable, continue */
- EMGD_DEBUG("No pipe timing for port = %lu", display->port_number);
- continue;
- }
- /* Enable command queues */
- if(context->mod_dispatch.cmd_control) {
- for (i = 0; i < IGD_MAX_PIPE_QUEUES; i++) {
- if (PIPE(display)->queue[i]) {
- EMGD_DEBUG("Enabling command queue [%d]", i);
- context->mod_dispatch.cmd_control(
- PIPE(display)->queue[i], CMD_CONTROL_ON);
- }
- }
- }
-
- /* Set port power state */
- for (i = 0; i < IGD_MAX_PORTS; i++) {
- if (display->port[i] &&
- (((igd_display_port_t *)display->port[i])->pt_info->flags &
- IGD_DISPLAY_ENABLE)) {
- mode_context->dispatch->program_port(display, i+1, TRUE);
- }
- }
- mode_context->dispatch->program_pipe(display, TRUE);
- mode_context->dispatch->program_plane(display, TRUE);
- for (i = 0; i < IGD_MAX_PORTS; i++) {
- if (display->port[i] &&
- (((igd_display_port_t *)display->port[i])->pt_info->flags &
- IGD_DISPLAY_ENABLE)) {
- mode_context->dispatch->post_program_port(display, i+1, 0);
- }
- }
- break;
- case IGD_POWERSTATE_D1:
- case IGD_POWERSTATE_D2:
- case IGD_POWERSTATE_D3:
- /* Set port power state */
- for (i = 0; i < IGD_MAX_PORTS; i++) {
- if (display->port[i] &&
- (((igd_display_port_t *)display->port[i])->pt_info->flags &
- IGD_DISPLAY_ENABLE)) {
- mode_context->dispatch->program_port(display, i+1, TRUE);
- }
- }
- mode_context->dispatch->program_plane(display, TRUE);
- mode_context->dispatch->program_pipe(display, TRUE);
-
- /* Disable command queues */
- if(context->mod_dispatch.cmd_control) {
- for (i = 0; i < IGD_MAX_PIPE_QUEUES; i++) {
- if (PIPE(display)->queue[i]) {
- EMGD_DEBUG("Disabling command queue [%d]", i);
- context->mod_dispatch.cmd_control(
- PIPE(display)->queue[i], CMD_CONTROL_OFF);
- }
- }
- }
- break;
- default:
- break;
- }
- }
-
- EMGD_TRACE_EXIT;
- return 0;
-} /* end mode_pwr() */
-
-/*!
- * This function is used to save mode module register state.
- *
- * @param context SS level igd_context
- * @param state pointer to module_state handle, where module_state_h is
- * pointer to actual state
- *@param flags should have IGD_REG_SAVE_MODE bit set for save
- *
- * @return 0 on success
- * @return -IGD_INVAL on failure
- */
-static int mode_save(igd_context_t *context, module_state_h *state,
- unsigned long *flags)
-{
- mode_state_t *mstate;
- int i, ret;
- igd_display_port_t *port = NULL;
- inter_module_dispatch_t *md;
-
- EMGD_TRACE_ENTER;
-
- if (!state || !(*flags & IGD_REG_SAVE_MODE)) {
- EMGD_ERROR_EXIT("NULL pointer to save mode state or"
- " flags don't have IGD_REG_SAVE_MODE bit set.");
- return -IGD_ERROR_INVAL;
- }
-
- /* First allocate memory for mode state which includes pd states */
- mstate = OS_ALLOC(sizeof(mode_state_t));
- if (!mstate) {
- EMGD_ERROR_EXIT("memory allocation failed.");
- return -IGD_ERROR_NOMEM;
- }
- OS_MEMSET(mstate, 0, sizeof(mode_state_t));
-
- md = &context->mod_dispatch;
-
- /* Call pd_save */
- port = NULL;
- i = 0;
- while ((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
- if (port->pd_driver) {
- EMGD_DEBUG("saving %s", port->pd_driver->name);
- ret = port->pd_driver->pd_save(port->pd_context,
- &(mstate->pd_state[i].state), 0);
- if (ret) {
- EMGD_DEBUG("pd_save failed for %s", port->pd_driver->name);
- }
-
- mstate->pd_state[i].port = port;
- i++;
- }
- }
-
- /* Update mode state */
- *state = (module_state_h) mstate;
-
- EMGD_DEBUG("mode_save: saved %d port driver states.", i);
-
- EMGD_TRACE_EXIT;
- return 0;
-} /* end mode_save() */
-
-/*!
- * This function is used to save mode module register state.
- *
- * @param context SS level igd_context
- * @param state pointer to module_state handle, where module_state_h is
- * pointer to actual state
- * *@param flags should have IGD_REG_SAVE_MODE bit set for restore
- *
- * @return 0 on success
- * @return -IGD_INVAL on failure
- */
-int mode_restore(igd_context_t *context, module_state_h *state,
- unsigned long *flags)
-{
- int i, ret;
- igd_display_port_t *port = NULL;
- mode_state_t *mstate;
-
- EMGD_TRACE_ENTER;
-
- if (!state || !(*flags & IGD_REG_SAVE_MODE)) {
- EMGD_ERROR_EXIT("Null mode state.or trying to restore without a save");
- return 0;
- }
-
- mstate = (mode_state_t *)(*state);
-
- if (!mstate) {
- EMGD_DEBUG("mode_restore: mstate = NULL");
- EMGD_TRACE_EXIT;
- return 0;
- }
-
- /* Restore all PD drivers */
- i = 0;
- while (mstate->pd_state[i].port) {
- port = mstate->pd_state[i].port;
-
- EMGD_DEBUG("restoring %s", port->pd_driver->name);
- ret = port->pd_driver->pd_restore(port->pd_context,
- mstate->pd_state[i].state, 0);
- if (ret) {
- /* What can be done if restore fails */
- EMGD_DEBUG("pd_restore failed for %s", port->pd_driver->name);
- }
-
- i++;
- }
-
- /* Free the memory allocated */
- OS_FREE(mstate);
- *state = NULL;
-
- EMGD_TRACE_EXIT;
- return 0;
-} /* end mode_restore() */
-
-/*!
- *
- * @param cursor
- * @param image
- * @param rotate
- * @param flip
- * @param width
- * @param height
- *
- * @return void
- */
-static void load_argb_cursor_image(unsigned long *cursor,
- unsigned long *image,
- int rotate, int flip,
- int width, int height)
-{
- int w, h, x, y;
- unsigned short nx, ny;
- unsigned long *i;
-
- w = width;
- h = height;
-
- /* make sure size is constrained to 64x64 */
- if (w > 64) {
- w = 64;
- }
- if (h > 64) {
- h = 64;
- }
-
- /* Copy image */
- for (y = 0; y < h; y++) {
- i = image;
- image += width;
- for (x = 0; x < w; x++) {
- /* rotate, flip x,y here. No scaling! */
- nx = (unsigned short) x;
- ny = (unsigned short) y;
- igd_fb_to_screen((unsigned short) rotate, (unsigned char) flip,
- 0, 0, 0, 64, 64, &nx, &ny, 0, 0);
- cursor[nx + (64 * ny)] = *i++;
- }
- }
-}
-
-/*!
- *
- * @param cursor
- * @param image
- * @param rotate
- * @param flip
- * @param width
- * @param height
- *
- * @return void
- */
-static void load_xor_cursor_image(unsigned char *cursor,
- unsigned char *image,
- int rotate, int flip,
- int width, int height)
-{
- int j, x, y;
- int pixel_num, byte_num, line_num;
- int npixel_num, nbyte_num, nline_num, nbit_num;
- unsigned short nx, ny;
- unsigned char b_val, sbit, mask, pixel;
-
- for (j = 0; j < 2; j++) {
- cursor += (j * 8);
- image += (j * 8);
- for (y = 0; y < 64; y++) {
- for (x = 0; x < 64; x++) {
- pixel_num = x + (y * 64);
- line_num = pixel_num / 64;
- byte_num = (pixel_num & 63) / 8;
- b_val = *(image + (16 * line_num) + byte_num);
- pixel = (b_val >> ( 7 - (pixel_num & 7))) & 0x01;
-
- nx = (unsigned short) x;
- ny = (unsigned short) y;
- igd_fb_to_screen((unsigned short) rotate, (unsigned char) flip,
- 0, 0, 0, (unsigned short) width, (unsigned short) height,
- &nx, &ny, 0 , 0);
- npixel_num = nx + (ny * 64);
- nline_num = npixel_num / 64;
- nbyte_num = (npixel_num & 63) / 8;
- nbit_num = 7 - (npixel_num & 7);
- b_val = *(cursor + (16 * nline_num) + nbyte_num);
-
- sbit = pixel << nbit_num;
- mask = 0x01 << nbit_num;
- b_val = (b_val & ~mask) | sbit;
- *(cursor + (16 * nline_num) + nbyte_num) = b_val;
-
- /*(cursor + (16 * line_num) + byte_num) = b_val; */
- }
- }
- }
-}
-
-/*!
- * This function caclulates the correct cursor position from IAL
- * provided coordinates. It takes into account hotspot, rotation, flip,
- * and render_scale.
- *
- * This takes an x and y coordinate and sets the internal cursor
- * info structure with the updated values. In addition, it
- * sets a flag if the coordiantes are outside the displays active
- * area.
- *
- * @param display
- * @param x
- * @param y
- * @param hotx
- * @param hoty
- *
- * @return void
- */
-static void igd_set_cursor_pos(igd_display_context_t *display,
- unsigned short x, unsigned short y,
- unsigned short hotx, unsigned short hoty)
-{
- igd_display_context_t *primary;
- igd_cursor_info_t *internal_ci;
- igd_display_info_t *timing;
- igd_display_plane_t *plane;
- unsigned char render_scale = 0;
- unsigned short rotation, flip;
- unsigned long cursor_state;
-
- if (!display || !PLANE(display) || !PIPE(display) ||
- !PIPE(display)->cursor || !PIPE(display)->cursor->cursor_info ||
- !PORT_OWNER(display) || !PORT_OWNER(display)->pt_info) {
- return;
- }
-
- internal_ci = PIPE(display)->cursor->cursor_info;
- timing = PORT_OWNER(display)->pt_info;
- plane = PLANE(display);
-
- rotation = (unsigned short) ((internal_ci->rotation &
- IGD_RENDER_OP_ROT_MASK) >> 8) * 90;
- flip = (unsigned short) (internal_ci->rotation &
- IGD_RENDER_OP_FLIP) >> 10;
-
- /*
- * Handle rotation, flip and render scale
- * Note that the x,y arguments are unsigned, but cursor cordinates
- * are signed and we need to preserve the signness when saving back
- * into internal_ci structure!
- */
- if ((internal_ci->render_scale_x > 0) ||
- (internal_ci->render_scale_y > 0)) {
- render_scale = 1;
- } else {
- render_scale = 0;
- }
-
- igd_fb_to_screen((unsigned short) rotation, (unsigned char) flip,
- render_scale,
- internal_ci->render_scale_x, internal_ci->render_scale_y,
- (unsigned short) plane->fb_info->width,
- (unsigned short) plane->fb_info->height,
- &x, &y,
- hotx, hoty);
-
- /* Adjust the x and y values relative to the current display offset */
- internal_ci->x_offset = (long)((short)x - (short)timing->x_offset);
- internal_ci->y_offset = (long)((short)y - (short)timing->y_offset);
-
-
- /* Adjust the cursor offset for rotation and flip */
-
- switch (rotation) {
- case 0:
- if (flip) {
- internal_ci->x_offset -= 63;
- }
- break;
- case 90:
- internal_ci->y_offset += 1;
- if (!flip) {
- internal_ci->y_offset -= 63;
- }
- break;
- case 180:
- internal_ci->x_offset += 1;
- internal_ci->y_offset -= 63;
- if (!flip) {
- internal_ci->x_offset -= 63;
- }
- break;
- case 270:
- internal_ci->x_offset -= 63;
- if (flip) {
- internal_ci->y_offset -= 63;
- }
- break;
- default:
- break;
- }
-
- display->context->mod_dispatch.dsp_get_dc(NULL, &primary, NULL);
- if(display == primary) {
- cursor_state = CURSOR_1_STATE;
- } else {
- cursor_state = CURSOR_2_STATE;
- }
-
- /*
- * When panning, the cursor can be positioned off screen. The hardware
- * doesn't like it if this happens. Thus, we set a flag to indicate
- * that the cursor is currently off screen. That way it can be
- * turned off when actually programmed.
- *
- * This also moves the position so that it is at the very edge of the
- * screen, just in case it is turned on.
- */
-
- internal_ci->off_screen &= ~cursor_state;
-
- /* Make sure the cursor is fully displayed */
- if (internal_ci->x_offset < -63) {
- internal_ci->x_offset = -63;
- internal_ci->off_screen |= cursor_state;
- }
- if (internal_ci->x_offset >= (long)timing->width) {
- internal_ci->x_offset = timing->width - 1;
- internal_ci->off_screen |= cursor_state;
- }
- if (internal_ci->y_offset < -63) {
- internal_ci->y_offset = -63;
- internal_ci->off_screen |= cursor_state;
- }
- if (internal_ci->y_offset >= (long)timing->height) {
- internal_ci->y_offset = timing->height - 1;
- internal_ci->off_screen |= cursor_state;
- }
-
- return;
-}
-
-/*!
- * This function sets the cursor_info obtained from igd_alloc_cursor
- * and programs the cursor
- *
- * @param display_handle
- * @param cursor_info
- * @param image
- *
- * @return -IGD_ERROR_INVAL on failure
- * @return 0 on success
- */
-int igd_alter_cursor(igd_display_h display_handle,
- igd_cursor_info_t *cursor_info,
- unsigned char *image)
-{
- igd_display_context_t *display = (igd_display_context_t *) display_handle;
- igd_display_context_t *display2;
- igd_display_context_t *primary;
- igd_cursor_info_t *internal_ci;
- unsigned short rotation, flip;
- unsigned long cursor_state;
- unsigned long cursor_state2;
- unsigned long *cursora = NULL;
- unsigned char *cursorx = NULL;
-
- EMGD_TRACE_ENTER;
-
- EMGD_ASSERT(display, "Null Display Handle", -IGD_ERROR_INVAL);
- EMGD_ASSERT(cursor_info, "Null cursor info", -IGD_ERROR_INVAL);
-
- if(validate_cursor(cursor_info, display)) {
- EMGD_ERROR_EXIT("pixel_format validation failed.");
- return -IGD_ERROR_INVAL;
- }
-
- internal_ci = PIPE(display)->cursor->cursor_info;
-
- cursor_info->argb_offset = internal_ci->argb_offset;
- cursor_info->xor_offset = internal_ci->xor_offset;
-
- rotation = (unsigned short) ((cursor_info->rotation &
- IGD_RENDER_OP_ROT_MASK) >> 8) * 90;
- flip = (unsigned short) (cursor_info->rotation & IGD_RENDER_OP_FLIP) >> 10;
-
- display->context->mod_dispatch.dsp_get_dc(NULL, &primary, NULL);
-
- /* If cursor plane is mirrored, then do the same for the other cursor */
- if (PIPE(display)->cursor->mirror != NULL) {
- if(display == primary) {
- display->context->mod_dispatch.dsp_get_dc(NULL, NULL,
- &display2);
- } else {
- display2 = primary;
- }
- }
-
- /*
- * Loading new cursor (for both primary and clone):
- * 1. Blank cursor image: This can be avoided if new hotspot and
- * new bitmap size are same as existing hotspot and image size.
- * 2. Move cursor to new location accounting for new hotspot
- * 3. Wait for vblank to load the new cursor to avoid flashing/tearing.
- * This impacts performace tests as cursor shape changes several times
- * while running/loading tests and this wait for vblank counts against
- * test times. So going without a wait for vblank. If flashing/tearing
- * becomes a must fix issue, then uncomment below wait_vblank().
- * 4. Load new image
- */
-
- if ((image != NULL) && (cursor_info->flags & IGD_CURSOR_LOAD_ARGB_IMAGE)) {
-#ifdef PRE_KOHEO_CODE
- cursora = (unsigned long *)OS_GART_MAP(0, internal_ci->argb_offset,
- 0, display->context->device_context.virt_fb_adr);
-
- if(!cursora){
- cursora = (unsigned long *)(internal_ci->argb_offset +
- display->context->device_context.virt_fb_adr);
- }
-#else /* PRE_KOHEO_CODE */
- unsigned long buffer_phys = 0;
-
- /* Calculate the cursor's address in kernel-space: */
- if (display->context->dispatch.gmm_virt_to_phys(internal_ci->argb_offset,
- &buffer_phys)) {
- EMGD_ERROR_EXIT("GMM Virtual to Physical Address translation failed");
- return -IGD_ERROR_INVAL;
- }
-
- /*
- * TODO: Verify that phys_to_virt returns a valid address for
- * agp memory
- */
- cursora = phys_to_virt(buffer_phys);
- EMGD_DEBUG("ARGB cursor virtual address is 0x%p", cursora);
- if (cursora == NULL) {
- EMGD_ERROR_EXIT("Physical to Virtual Address translation failed");
- return -IGD_ERROR_INVAL;
- }
-
-#endif /* PRE_KOHEO_CODE */
- /* Clear cursor plane */
- OS_MEMSET(cursora, 0, 64*64*4);
-
- } else if ((image != NULL) &&
- (cursor_info->flags & IGD_CURSOR_LOAD_XOR_IMAGE)) {
-
-#ifdef PRE_KOHEO_CODE
- cursorx = (unsigned char *)(internal_ci->xor_offset +
- display->context->device_context.virt_fb_adr);
-#else /* PRE_KOHEO_CODE */
- unsigned long buffer_phys = 0;
-
- /* Calculate the cursor's address in kernel-space: */
- if (display->context->dispatch.gmm_virt_to_phys(internal_ci->xor_offset,
- &buffer_phys)) {
- EMGD_ERROR_EXIT("GMM Virtual to Physical Address translation failed");
- return -IGD_ERROR_INVAL;
- }
-
- /*
- * TODO: Verify that phys_to_virt returns a valid address for
- * agp memory
- */
- cursorx = phys_to_virt(buffer_phys);
- EMGD_DEBUG("XOR cursor virtual address is 0x%p", cursorx);
- if (cursorx == NULL) {
- EMGD_ERROR_EXIT("Physical to Virtual Address translation failed");
- return -IGD_ERROR_INVAL;
- }
-#endif /* PRE_KOHEO_CODE */
- }
-
- /* calculate the cursor position adjusting to new hotspot */
- igd_set_cursor_pos(display,
- (unsigned short)cursor_info->x_offset,
- (unsigned short)cursor_info->y_offset,
- (unsigned short)cursor_info->hot_x,
- (unsigned short)cursor_info->hot_y);
-
- /* Update internal structure with altered data */
- internal_ci->pixel_format = cursor_info->pixel_format;
- internal_ci->palette[0] = cursor_info->palette[0];
- internal_ci->palette[1] = cursor_info->palette[1];
- internal_ci->palette[2] = cursor_info->palette[2];
- internal_ci->palette[3] = cursor_info->palette[3];
- internal_ci->flags = cursor_info->flags;
- internal_ci->rotation = cursor_info->rotation;
- internal_ci->render_scale_x = cursor_info->render_scale_x;
- internal_ci->render_scale_y = cursor_info->render_scale_y;
-
- if(display == primary) {
- cursor_state = CURSOR_1_STATE;
- cursor_state2 = CURSOR_2_STATE;
- } else {
- cursor_state = CURSOR_2_STATE;
- cursor_state2 = CURSOR_1_STATE;
- }
-
- if ((cursor_info->flags & IGD_CURSOR_ON) &&
- !(internal_ci->off_screen & cursor_state)) {
- mode_context->dispatch->full->program_cursor(display, TRUE);
- } else {
- mode_context->dispatch->full->program_cursor(display, FALSE);
- }
-
- if (PIPE(display)->cursor->mirror) {
- igd_set_cursor_pos(display2,
- (unsigned short)cursor_info->x_offset,
- (unsigned short)cursor_info->y_offset,
- (unsigned short)cursor_info->hot_x,
- (unsigned short)cursor_info->hot_y);
-
- if ((cursor_info->flags & IGD_CURSOR_ON) &&
- !(internal_ci->off_screen & cursor_state2)) {
- mode_context->dispatch->full->program_cursor(display2, TRUE);
- } else {
- mode_context->dispatch->full->program_cursor(display2, FALSE);
- }
- }
-
- /* Pitch may have been altered by program_cursor */
- cursor_info->xor_pitch = internal_ci->xor_pitch;
- cursor_info->argb_pitch = internal_ci->argb_pitch;
-
- /* wait for VBLANK */
- /* mode_context->dispatch->wait_vblank(display); */
-
- if ((image != NULL) &&
- (cursor_info->flags & IGD_CURSOR_LOAD_ARGB_IMAGE)) {
- load_argb_cursor_image(cursora, (unsigned long *)image, rotation, flip,
- cursor_info->width, cursor_info->height);
-
- } else if ((image != NULL) &&
- (cursor_info->flags & IGD_CURSOR_LOAD_XOR_IMAGE)) {
- load_xor_cursor_image(cursorx, image, rotation, flip,
- cursor_info->width, cursor_info->height);
- }
-
- EMGD_TRACE_EXIT;
- return 0;
-}
-
-/*!
- * This function programs the cursor position. It takes into account
- * rotation, flip, and render_scale. It also knows about clone mode
- * and manages the clone cursor automaticlly.
- *
- * @param display_handle
- * @param cursor_info
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_alter_cursor_pos(igd_display_h display_handle,
- igd_cursor_info_t *cursor_info)
-{
- igd_display_context_t *display = (igd_display_context_t *) display_handle;
- igd_display_context_t *display2 = NULL;
- igd_cursor_info_t *internal_ci;
- unsigned long cursor_on_screen;
- unsigned long cursor_state=0;
-
- /* If there is no cursor, return immediately */
- if (!display || !PIPE(display) || !PIPE(display)->cursor) {
- return -IGD_INVAL;
- }
-
- if (PIPE(display)->cursor->mirror != NULL) {
- display->context->mod_dispatch.dsp_get_dc(NULL, NULL, &display2);
- if (display == display2) {
- display->context->mod_dispatch.dsp_get_dc(NULL, &display2, NULL);
- cursor_state = CURSOR_2_STATE;
- } else {
- cursor_state = CURSOR_1_STATE;
- }
- }
-
- /* Reset display2 if cursor isn't setup */
- if (display2) {
- if (!PIPE(display2) || !PIPE(display2)->cursor) {
- display2 = NULL;
- }
- }
-
- while (display) {
- internal_ci = PIPE(display)->cursor->cursor_info;
- cursor_on_screen = (internal_ci->off_screen & cursor_state);
-
- igd_set_cursor_pos(display,
- (unsigned short)cursor_info->x_offset,
- (unsigned short)cursor_info->y_offset,
- (unsigned short)cursor_info->hot_x,
- (unsigned short)cursor_info->hot_y);
-
- if (cursor_on_screen !=
- (internal_ci->off_screen & cursor_state)) {
- /*
- * Cursor has moved either on or off screen since the last
- * call. If it has moved back on screen, turn the cursor
- * back on. If it moved off screen, turn it off.
- */
- if (internal_ci->off_screen & cursor_state) {
- mode_context->dispatch->full->program_cursor(display, FALSE);
-
- } else if (cursor_info->flags & IGD_CURSOR_ON) {
- /*
- * Only program the cursor back on if the IAL already has it
- * ON. This is to prevent the problem where the IAL turned
- * of the cursor on purpose, e.g. a user app turns it off, and
- * then have the HAL turn it back on when moving the cursor
- * from one screen to another.
- */
- mode_context->dispatch->full->program_cursor(display, TRUE);
- }
- }
-
- /* Program cursor position */
- if ((cursor_info->flags & IGD_CURSOR_ON) &&
- !(internal_ci->off_screen & cursor_state)) {
- mode_context->dispatch->full->alter_cursor_pos(
- (igd_display_h)display, internal_ci);
- }
-
- /* Switch to the second display if it is mirrored */
- display = display2;
- display2 = NULL;
- /* Switch the cursor states as well */
- if(cursor_state == CURSOR_1_STATE) {
- cursor_state = CURSOR_2_STATE;
- } else {
- cursor_state = CURSOR_1_STATE;
- }
- }
-
- return 0;
-}
-
-/*!
- * This function returns the current framebuffer and
- * display information.
- *
- * @param hDisplay required. The hDisplay contains the display
- * information to return. This parameter was returned from a
- * previous call to igd_alloc_display().
- * @param port_number
- * @param pFbInfo required and allocated by the caller. The pFbInfo
- * struct is returned to the caller describing the current
- * frame buffer.
- * @param pPtInfo required and allocated by the caller. The
- * pPtInfo struct is returned to caller describing the
- * requested display parameters.
- * @param ulFlags Currently not used
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_get_display(
- igd_display_h hDisplay,
- unsigned short port_number,
- pigd_framebuffer_info_t pFbInfo,
- pigd_display_info_t pPtInfo,
- unsigned long ulFlags)
-{
- igd_display_context_t *display = (igd_display_context_t *)hDisplay;
-
- EMGD_TRACE_ENTER;
-
- /* Check for NULL pointers */
- EMGD_ASSERT(pFbInfo, "Null FB Info", -IGD_ERROR_INVAL);
- EMGD_ASSERT(pPtInfo, "Null PT Info", -IGD_ERROR_INVAL);
-
- /* If the port->pt_info isn't set that means it is called just after
- * igd_alloc_display and before igd_alter_display(). So, just fill
- * port_type into pPtInfo */
- if (PORT(display, port_number)->pt_info == NULL) {
- OS_MEMSET(pPtInfo, 0, sizeof(igd_display_info_t));
- pPtInfo->flags = PORT(display, port_number)->port_type;
- } else {
- OS_MEMCPY(pPtInfo, PORT(display, port_number)->pt_info,
- sizeof(igd_display_info_t));
- }
-
- if (PLANE(display)->fb_info == NULL) {
- OS_MEMSET(pFbInfo, 0, sizeof(igd_framebuffer_info_t));
- } else {
- OS_MEMCPY(pFbInfo, PLANE(display)->fb_info,
- sizeof(igd_framebuffer_info_t));
- }
-
- EMGD_TRACE_EXIT;
- return 0;
-}
-
-/*!
- * This function pans the display on the display device.
- * It takes a x_offset, y_offset into the frame buffer and
- * sets the display from (x_offset, y_offset) to
- * (x_offset+width, y_offset+height).
- * If x_offset+width, y_offset+height crosses frame buffer
- * width and heigth, then it will return error.
- *
- * @param hDisplay pointer to an IGD_DISPLAY pointer returned
- * from a successful call to igd_allocate_display().
- * @param x_offset frame buffer offsets from (0, 0)
- * @param y_offset frame buffer offsets from (0, 0)
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-long igd_pan_display(igd_display_h hDisplay,
- unsigned long x_offset, unsigned long y_offset)
-{
- igd_display_context_t *display = (igd_display_context_t *)hDisplay;
- igd_framebuffer_info_t *fb_info;
- igd_display_info_t *pt_info;
- unsigned long x_old;
-
- EMGD_TRACE_ENTER;
-
- EMGD_ASSERT((display && PORT_OWNER(display) && PORT_OWNER(display)->pt_info),
- "Unvalid Display Handle", -IGD_ERROR_INVAL);
-
- fb_info = PLANE(display)->fb_info;
- pt_info = PORT_OWNER(display)->pt_info;
-
- /* Check paning can be done or not */
- if (!fb_info || !pt_info) {
- EMGD_ERROR_EXIT("Panning cannot be done. fb, pt infos weren't set.");
- return -IGD_ERROR_INVAL;
- }
-
- if (! (PORT_OWNER(display)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
- EMGD_DEBUG("Currently this display is not enabled.");
- EMGD_TRACE_EXIT;
- return -IGD_ERROR_INVAL;
- }
-
- if ((pt_info->width == fb_info->width) &&
- (pt_info->height == fb_info->height)) {
- EMGD_DEBUG("FB and display pt_info are same size, no paning.");
- EMGD_TRACE_EXIT;
- return 0;
- }
-
- /*
- address HSD 200474 (08/27/2008
- handle case primary: 1280x720 seconday:1024x768
- TODO (Chandra idea)
- "ideally the FB 720 height should center on LVDS 768 height and pan across horizontally that is 1280 FB width pans on LVDS 1024 width."
- */
- if (fb_info->height >= pt_info->height) {
- if (pt_info->width + x_offset > fb_info->width ||
- pt_info->height + y_offset > fb_info->height) {
- EMGD_ERROR_EXIT("invalid offsets are passing frame buffer.");
- return -IGD_ERROR_INVAL;
- }
- } else {
- if (pt_info->width + x_offset > fb_info->width ) {
- EMGD_ERROR_EXIT("invalid offsets are passing frame buffer.");
- return -IGD_ERROR_INVAL;
- }
- }
-
- /* Now do the paning.
- * Note: Never change the fb_base_offset (it always points to the
- * first pixel in the frame buffer), nor the visible_offset (it
- * always points to the first pixel of the visible buffer). */
- /* TODO: How to know which fb we are using, frontbuffer/backbuffer? */
-
- x_old = x_offset;
- mode_context->dispatch->full->set_display_base(display, fb_info,
- &x_offset, &y_offset);
-
- /* Save offsets into pt_info */
- pt_info->x_offset = (unsigned short)x_offset;
- pt_info->y_offset = (unsigned short)y_offset;
-
- /* FIXME:
- * This could be negative, and thus conflict with the error codes
- * returned above. However, this is needed for Whitney to compensate
- * for the framebuffer offset alignment requirements and should only
- * be positive.
- */
- EMGD_TRACE_EXIT;
- return (x_offset - x_old);
-
-} /* end igd_pan_display() */
-
-/*!
- * This function get attributes for a port. SS will
- * allocate the memory required to return the *attr_list.
- * This is a live copy of attributes used by both IAL and SS.
- * Don't deallocate this memory. This will be freed by SS.
- *
- * The list returned will contain a list of HAL attributes
- * followed by a pointer to the PD attributes.
- *
- * @param driver_handle pointer to an IGD context pointer returned
- * from a successful call to igd_init().
- * @param port_number port number of port to get pd attributes.
- * @param num_attrs pointer to return the number of attributes
- * returned in attr_list.
- * @param attr_list - pointer to return the attributes.
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_get_attrs(
- igd_driver_h driver_handle,
- unsigned short port_number,
- unsigned long *num_attrs,
- igd_attr_t **attr_list)
-{
- igd_context_t *context = (igd_context_t *)driver_handle;
- igd_display_context_t *display;
- int ret;
- unsigned long hal_attrib_num, pd_attr_num;
- igd_display_port_t *port;
- igd_attr_t *pd_attr_list = NULL;
-
-
- EMGD_TRACE_ENTER;
-
- /* basic parameter check */
- EMGD_ASSERT(driver_handle, "Null Driver Handle", -IGD_ERROR_INVAL);
-
- /* Get the display context that is currently using this port */
- context->mod_dispatch.dsp_get_display(port_number, &display, &port, 0);
-
- if(!display || !port) {
- /*
- * No display is using this port,
- * should we abort at this point?
- */
- EMGD_TRACE_EXIT;
- printk(KERN_ALERT "[EGD] igd_get_attrs exiting: "
- "No display is using port %d.\n", port_number);
- return -IGD_ERROR_INVAL;
- }
-
- /* Get PD attributes */
- pd_attr_num = *num_attrs;
- ret = port->pd_driver->get_attrs( port->pd_context,
- &pd_attr_num,
- &pd_attr_list );
-
- if (ret) {
- pd_attr_num = 0;
- pd_attr_list = NULL;
- }
-
- /* find the extension attribute and attach the pd_attr_list */
- for (hal_attrib_num = 0;
- PD_ATTR_LIST_END != port->attributes[hal_attrib_num].id;
- hal_attrib_num++ ) {
-
- if (PD_ATTR_ID_EXTENSION == port->attributes[hal_attrib_num].id ) {
- ((igd_extension_attr_t *)(&port->attributes[hal_attrib_num]))->extension = pd_attr_list;
- }
- }
-
- /* If attr_list is NULL then the caller is only interested in
- * the number of attributes
- */
- if( NULL != attr_list ) {
- *attr_list = port->attributes;
- }
-
- if (0 == pd_attr_num ) {
- /* if there are no PD attributes, then subtract 1 from hal_attrib_num
- * so that the "extension" attribute is not counted*/
- *num_attrs = hal_attrib_num - 1;
- } else {
- /* subtract 1 because we should not count the "extension" attribute */
- *num_attrs = hal_attrib_num + pd_attr_num - 1;
- }
-
- EMGD_TRACE_EXIT;
- return 0;
-} /* end igd_get_attrs() */
-
-/*!
- * This function set attributes on a port.
- *
- * @param driver_handle pointer to an IGD context pointer returned
- * from a successful call to igd_init().
- * @param port_number port number of port to get pd attributes.
- * @param num_attrs pointer to return the number of attributes
- * returned in attr_list.
- * @param attr_list - pointer to return the attributes.
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_set_attrs(
- igd_driver_h driver_handle,
- unsigned short port_number,
- unsigned long num_attrs,
- igd_attr_t *attr_list)
-{
- igd_context_t *context = (igd_context_t *)driver_handle;
- igd_display_context_t *display;
- igd_display_port_t *port;
- igd_attr_t *attr;
- unsigned int i;
-
- unsigned long num_attrs_set = 0;
- int ret = 0, setmode = 0;
- igd_timing_info_t *pd_timing_table = NULL;
-
- EMGD_TRACE_ENTER;
-
- /* basic parameter check */
- EMGD_ASSERT(driver_handle, "Null Driver Handle", -IGD_ERROR_INVAL);
-
- /* Get the display context that is currently using this port */
- context->mod_dispatch.dsp_get_display(port_number, &display, &port, 0);
- if(!display || !port) {
- /* No display is using this port, should we abort at this point? */
- return -IGD_ERROR_INVAL;
- }
-
- if(num_attrs == 0) {
- return 0;
- }
-
-
- /*
- * Take care of HAL attributes. Here we keep track of the number of
- * attributes set. If the number set is equal to num_attrs, then we
- * don't need to call port driver's set_attr when this loop is done
- */
- for( i = 0; i < num_attrs; i ++ ) {
- switch (attr_list[i].id) {
- case PD_ATTR_ID_FB_GAMMA:
- case PD_ATTR_ID_FB_BRIGHTNESS:
- case PD_ATTR_ID_FB_CONTRAST:
- set_color_correct(display, (igd_range_attr_t *) &attr_list[i]);
- num_attrs_set++;
- break;
-
- default:
- /* ignore all non HAL-related attributes */
- break;
- }
- }
-
- /* Pass the attribute list down to the port driver for futher processing
- * if necessary */
- if (num_attrs > num_attrs_set) {
- ret = port->pd_driver->set_attrs(port->pd_context, num_attrs, attr_list);
-
- if (ret) {
- return -IGD_INVAL;
- }
- }
-
- attr = attr_list;
- i = 0;
- while (i++ < num_attrs) {
- if (attr->flags & PD_ATTR_FLAG_SETMODE) {
- setmode = 1;
- break;
- }
- attr++;
- }
-
- ret = 0;
- if (setmode) {
- /* Update internal timings */
- ret = port->pd_driver->get_timing_list(port->pd_context,
- (pd_timing_t *)port->timing_table,
- (pd_timing_t **)&pd_timing_table);
-
- if (ret) {
- EMGD_ERROR_EXIT("get_timing_list failed.");
- return -IGD_ERROR_INVAL;
- }
-
- port->timing_table = pd_timing_table;
- port->num_timing = get_native_dtd(pd_timing_table,
- PI_SUPPORTED_TIMINGS, &port->fp_native_dtd,
- PD_MODE_DTD_FP_NATIVE);
- ret = IGD_DO_QRY_SETMODE;
- }
-
- EMGD_TRACE_EXIT;
- return ret;
-} /* end igd_set_attrs() */
-
-/*!
- *
- * @param display_h
- * @param width
- * @param height
- *
- * @return -IGD_ERROR_INVAL on failure
- * @return 0 on success
- */
-int mode_getresolution(
- igd_display_h display_h,
- unsigned long *width,
- unsigned long *height)
-{
- igd_display_context_t *display;
- int ret = 0;
-
- if (display_h) {
- display = (igd_display_context_t *) display_h;
-
- if (PORT_OWNER(display)->pt_info) {
- *width = PORT_OWNER(display)->pt_info->width;
- *height = PORT_OWNER(display)->pt_info->height;
- ret = 0;
- }
- else {
- ret = -IGD_ERROR_INVAL;
- }
-
- } else {
- ret = -IGD_ERROR_INVAL;
- }
-
- return ret;
-}
-
-/*!
- *
- * @param driver_handle A igd_driver_h type returned from a previous
- * igd_init call.
- * @param port_number
- * @param port_info Returns the information about port
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_get_port_info(igd_driver_h driver_handle,
- unsigned short port_number,
- igd_port_info_t *port_info)
-{
- igd_context_t *context = (igd_context_t *)driver_handle;
- igd_display_port_t *port;
- pd_port_status_t port_status;
- int ret;
-
- EMGD_TRACE_ENTER;
-
- EMGD_ASSERT(driver_handle, "Invalid Driver Handle", -IGD_ERROR_INVAL);
-
- if(port_number >= (IGD_MAX_PORTS + 1)) {
- EMGD_ERROR("Error, invalid port number. ");
- return -IGD_INVAL;
- }
-
- OS_MEMSET(port_info, 0, sizeof(igd_port_info_t));
-
- context->mod_dispatch.dsp_get_display(port_number, NULL, &port, 0);
-
- if (!port || !port->pd_driver || !port->pd_driver->pd_get_port_status) {
- EMGD_ERROR_EXIT("pd_get_port_status not implemented. ");
- return -IGD_ERROR_INVAL;
- }
-
- pd_strcpy(port_info->pd_name, port->pd_driver->name);
- pd_strcpy(port_info->port_name, port->port_name);
-
- port_info->port_num = port->port_number;
- OS_MEMCPY(&port_info->driver_version, port->pd_driver->version,
- sizeof(pd_version_t));
-
- ret = port->pd_driver->pd_get_port_status(port->pd_context, &port_status);
- if (ret == PD_SUCCESS) {
- if (port_status.connected == PD_DISP_STATUS_DETACHED) {
- /* 0 = Not Connected */
- port_info->connected = 0;
- } else {
- /* PD_DISP_STATUS_ATTACHED, PD_DISP_STATUS_UNKNOWN */
- port_info->connected = 1;
- }
- } else {
- port_info->connected = 1;
- }
-
- port_info->display_type = port_status.display_type;
-
- EMGD_TRACE_EXIT;
- return 0;
-}
-
-/*!
- *
- * @param driver_handle A igd_driver_h type returned from a previous
- * igd_init call.
- * @param i2c_reg
- * @param flags
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int igd_access_i2c(
- igd_driver_h driver_handle,
- igd_i2c_reg_t *i2c_reg,
- unsigned long flags)
-{
- igd_context_t *context = (igd_context_t *)driver_handle;
- unsigned char i;
- unsigned long *gpio, num_gpio;
- int ret = 0;
-
- EMGD_TRACE_ENTER;
-
- if (!driver_handle || !i2c_reg) {
- return -IGD_INVAL;
- }
-
- num_gpio = mode_context->dispatch->get_gpio_sets(&gpio);
-
- if (i2c_reg->bus_id >= num_gpio) {
- EMGD_DEBUG("Invalid bus number specified.");
- return -IGD_ERROR_INVAL;
- }
-
- if ((unsigned long)(i2c_reg->reg + i2c_reg->num_bytes) > 0xFF) {
- EMGD_DEBUG("Invalid number of %d bytes requested from reg 0x%x.",
- i2c_reg->num_bytes, i2c_reg->reg);
- return -IGD_ERROR_INVAL;
- }
-
- if (flags == IGD_I2C_WRITE) {
- pd_reg_t temp_reg[2];
- temp_reg[1].reg = PD_REG_LIST_END;
-
- /* I2C write operation */
- for (i=0; i<i2c_reg->num_bytes; i++) {
- temp_reg[0].reg = i2c_reg->reg + i;
- temp_reg[0].value = i2c_reg->buffer[i];
- ret = context->mod_dispatch.i2c_write_reg_list(
- context,
- gpio[i2c_reg->bus_id],
- i2c_reg->i2c_speed,
- i2c_reg->dab,
- temp_reg,
- 0);
- if (ret) {
- EMGD_DEBUG("i2c write error.");
- break;
- }
- }
- } else if (flags == IGD_I2C_READ) {
- /* I2C read operation */
- ret = context->mod_dispatch.i2c_read_regs(
- context,
- gpio[i2c_reg->bus_id],
- i2c_reg->i2c_speed,
- i2c_reg->dab,
- i2c_reg->reg,
- i2c_reg->buffer,
- i2c_reg->num_bytes);
- if (ret) {
- EMGD_DEBUG("i2c read error.");
- }
- }
-
- EMGD_TRACE_EXIT;
- return ret;
-} /* end igd_access_i2c() */
-
-/*!
- *
- * @param driver_handle A igd_driver_h type returned from a previous
- * igd_init call.
- * @param port_number
- * @param edid_version
- * @param edid_revision
- * @param edid_size
- *
- * @return -IGD_ERROR_INVAL or -IGD_ERROR_EDID on failure
- * @return 0 on success
- */
-/* FIXME: Move to PI */
-static int igd_get_EDID_info(igd_driver_h driver_handle,
- unsigned short port_number,
- unsigned char *edid_version, unsigned char *edid_revision,
- unsigned long *edid_size)
-{
- igd_context_t *context = (igd_context_t *)driver_handle;
- igd_display_port_t *port;
- int ret;
- unsigned char temp_buf[25];
- unsigned char edid_1_3_header[] = {
- 0x00, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x00
- };
-
- EMGD_TRACE_ENTER;
-
- if (!driver_handle || !edid_version || !edid_revision || !edid_size) {
- return -IGD_ERROR_INVAL;
- }
-
- context->mod_dispatch.dsp_get_display(port_number, NULL, &port, 0);
- if(!port) {
- return -IGD_ERROR_INVAL;
- }
-
- /* Read EDID */
- ret = context->mod_dispatch.i2c_read_regs(context,
- port->ddc_reg,
- 10, /* DDC speed 10 KHz */
- port->ddc_dab,
- 0x00, /* DDC Address */
- temp_buf, /* Read 20 bytes into temp_buf */
- 20);
- if (ret) {
- return -IGD_ERROR_EDID;
- }
-
- /* Check for EDID version */
- if (!OS_MEMCMP((void *)temp_buf, (void *)edid_1_3_header, 8)) {
- *edid_version = temp_buf[18];
- *edid_revision = temp_buf[19];
- *edid_size = 128;
-
- /* Read EDID byte 0x7E which gives the number of (optional) 128-byte
- * EDID extension blocks to follow. */
- temp_buf[0] = 0;
- ret = context->mod_dispatch.i2c_read_regs(context,
- port->ddc_reg,
- 10, /* DDC speed 10 KHz */
- port->ddc_dab,
- 0x7E, /* DDC Address */
- &temp_buf[0], /* Read 1 byte into temp_buf */
- 1);
- if (ret) {
- return -IGD_ERROR_EDID;
- }
-
- *edid_size += (temp_buf[0] * 128);
-
- } else {
- *edid_version = temp_buf[0] >> 4;
- if (*edid_version != 2) {
- return -IGD_ERROR_EDID;
- }
-
- *edid_revision = temp_buf[0] & 0x0F;
- *edid_size = 256;
- }
-
- EMGD_TRACE_EXIT;
- return 0;
-} /* end igd_get_EDID_info() */
-
-/*!
- * This function sets enables or disables a specific port. Or, if
- * the port number passed in is zero, it applies the change to all
- * ports associated with the display handle.
- *
- * @param driver_handle display handle.
- * @param port_number port number to enable or disable (or zero).
- * @param flag IGD_ENABLE or IGD_DISABLE
- * @param test IGD_TEST or zero
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-static int igd_enable_port(igd_display_h display_handle,
- unsigned short port_number,
- unsigned long flag,
- unsigned long test)
-{
- igd_display_context_t *display;
- igd_display_port_t *port;
- int i;
- int ret;
-
- EMGD_TRACE_ENTER;
-
- display = (igd_display_context_t *)display_handle;
-
- /*
- * There are a number of things that will probably need to be checked.
- *
- * When enabling a port, make sure the display has pipe timings.
- *
- * When enabling a port and display_detect is on, make sure a display
- * is detected before enabling the port.
- *
- * When enabling a port, check if it must be master, if so, the timings
- * will need to be changed.
- *
- * When disabling a port, don't disable the only port allocated to the
- * display.
- *
- * When disabling a port and it was the master, change timings to next
- * allocated port.
- */
-
- if (!PIPE(display)->timing && (flag & IGD_DISPLAY_ENABLE)) {
- EMGD_ERROR("port enable requested without pipe timings.");
- return -IGD_ERROR_INVAL;
- }
-
- if ((port_number > 0) && (port_number <= IGD_MAX_PORTS)) {
- port = (igd_display_port_t *)display->port[port_number - 1];
- if (port == NULL) {
- return -IGD_ERROR_INVAL;
- }
-
- if (test == IGD_TEST) {
- if ((port->pt_info->flags & IGD_DISPLAY_ENABLE) ==
- (flag & IGD_DISPLAY_ENABLE)) {
- return 0;
- } else {
- return -IGD_ERROR_INVAL;
- }
- }
-
- if (flag & IGD_DISPLAY_ENABLE) {
- /* Can we enable this port? */
- if (dsp_display_connected(display->context, port)) {
- port->pt_info->flags |= IGD_DISPLAY_ENABLE;
- } else {
- return -IGD_ERROR_INVAL;
- }
- } else {
- port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
- }
- } else if ((port_number == 0) && !(flag & IGD_DISPLAY_ENABLE)) {
- /* special case, disable all ports */
- for (i = 0; i < IGD_MAX_PORTS; i++) {
- if (display->port[i]) {
- port = (igd_display_port_t *)display->port[i];
- port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
- }
- }
- }
-
- /* Program ports to the proper enable/disable state */
- for(i = 0; i < IGD_MAX_PORTS; i++) {
- if ((port = (igd_display_port_t *)display->port[i]) != NULL) {
- if (!port_number || (port->port_number == port_number)) {
- if (port->pt_info->flags & IGD_DISPLAY_ENABLE) {
- ret = mode_context->dispatch->program_port(display, i+1,
- TRUE);
- } else {
- ret = mode_context->dispatch->program_port(display, i+1,
- FALSE);
- }
- if (ret != 0) {
- EMGD_ERROR("programming port %d failed", i+1);
- }
- if (port->pt_info->flags & IGD_DISPLAY_ENABLE) {
- /* Call post_program_port if port is getting enabled. */
- ret = mode_context->dispatch->post_program_port
- (display, i+1, 0);
- } else {
- ret = 0;
- }
- if (ret != 0) {
- EMGD_ERROR("post programming port %d failed", i+1);
- }
- }
- }
- }
-
- EMGD_TRACE_EXIT;
-
- return 0;
-}
-
-/*!
- * Free memory allocated to hold timing infomation. This must have been
- * allocated using the igd_query_mode_list.
- *
- * @param mode_list
- *
- * @return void
- */
-void igd_free_mode_list(igd_display_info_t *mode_list)
-{
- if (mode_list) {
- OS_FREE(mode_list);
- }
-}
-
-/*!
- * Generate a mode list that is correct for the given pipe master and
- * any twins.
- *
- * @param driver_handle
- * @param dc
- * @param mode_list
- * @param port
- *
- * @return -IGD_ERROR_INVAL on failure
- * @return 0 on success
- */
-int full_mode_query(igd_driver_h driver_handle,
- unsigned long dc,
- igd_display_info_t **mode_list,
- igd_display_port_t *port)
-{
- igd_timing_info_t *tt;
- igd_timing_info_t *xt;
- int timings = 0;
-
- /* determine the size of the mode list including the extensions */
- tt = port->timing_table;
- if (!tt) {
- EMGD_ERROR("igd_query_mode_list: No Timings");
- return -IGD_ERROR_INVAL;
- }
- while (tt->width != IGD_TIMING_TABLE_END) {
- /*
- * Check here to see if this timing is valid on all other
- * ports. If it is, then we'll add it to the list, otherwise
- * it's skipped.
- */
- if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
- timings++;
- }
- tt++;
-
- /*
- * If reached the first table END, then check for timings
- * added by the user or EDID.
- */
- if ((tt->width == IGD_TIMING_TABLE_END) && tt->extn_ptr) {
- tt = tt->extn_ptr;
- }
- }
- timings++; /* add one for the terminating marker */
-
- *mode_list = OS_ALLOC(sizeof(igd_timing_info_t) * timings);
- if (*mode_list != NULL) {
- /* Now build the new mode list */
- tt = port->timing_table;
- xt = (igd_timing_info_t *)*mode_list;
- while (tt->width != IGD_TIMING_TABLE_END) {
- if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
- OS_MEMCPY(xt, tt, sizeof(igd_timing_info_t));
- xt++;
- }
-
- tt++;
- /*
- * If reached the first table END, then check for timings
- * added by the user or EDID.
- */
- if ((tt->width == IGD_TIMING_TABLE_END) && tt->extn_ptr) {
- tt = tt->extn_ptr;
- }
- }
- /* copy end of list marker */
- OS_MEMCPY(xt, tt, sizeof(igd_timing_info_t));
- } else {
- EMGD_ERROR("igd_query_mode_list: Memory allocation failure.");
- return -IGD_ERROR_INVAL;
- }
- return 0;
-}
-
-/*!
- * This function is used to shutdown any module/dsp
- * module specific structures or tables etc.
- *
- * @param context SS level igd_context.
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-static void mode_shutdown(igd_context_t *context)
-{
- inter_module_dispatch_t *md;
- module_state_h *mode_state = NULL;
- unsigned long *flags = NULL;
-
- EMGD_DEBUG("mode_shutdown Entry");
-
- /*
- * Disable all the displays in decending pipe order
- * Note: This isn't exactly device independent. It works for all
- * multipipe platforms that we know of but is limited to 2 pipes
- * and assumes that it is ok to disable pipe b before a.
- */
-
- dsp_wait_rb(mode_context->context);
-
- /* Disable all VBlank interrupts: */
- context->dispatch.disable_vblank_callback(ALL_PORT_CALLBACKS);
-
- /* Reset all planes, pipe, ports to a known "off" state */
- mode_context->dispatch->reset_plane_pipe_ports(context);
-
- /* Shutdown dsp module */
- context->mod_dispatch.dsp_shutdown(context);
-
- /* Restore mode state */
- md = &context->mod_dispatch;
- md->reg_get_mod_state(REG_MODE_STATE, &mode_state, &flags);
- mode_restore(context, mode_state, flags);
-
- /* Shutdown PI module */
- context->mod_dispatch.pi_shutdown(context);
-
- /*
- * Do not clear mode_context pointer. It needs to stay around until
- * the very last thing.
- *
- * context->mode_context = NULL;
- */
-
- EMGD_DEBUG("Return");
- return;
-} /* end mode_shutdown() */
-
-/*!
- * This function is used to shutdown any module/dsp
- * module specific structures or tables etc.
- *
- * @param context SS level igd_context.
- * @param mode_context mode module initialization parameters
- *
- * @return -IGD_INVAL on failure
- * @return 0 on success
- */
-int full_mode_init(igd_context_t *context,
- mode_context_t *mode_context)
-{
- igd_dispatch_t *dispatch = &context->dispatch;
-
- /* Hook up the IGD dispatch table entires for mode */
- dispatch->get_display = igd_get_display;
- dispatch->pan_display = igd_pan_display;
- dispatch->alter_cursor = igd_alter_cursor;
- dispatch->alter_cursor_pos = igd_alter_cursor_pos;
- dispatch->get_attrs = igd_get_attrs;
- dispatch->set_attrs = igd_set_attrs;
- dispatch->get_port_info = igd_get_port_info;
- dispatch->access_i2c = igd_access_i2c;
- dispatch->get_EDID_info = igd_get_EDID_info;
- dispatch->free_mode_list = igd_free_mode_list;
- dispatch->enable_port = igd_enable_port;
-
- /* Hook up optional inter-module functions */
- context->mod_dispatch.mode_save = mode_save;
- context->mod_dispatch.mode_restore = mode_restore;
- context->mod_dispatch.mode_pwr = mode_pwr;
- context->mod_dispatch.mode_shutdown = mode_shutdown;
- context->mod_dispatch.set_flip_pending =
- mode_context->dispatch->full->set_flip_pending;
- context->mod_dispatch.check_flip_pending =
- mode_context->dispatch->full->check_flip_pending;
- context->mod_dispatch.get_dd_timing =
- mode_context->dispatch->get_dd_timing;
- context->mod_dispatch.check_port_supported =
- mode_context->dispatch->check_port_supported;
- context->mod_dispatch.get_refresh_in_border =
- mode_context->dispatch->get_refresh_in_border;
-
- /* Hook up Core specific IGD dispatch table entries */
- dispatch->set_palette_entry = mode_context->dispatch->set_palette_entry;
- dispatch->get_scanline = mode_context->dispatch->full->get_scanline;
- dispatch->wait_vsync = mode_context->dispatch->full->wait_vsync;
- dispatch->query_in_vblank = mode_context->dispatch->full->query_in_vblank;
- dispatch->get_surface = mode_context->dispatch->full->get_surface;
- dispatch->set_surface = mode_context->dispatch->full->set_surface;
- dispatch->query_event = mode_context->dispatch->full->query_event;
- dispatch->register_vblank_callback =
- mode_context->dispatch->full->register_vblank_callback;
- dispatch->unregister_vblank_callback =
- mode_context->dispatch->full->unregister_vblank_callback;
- dispatch->enable_vblank_callback =
- mode_context->dispatch->full->enable_vblank_callback;
- dispatch->disable_vblank_callback =
- mode_context->dispatch->full->disable_vblank_callback;
-
- /* Assign the fw_info structure and Zero-out the contents */
- mode_context->fw_info = &global_fw_info;
- OS_MEMSET(mode_context->fw_info, 0, sizeof(fw_info_t));
-
- /* Set the mode context quickboot options from the params */
- mode_context->quickboot = context->mod_dispatch.init_params->quickboot;
- mode_context->seamless = context->mod_dispatch.init_params->qb_seamless;
- mode_context->video_input = context->mod_dispatch.init_params->qb_video_input;
- mode_context->splash = context->mod_dispatch.init_params->qb_splash;
-
- /* Just in case, disable all VBlank interrupts: */
- dispatch->disable_vblank_callback(ALL_PORT_CALLBACKS);
-
- return 0;
-} /* end full_mode_init() */
-
-/*!
- * This function clears the framebutffer.
- *
- * @param mode_context mode module initialization parameters
- * @param fb_info
- * @param user_fb - the caller can provide an fb. If they do, then this
- * function will not mem map it. If they provide this parameter as NULL,
- * then we will go ahead and map one here.
- *
- * @return void
- */
-void full_clear_fb(mode_context_t *mode_context,
- igd_framebuffer_info_t *fb_info,
- unsigned char *user_fb)
-{
- unsigned short line, index;
- unsigned char *fb;
-
- if(user_fb) {
- fb = user_fb;
- } else {
- fb = mode_context->context->dispatch.gmm_map(
- fb_info->fb_base_offset);
- EMGD_DEBUG("After gmm_map(), fb = 0x%p", fb);
- }
-
- for (line = 0; line < fb_info->height; line++) {
- for(index = 0; index < fb_info->screen_pitch; index++) {
- OS_MEMSET(fb +
- (unsigned long)line *
- (unsigned long)fb_info->screen_pitch +
- index,
- (mode_context->display_color>>
- ((index%sizeof(unsigned long)) * 8)) &
- 0xFF,
- 1);
- }
- }
-
- if(!user_fb) {
- mode_context->context->dispatch.gmm_unmap(fb);
- }
-}
-
-/*!
- * This is done in an attempt to re-use the plane and cursor allocated
- * to a port when that port is moved to a new display handle. The basic
- * case is when the DC changes in this way:
- *
- * 0x00200058 -> 0x00000021
- * 0x00000021 -> 0x00200058
- *
- * In both these cases, it is better if the plane and cursor are sticky
- * to port 2.
- *
- * @param void
- *
- * @return void
- */
-void swap_fb_cursor( void )
-{
- igd_plane_t *display_plane1, *display_plane2;
- igd_display_pipe_t *pipe1, *pipe2;
- void *tmp;
-
- mode_context->context->mod_dispatch.dsp_get_planes_pipes(
- &display_plane1, &display_plane2,
- &pipe1, &pipe2);
-
- /* Swap the plane info data */
- if (display_plane1 && display_plane2) {
-
- tmp = display_plane1->plane_info;
- display_plane1->plane_info = display_plane2->plane_info;
- display_plane2->plane_info = tmp;
- }
-
- /* Swap the cursor info */
- if (pipe1 && pipe2 && pipe1->cursor && pipe2->cursor) {
-
- tmp = pipe1->cursor->cursor_info;
- pipe1->cursor->cursor_info = pipe2->cursor->cursor_info;
- pipe2->cursor->cursor_info = tmp;
- }
-}
-
-/*!
- * This function calculates target X and Y coordincates
- * for a provided front buffer dimension after including
- * corrections for render-scaling, rotation and flipping.
- *
- * @param rotation 0, 90, 180 or 270
- * @param do_flip 0 or 1
- * @param do_rscale 0 or 1
- * @param x_rnd_scale fixed point int = (native_width << 16) / fb_width
- * @param y_rnd_scale fixed point int = (native_height << 16) / fb_height
- * @param front_width front buffer width for this pipe
- * @param front_height front buffer height for this pipe
- * @param x
- * @param y
- * @param hotx
- * @param hoty
- *
- * @return void
- */
-void igd_fb_to_screen(unsigned short rotation,
- unsigned char do_flip, unsigned char do_rscale,
- unsigned long x_rnd_scale, unsigned long y_rnd_scale,
- unsigned short front_width, unsigned short front_height,
- unsigned short *x, unsigned short *y,
- unsigned short hotx, unsigned short hoty)
-{
- unsigned short x_temp;
- unsigned short y_temp;
-
- /*
- * we only need to up(or down)-scale the coordinates of
- * of the cursor when we are moving the cursor... dont care
- * about scaling the cursor image itself
- */
- if(do_rscale){
- unsigned long phys_x_pos_scale = x_rnd_scale;
- unsigned long phys_y_pos_scale = y_rnd_scale;
-
- if(rotation == 90 || rotation == 270) {
- phys_x_pos_scale = y_rnd_scale;
- phys_y_pos_scale = x_rnd_scale;
- }
-
- /* Added code to fix rounding error */
- if(*x & 0x8000) {
- /* if its a negative x_offset, we need to put in additional
- * type casting so the negative signage doesnt get scaled up
- * and down and end up being a very large positive number
- */
- *x = (unsigned short)(-(short)((((unsigned long )
- ((short)-*x) * phys_x_pos_scale) + ((1<<15)-1)) >> 16));
- } else {
- *x = (unsigned short)((((unsigned long)*x * phys_x_pos_scale) + ((1<<15)-1)) >> 16);
- }
-
- if(*y & 0x8000) {
- /* if its a negative y_offset, we need to put in additional
- * type casting so the negative signage doesnt get scaled up
- * and down and end up being a very large positive number
- */
- *y = (unsigned short)(-(short)((((unsigned long )
- ((short)-*y) * phys_y_pos_scale) + ((1<<15)-1)) >> 16));
- } else {
- *y = (unsigned short)((((unsigned long)*y * phys_y_pos_scale) + ((1<<15)-1)) >> 16);
- }
- }
-
- *x -= hotx;
- *y -= hoty;
-
- x_temp = *x;
- y_temp = *y;
-
- switch(rotation) {
- case 0:
- default:
- if(do_flip) {
- *x = front_width-1 - x_temp;
- }
- break;
- case 90:
- *x = y_temp;
- *y = (front_height - 1) - x_temp;
- if(do_flip) {
- *y = front_height-1 - *y ;
- }
- break;
- case 180:
- /* This is accurate for a 180 rotate */
- *x = (front_width -1) - x_temp;
- *y = (front_height-1) - y_temp;
- if(do_flip) {
- *x = (front_width -1) - *x;
- }
- break;
- case 270:
- *x = (front_width - 1) - y_temp;
- *y= x_temp;
- if(do_flip) {
- *y = (front_height -1) - *y;
- }
- break;
- }
-}
-
-
-
-/*!
- * Compare the incoming dc, timing, fb with the one that
- * the firmware has already programmed and see if seamless
- * is possible.
- *
- * @param dc
- * @param index 0 for primary and 1 for secondary
- * @param pt
- * @param pf
- * @param flags Not used right now
- *
- * @return TRUE if seamless is possible
- * @return FALSE if not possible
- */
-int query_seamless(unsigned long dc,
- int index,
- igd_timing_info_t *pt,
- igd_framebuffer_info_t *pf,
- unsigned long flags)
-{
- int ret = FALSE;
- igd_display_info_t *timing;
- igd_framebuffer_info_t *fb_info;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("Incoming dc = 0x%08lx", dc);
-
- /* Get the fw programmed DC from the inter-module data
- * structure
- */
- mode_context->fw_info->fw_dc =
- mode_context->context->mod_dispatch.dsp_fw_dc;
-
- if(dc != mode_context->fw_info->fw_dc) {
- /* DC doesn't match */
- return FALSE;
- }
-
- /* Note: this test both overcomes a compiler warning, as well as a
- * potential kernel Oops from chasing a NULL pointer:
- */
- if ((pt == NULL) || (pf == NULL)) {
- return FALSE;
- }
- EMGD_DEBUG("Incoming Timing Width = %hu", pt->width);
- EMGD_DEBUG("Incoming Timing height = %hu", pt->height);
- EMGD_DEBUG("Incoming Timing Refresh = %hu", pt->refresh);
-
- /* Check pipe Timings */
- if(pt != NULL) {
- timing = &mode_context->fw_info->timing_arr[index];
- ret = FALSE;
-
- if( (timing->width == pt->width) &&
- (timing->height == pt->height) )
-
- /* Have to build in some tolerance here because the fresh rate may
- * not match exactly */
- if (abs(timing->refresh - pt->refresh) <= 1) {
-
- ret = TRUE;
- }
- }
-
- EMGD_DEBUG(" ");
- EMGD_DEBUG("Firmware Timing Width = %hu", timing->width);
- EMGD_DEBUG("Fimrware Timing Height = %hu", timing->height);
- EMGD_DEBUG("Fimrware Timing Refesh = %hu", timing->refresh);
- EMGD_DEBUG("-------------------------");
-
- if(ret == FALSE) {
- EMGD_DEBUG("Incoming Timings and Firmware Timings Do NOT match!");
- EMGD_DEBUG("Seamless is NOT possible");
- EMGD_TRACE_EXIT;
- return ret;
- }
-
-
- EMGD_DEBUG("Incoming FB Width = %u", pf->width);
- EMGD_DEBUG("Incoming FB Height = %u", pf->height);
- EMGD_DEBUG("Incoming FB Pitch = %u", pf->screen_pitch);
-
- /* Check Plane information */
- if(pf != NULL) {
- fb_info = &mode_context->fw_info->fb_info[index];
- ret = FALSE;
-
- if( (fb_info->screen_pitch != pf->screen_pitch) ||
- (fb_info->width != pf->width) ||
- (fb_info->height != pf->height) ) {
-
- /* If width, height or pitch is different
- * Don't have to turn-off pipe, just update
- * the registers with the new values.
- * Later we just call program_plane to update
- * the registers.
- */
- mode_context->fw_info->program_plane = 1;
- ret = TRUE;
- }
-
- }
-
- EMGD_DEBUG(" ");
- EMGD_DEBUG("Firmware FB Width = %u", fb_info->width);
- EMGD_DEBUG("Firmware FB Height = %u", fb_info->height);
- EMGD_DEBUG("Firmware FB Pitch = %u", fb_info->screen_pitch);
- EMGD_DEBUG("-----------------------");
-
- EMGD_DEBUG("value of ret = %d", ret);
-
- EMGD_TRACE_EXIT;
- return ret;
-} /* end of query_seamless */
-
-/*----------------------------------------------------------------------------
- * File Revision History
- * $Id: igd_mode.c,v 1.23 2010/09/17 23:54:51 syeh2 Exp $
- *----------------------------------------------------------------------------
- */