aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c')
-rw-r--r--drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c2680
1 files changed, 0 insertions, 2680 deletions
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
deleted file mode 100644
index 8c232606404e..000000000000
--- a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
+++ /dev/null
@@ -1,2680 +0,0 @@
-/**********************************************************************
- * 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.
- ******************************************************************************/
-#define MODULE_NAME hal.pvr3dd
-
-#include <linux/spinlock.h>
-
-#include "drm_emgd_private.h"
-
-#include "img_defs.h"
-#include "servicesext.h"
-#include "kerneldisplay.h"
-#include "emgd_dc.h"
-#include "emgd_drm.h"
-
-
-#if !defined(SUPPORT_DRI_DRM)
-#error "SUPPORT_DRI_DRM must be set"
-#endif
-
-
-/* Function to get the PVR services jump table */
-extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *jtable);
-
-#ifdef SUPPORT_FB_EVENTS
-static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo);
-static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo);
-#endif /* SUPPORT_FB_EVENTS */
-static void flush_flip_queue(emgddc_swapchain_t *swap_chain);
-static PVRSRV_ERROR do_mode_change(igd_context_t *context,
- emgddc_devinfo_t *devinfo,
- drm_emgd_private *priv,
- DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib);
-
-
-/* Special value used to register with the PVR services command queue: */
-#define EMGDDC_COMMAND_COUNT 1
-
-
-/**
- * This is a pointer to the global emgddc_devinfo_t structure, used in various
- * parts of this file.
- */
-static emgddc_devinfo_t *global_devinfo[] = {NULL, NULL};
-
-
-/**
- * Pairs of equivalent pixel formats, in EMGD and PVR formats:
- */
-emgddc_pixelformat_translator_t known_pfs[] = {
- /* 1 Byte-per-pixel [A]RGB Pixel Formats: */
- {IGD_PF_ARGB8_INDEXED, PVRSRV_PIXEL_FORMAT_PAL8}, /* IMG numbered */
- {IGD_PF_ARGB4_INDEXED, PVRSRV_PIXEL_FORMAT_PAL4}, /* IMG numbered */
-
- /* 2 Byte-per-pixel [A]RGB Pixel Formats: */
- {IGD_PF_ARGB16_4444, PVRSRV_PIXEL_FORMAT_ARGB4444}, /* IMG# & PVR2D-known */
- {IGD_PF_ARGB16_1555, PVRSRV_PIXEL_FORMAT_ARGB1555}, /* IMG# & PVR2D-known */
- {IGD_PF_RGB16_565, PVRSRV_PIXEL_FORMAT_RGB565}, /* IMG# & PVR2D-known */
- {IGD_PF_xRGB16_555, PVRSRV_PIXEL_FORMAT_RGB555}, /* IMG numbered */
-
- /* 3 Byte-per-pixel [A]RGB Pixel Formats: */
- {IGD_PF_RGB24, PVRSRV_PIXEL_FORMAT_RGB888}, /* IMG numbered */
-
- /* 4 Byte-per-pixel [A]RGB Pixel Formats: */
- {IGD_PF_xRGB32_8888, PVRSRV_PIXEL_FORMAT_XRGB8888}, /* IMG numbered */
- /* a.k.a. IGD_PF_ARGB32_8888 */
- {IGD_PF_ARGB32, PVRSRV_PIXEL_FORMAT_ARGB8888}, /* IMG# & PVR2D-known */
- {IGD_PF_xBGR32_8888, PVRSRV_PIXEL_FORMAT_XBGR8888}, /* IMG numbered */
- {IGD_PF_ABGR32_8888, PVRSRV_PIXEL_FORMAT_ABGR8888}, /* IMG numbered */
-
- /* YUV Packed Pixel Formats: */
- {IGD_PF_YUV422_PACKED_YUY2, PVRSRV_PIXEL_FORMAT_YUY2},
- {IGD_PF_YUV422_PACKED_YVYU, PVRSRV_PIXEL_FORMAT_YVYU},
- {IGD_PF_YUV422_PACKED_UYVY, PVRSRV_PIXEL_FORMAT_UYVY},
- {IGD_PF_YUV422_PACKED_VYUY, PVRSRV_PIXEL_FORMAT_VYUY},
- /* UNKNOWN to IMG
- {IGD_PF_YUV411_PACKED_Y41P, PVRSRV_PIXEL_FORMAT_UNKNOWN},
- */
-
- /* YUV Planar Pixel Formats: */
- /* a.k.a. IGD_PF_YUV420_PLANAR_IYUV */
- {IGD_PF_YUV420_PLANAR_I420, PVRSRV_PIXEL_FORMAT_I420},/* IMG numbered */
- {IGD_PF_YUV420_PLANAR_YV12, PVRSRV_PIXEL_FORMAT_YV12},/* IMG numbered */
- /* UNKNOWN to IMG
- {IGD_PF_YUV410_PLANAR_YVU9, PVRSRV_PIXEL_FORMAT_UNKNOWN},
- */
- {IGD_PF_YUV420_PLANAR_NV12, PVRSRV_PIXEL_FORMAT_NV12},
-};
-unsigned int num_known_pfs =
- sizeof(known_pfs) / sizeof(emgddc_pixelformat_translator_t);
-
-
-/**
- * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
- *
- * @param emgd_pf (IN) EMGD-specific pixel format.
- * @return Translated PVR-specific pixel format.
- */
-static unsigned long pvr2emgd_pf(PVRSRV_PIXEL_FORMAT pvr_pf)
-{
- int i;
- for (i = 0 ; i < num_known_pfs ; i++) {
- if (known_pfs[i].pvr_pf == pvr_pf) {
- return known_pfs[i].emgd_pf;
- }
- }
-
- /* If we get to here, we didn't find a known PVR pixel format: */
- return IGD_PF_UNKNOWN;
-}
-
-
-/**
- * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
- *
- * @param emgd_pf (IN) EMGD-specific pixel format.
- * @return Translated PVR-specific pixel format.
- */
-static PVRSRV_PIXEL_FORMAT emgd2pvr_pf(unsigned long emgd_pf)
-{
- int i;
- for (i = 0 ; i < num_known_pfs ; i++) {
- if (known_pfs[i].emgd_pf == emgd_pf) {
- return known_pfs[i].pvr_pf;
- }
- }
-
- /* If we get to here, we didn't find a known PVR pixel format: */
- return IGD_PF_UNKNOWN;
-}
-
-
-/**
- * Determines if the user-space-provided pointer (to a devinfo) is valid.
- *
- * @param devinfo (IN) The user-space-provided pointer to a devinfo.
- */
-static int is_valid_devinfo(emgddc_devinfo_t *devinfo)
-{
- if ((devinfo == global_devinfo[0]) || (devinfo == global_devinfo[1])) {
- return 1;
- } else {
- return 0;
- }
-} /* is_valid_devinfo() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnOpenDCDevice()
- * function. This function is called when a client wants to use PVR services
- * with the specified device.
- *
- * @param device_id (IN) The device_id associated with this device (i.e.
- * obtained when emgddc_init() called
- * PVRSRV_DC_DISP2SRV_KMJTABLE.pfnPVRSRVRegisterDCDevice()).
- * @param device_h (OUT) The handle for this device (an opaque pointer to
- * devinfo).
- * @param system_buffer_sync_data (IN) Sync data for this device's system
- * buffer.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 device_id,
- IMG_HANDLE *device_h,
- PVRSRV_SYNC_DATA* system_buffer_sync_data)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
-
-
- UNREFERENCED_PARAMETER(device_id);
-
- /* Look up the device (for DIH/Extended mode): */
- if (device_id == global_devinfo[0]->device_id) {
- devinfo = global_devinfo[0];
- EMGD_DEBUG("devinfo = global_devinfo[0] = 0x%p", devinfo);
- } else if (device_id == global_devinfo[1]->device_id) {
- devinfo = global_devinfo[1];
- EMGD_DEBUG("devinfo = global_devinfo[1] = 0x%p", devinfo);
- } else {
- printk(KERN_ERR "[EMGD] OpenDCDevice() called with unknown device ID "
- "%lu\n", device_id);
- return PVRSRV_ERROR_INVALID_DEVICE;
- }
- devinfo->system_buffer.sync_data = system_buffer_sync_data;
- *device_h = (IMG_HANDLE) devinfo;
-
-
- EMGD_TRACE_EXIT;
-
- return PVRSRV_OK;
-} /* OpenDCDevice() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCloseDCDevice()
- * function. This function is called when a client is finished using PVR
- * services with the specified device.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE device_h)
-{
- EMGD_TRACE_STUB;
-
- EMGD_DEBUG("device_h = 0x%p", device_h);
- if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, device_h);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- return PVRSRV_OK;
-} /* CloseDCDevice() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCFormats()
- * function. This function is called when a client wants to determine the
- * pixel format currently being used with, and potentially, to determine which
- * pixel formats can be used with the specified device. The first entry in the
- * array is the current pixel format.
- *
- * Note: this function must be called twice. The first time, the formats
- * parameter is set to NULL, and the client is trying to determine the number
- * of pixel formats. The second time, the formats parameter is non-NULL, and
- * points to enough memory for num_formats-worth of pixel formats. Note: this
- * creates a small window of time between calls where a mode change could
- * occur; the probability is considered so small, as to not be a worry.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param num_formats (OUT) The number of pixel formats for this device.
- * @param format (IN/OUT) An array of the pixel formats for this device (ignore
- * if NULL).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE device_h,
- IMG_UINT32 *num_formats,
- DISPLAY_FORMAT *format)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !num_formats) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- *num_formats = devinfo->num_formats;
-
- if (format) {
- unsigned long i;
-
- for (i = 0 ; i < devinfo->num_formats ; i++) {
- format[i] = devinfo->display_format_list[i];
- }
- }
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* EnumDCFormats() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCDims() function.
- * This function is called when a client wants to determine the current
- * dimensions (similar to an EMGD mode, but just the dimensions) of, and
- * potentially, to determine the possible dimensions that can be used with this
- * device. The first entry in the array is the current dimension.
- *
- * Note: this function must be called twice. The first time, the dims
- * parameter is set to NULL, and the client is trying to determine the number
- * of dimensions. The second time, the dims parameter is non-NULL, and points
- * to enough memory for num_dims-worth of dimensions. Note: this
- * creates a small window of time between calls where a mode change could
- * occur; the probability is considered so small, as to not be a worry.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param format (IN) A pointer to a pixel format (unused).
- * @param num_dims (OUT) The number of dimensions for this device.
- * @param dims (IN/OUT) An array of the dimensions for this device (ignore
- * if NULL).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR EnumDCDims(IMG_HANDLE device_h,
- DISPLAY_FORMAT *format,
- IMG_UINT32 *num_dims,
- DISPLAY_DIMS *dims)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !format || !num_dims) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- *num_dims = devinfo->num_dims;
-
- if (dims) {
- unsigned long i;
-
- for (i = 0 ; i < devinfo->num_dims ; i++) {
- dims[i] = devinfo->display_dim_list[i];
- }
- }
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* EnumDCDims() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCSystemBuffer()
- * function. This function returns a handle to the system buffer
- * (a.k.a. "frame buffer" or "front buffer") of the specified device. The
- * handle is an opaque pointer to the buffer.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param buffer_h (OUT) The handle for this buffer (an opaque pointer to
- * devinfo->system_buffer).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE device_h, IMG_HANDLE *buffer_h)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !buffer_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- *buffer_h = (IMG_HANDLE) &devinfo->system_buffer;
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* GetDCSystemBuffer() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCInfo() function.
- * This function returns a pointer to the DISPLAY_INFO structure associated
- * with this device, which contains the driver's name, and information about
- * swap chains that can be created (i.e. all static information).
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param dc_info (OUT) The DISPLAY_INFO structure associated with this device.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR GetDCInfo(IMG_HANDLE device_h, DISPLAY_INFO *dc_info)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !dc_info) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- *dc_info = devinfo->display_info;
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* GetDCInfo() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBufferAddr()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param buffer_h (IN) The handle of a buffer (an opaque pointer to an
- * emgddc_buffer_t) to return information of.
- * @param phys_addr (OUT) A pointer to an array pointer of page addresses of
- * the buffer. For many devices, this would be a pointer to the physical
- * address of a contiguous set of memory associated with the buffer, but since
- * EMGD doesn't use contiguous memory for a buffer, it returns the array of
- * addresses.
- * @param fb_size (OUT) The size (in bytes) of the buffer.
- * @param virt_addr (OUT) A pointer to the virtual address (in kernel space) of
- * the buffer.
- * @param os_map_info_h (OUT) Ununsed by PVR services.
- * @param is_contiguous (OUT) A pointer to a boolean that is set to IMG_FALSE,
- * because EMGD uses non-contiguous pages of memory for buffers.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE device_h,
- IMG_HANDLE buffer_h,
- IMG_SYS_PHYADDR **phys_addr,
- IMG_UINT32 *fb_size,
- IMG_VOID **virt_addr,
- IMG_HANDLE *os_map_info_h,
- IMG_BOOL *is_contiguous)
-{
- emgddc_devinfo_t *devinfo;
- igd_context_t *context;
- emgddc_buffer_t *system_buffer;
- unsigned long page_count = 0;
- int ret;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- context = devinfo->priv->context;
-
- if (!buffer_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- system_buffer = (emgddc_buffer_t *) buffer_h;
-
- if (!phys_addr) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
- EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
- if ((ret = context->dispatch.gmm_get_page_list(system_buffer->offset,
- (unsigned long **) phys_addr, &page_count)) != 0) {
- printk(KERN_ERR"Cannot get the page addresses for the buffer at offset "
- "0x%08lx\n", system_buffer->offset);
- EMGD_TRACE_EXIT;
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
- EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
- EMGD_DEBUG(" (*phys_addr)->uiAddr = 0x%lx", (*phys_addr)->uiAddr);
-
- if (!fb_size) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- if (fb_size) {
- *fb_size = (IMG_UINT32) system_buffer->size;
- EMGD_DEBUG(" fb_size = 0x%lx", *fb_size);
- }
-
- if (virt_addr) {
- *virt_addr = system_buffer->virt_addr;
- EMGD_DEBUG(" virt_addr = 0x%p", *virt_addr);
- }
-
- /* Note: this value is ignored by the PVR services code: */
- if (os_map_info_h) {
- *os_map_info_h = (IMG_HANDLE)system_buffer->offset;
- EMGD_DEBUG(" os_map_info_h = 0x%p", *os_map_info_h);
- }
-
- /*
- * Other than cursor, memory allocations are not contiguous pages
- */
- if (is_contiguous) {
- *is_contiguous = IMG_FALSE;
- }
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* GetDCBufferAddr() */
-
-
-/**
- * Determines if the user-space-provided pointers (to a devinfo and swap chain)
- * are valid.
- *
- * @param devinfo (IN) The user-space-provided pointer to a devinfo.
- * @param swap_chain (IN) The swap chain to add to the list.
- * @param must_be_flipable (IN) Non-zero if swap_chain must be flip-able.
- * @return non-zero if valid, zero if not.
- */
-static int is_valid_swap_chain(emgddc_devinfo_t *devinfo,
- emgddc_swapchain_t *swap_chain, int must_be_flipable)
-{
- if (!is_valid_devinfo(devinfo)) {
- return 0;
- } else {
- /* Search both lists for this swap chain: */
- emgddc_swapchain_t *swap = devinfo->flipable_swapchains;
- while (swap) {
- if (swap == swap_chain) {
- return 1;
- }
- swap = swap->next;
- }
- if (!must_be_flipable) {
- swap = devinfo->pixmap_swapchains;
- while (swap) {
- if (swap == swap_chain) {
- return 1;
- }
- swap = swap->next;
- }
- }
- }
- /* We didn't find this swap chain pointer, so it's not valid: */
- return 0;
-} /* is_valid_swap_chain() */
-
-
-/**
- * Called by CreateDCSwapChain() to add a new swap chain to one of the lists of
- * swap chains.
- *
- * @param list (IN) A pointer to a list of swap chains.
- * @param swap_chain (IN) The swap chain to add to the list.
- */
-static void add_swap_chain_to_list(emgddc_swapchain_t **list,
- emgddc_swapchain_t *swap_chain)
-{
- /* It's simplest to add to the front of the list: */
- if (*list == NULL) {
- *list = swap_chain;
- } else {
- swap_chain->next = *list;
- *list = swap_chain;
- }
-} /* add_swap_chain_to_list() */
-
-
-/**
- * Called by DestroyDCSwapChain() to remove an about-to-be-deleted swap chain
- * from one of the lists of swap chains.
- *
- * @param list (IN) A pointer to a list of swap chains.
- * @param swap_chain (IN) The swap chain to remove from the list.
- */
-static void remove_swap_chain_from_list(emgddc_swapchain_t **list,
- emgddc_swapchain_t *swap_chain)
-{
- emgddc_swapchain_t *swap, *prev;
-
- swap = *list;
- prev = *list;
- while (swap) {
- if (swap == swap_chain) {
- /* Found match */
- if (swap == *list) {
- *list = swap->next;
- } else {
- prev->next = swap->next;
- }
- break;
- }
- prev = swap;
- swap = swap->next;
- }
-} /* remove_swap_chain_from_list() */
-
-
-/**
- * Called by either CreateDCSwapChain() or DestroyDCSwapChain() to free all GMM
- * and kernel space memory memory of the specified swap chain.
- *
- * @param swap_chain (IN) The swap chain to free.
- * @param context (IN) The EMGD context to use to call gmm_free().
- */
-static void free_swap_chain(emgddc_swapchain_t *swap_chain,
- igd_context_t *context)
-{
- emgddc_buffer_t *buffers;
- int i;
-
- /*
- * Free and unmap the buffers. Must ensure that the HAL is running before
- * calling it, and ensure that we don't free/unmap the first buffer if is
- * actually the frame buffer.
- */
- if (swap_chain->devinfo->priv->hal_running) {
- buffers = swap_chain->buffers;
- for (i = 0 ; i < swap_chain->buffer_count ; i++) {
- if (!buffers[i].is_fb) {
- if (buffers[i].virt_addr) {
- context->dispatch.gmm_unmap(buffers[i].virt_addr);
- }
- if (buffers[i].offset) {
- context->dispatch.gmm_free(buffers[i].offset);
- }
- }
- }
- }
-
- if (swap_chain->flip_queue) {
- OS_FREE(swap_chain->flip_queue);
- }
- OS_FREE(swap_chain->buffers);
- OS_FREE(swap_chain);
-
- EMGD_TRACE_EXIT;
-} /* free_swap_chain() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCreateDCSwapChain()
- * function. This function was originally designed to create a flip-able swap
- * chain on the specified device, but has also been augmented to allow the X
- * driver to create pixmaps or other buffers in GTT memory. A flip-able swap
- * chain consists of a front buffer (the "system buffer, a.k.a. the "frame
- * buffer") and one or more back buffers (therefore, the number of buffers
- * includes the frame buffer).
- *
- * Note: Only full-screen flipping is supported (the hardware is pointed at one
- * complete buffer at a time). There is no support for the
- * SetDC{Src|Dst}Rect() functions to define a smaller region of the display for
- * the buffers/flipping.
- *
- * Note: The DDK documentation says that the mode should be changed if the
- * dimensions and pixel format do not match the current dimensions and pixel
- * format. However, this can only be supported if the X server isn't running
- * (which is in charge of changing modes when it is running). If the X server
- * is running, an error is returned unless the current dimensions and pixel
- * format are specified.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param flags (IN) Unused.
- * @param dst_surf_attrib (IN) While not described in the DDK documentation,
- * this presumably specifies the desired dimensions and pixel format of the
- * front buffer.
- * @param src_surf_attrib (IN) Specifies the desired dimensions and pixel
- * format of the back buffers.
- * @param buffer_count (IN) Number of buffers required in this swap chain.
- * @param sync_data (IN) While not described in the DDK documentation,
- * this is an array of sync data for each buffer.
- * @param oem_flags (IN) Unused.
- * @param swap_chain_h (OUT) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param swap_chain_id (OUT) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE device_h,
- IMG_UINT32 flags,
- DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib,
- DISPLAY_SURF_ATTRIBUTES *src_surf_attrib,
- IMG_UINT32 buffer_count,
- PVRSRV_SYNC_DATA **sync_data,
- IMG_UINT32 oem_flags,
- IMG_HANDLE *swap_chain_h,
- IMG_UINT32 *swap_chain_id)
-{
- emgddc_devinfo_t *devinfo;
- emgddc_swapchain_t *swap_chain;
- emgddc_buffer_t *buffers;
- IMG_UINT32 i;
- emgddc_flip_queue_item_t *flip_queue = NULL;
- unsigned long lock_flags;
-
- struct drm_device* drm_dev;
- drm_emgd_private *priv;
- igd_context_t *context;
- igd_dispatch_t *dispatch;
- int flipable;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p, buffer_count = %lu", device_h, buffer_count);
- EMGD_DEBUG("flags = 0x%08lx, oem_flags = 0x%08lx", flags, oem_flags);
-
-
- /*
- * Check the parameters and dependencies:
- */
- if (!device_h || !dst_surf_attrib || !src_surf_attrib || !sync_data ||
- !swap_chain_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- /*
- * The oem_flags will determine what type of swapchain this is. The
- * following types are for a non-flip-able swap chain (e.g. for a pixmap):
- *
- * PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY - General purpose displayable
- * PVR2D_CREATE_FLIPCHAIN_OEMGENERAL - General purpose non-displayable
- * PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY - Overlay
- *
- * Currently, if none of these flags are set, assume this is going
- * to create a set of back buffers, or a "flip-able" swap chain:
- *
- * PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN - Flip-able buffers
- */
- /* Is this is an OEM call (I.E. allocating a buffer)? */
- if ((oem_flags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
- PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
- PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY))) {
- flipable = 0;
- } else {
- /*
- * If this is suppose to be an actual flip-able swap chain, then
- * make sure there are at least 2 buffers.
- */
- if (buffer_count < 2) {
- return PVRSRV_ERROR_TOO_FEW_BUFFERS;
- }
- flipable = 1;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- if (!is_valid_devinfo(devinfo)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, devinfo);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
- drm_dev = devinfo->drm_device;
- priv = drm_dev->dev_private;
- context = priv->context;
- dispatch = &(context->dispatch);
-
-
- if (buffer_count > devinfo->display_info.ui32MaxSwapChainBuffers) {
- return PVRSRV_ERROR_TOOMANYBUFFERS;
- }
-
- /* Ensure the source & destination attributes match each other: */
- if ((dst_surf_attrib->pixelformat != src_surf_attrib->pixelformat) ||
- (dst_surf_attrib->sDims.ui32ByteStride !=
- src_surf_attrib->sDims.ui32ByteStride) ||
- (dst_surf_attrib->sDims.ui32Width != src_surf_attrib->sDims.ui32Width)||
- (dst_surf_attrib->sDims.ui32Height !=
- src_surf_attrib->sDims.ui32Height)) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- if (flipable) {
- PVRSRV_ERROR err =
- do_mode_change(context, devinfo, priv, dst_surf_attrib);
- if (err != PVRSRV_OK) {
- EMGD_DEBUG("Exiting early because of an error in do_mode_change()");
- EMGD_TRACE_EXIT;
- return err;
- }
- }
-
- /*
- * Allocate data structures:
- */
- swap_chain = (emgddc_swapchain_t *) OS_ALLOC(sizeof(emgddc_swapchain_t));
- if (!swap_chain) {
- EMGD_ERROR_EXIT("Can not allocate memory for a swap chain");
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- OS_MEMSET(swap_chain, 0, sizeof(emgddc_swapchain_t));
-
- buffers = (emgddc_buffer_t *) OS_ALLOC(sizeof(emgddc_buffer_t) *
- buffer_count);
- if (!buffers) {
- OS_FREE(swap_chain);
- EMGD_ERROR_EXIT("Can not allocate memory for swap chain buffers");
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- OS_MEMSET(buffers, 0, sizeof(emgddc_buffer_t) * buffer_count);
-
- if (flipable) {
- flip_queue = (emgddc_flip_queue_item_t *)
- OS_ALLOC(sizeof(emgddc_flip_queue_item_t) * buffer_count);
- if (!flip_queue) {
- OS_FREE(buffers);
- OS_FREE(swap_chain);
- EMGD_ERROR_EXIT("Can not allocate memory for flip queue");
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- OS_MEMSET(flip_queue, 0,
- sizeof(emgddc_flip_queue_item_t) * buffer_count);
- }
-
- /*
- * Initialize data structures:
- */
- swap_chain->devinfo = devinfo;
- swap_chain->valid = EMGD_TRUE;
- swap_chain->buffer_count = (unsigned long) buffer_count;
- swap_chain->buffers = buffers;
- swap_chain->flags = flags;
- swap_chain->next = NULL;
- if (flipable) {
- swap_chain->flip_queue = flip_queue;
- swap_chain->insert_index = 0;
- swap_chain->remove_index = 0;
- }
- swap_chain->pvr_jtable = &devinfo->pvr_jtable;
-
- /* Link the buffers of the swap chain: */
- for (i = 0 ; i < buffer_count-1 ; i++) {
- buffers[i].next = &buffers[i+1];
- }
- buffers[i].next = &buffers[0];
-
- i = 0;
- if (flipable) {
- /* The first buffer is the frame buffer (a.k.a. the front buffer). */
- buffers[i].priv = priv;
- buffers[i].offset = devinfo->system_buffer.offset;
- buffers[i].pixel_format = devinfo->system_buffer.pixel_format;
- buffers[i].width = devinfo->system_buffer.width;
- buffers[i].height = devinfo->system_buffer.height;
- buffers[i].pitch = devinfo->system_buffer.pitch;
- buffers[i].size = devinfo->system_buffer.size;
- buffers[i].virt_addr = devinfo->system_buffer.virt_addr;
- buffers[i].sync_data = sync_data[0];
- buffers[i].is_fb = 1;
- swap_chain->flags |= PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN;
- i++;
- }
-
- /*
- * Allocate memory for the buffers
- */
- for (; i < buffer_count ; i++) {
- unsigned long offset;
- unsigned int width = 0;
- unsigned int height = 0;
- unsigned int pitch = 0;
- unsigned long size = 0;
- unsigned long pf;
- unsigned long flags = IGD_SURFACE_RENDER;
- int ret;
-
- if (!(oem_flags & PVR2D_CREATE_FLIPCHAIN_OEMGENERAL)) {
- flags |= IGD_SURFACE_DISPLAY;
- }
-
- buffers[i].priv = priv;
-
- /*
- * What should be used for the surface attributes, the source
- * surface attributes or the destination surface attributes?
- * Can we assume that source is the surface requested?
- */
- pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
- width = dst_surf_attrib->sDims.ui32Width;
- height = dst_surf_attrib->sDims.ui32Height;
- pitch = dst_surf_attrib->sDims.ui32ByteStride;
- flags |= IGD_MIN_PITCH;
- ret = dispatch->gmm_alloc_surface(&offset,
- pf,
- &width, &height,
- &pitch, &size,
- IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
- if (0 != ret) {
- free_swap_chain(swap_chain, context);
- EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
- dst_surf_attrib->sDims.ui32ByteStride = pitch;
- src_surf_attrib->sDims.ui32ByteStride = pitch;
-
- buffers[i].pixel_format = pf;
- buffers[i].width = width;
- buffers[i].height = height;
- buffers[i].pitch = pitch;
- buffers[i].size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
- buffers[i].offset = offset;
- buffers[i].virt_addr = dispatch->gmm_map(offset);
- buffers[i].sync_data = sync_data[i];
- buffers[i].is_fb = 0;
- } /* for */
-
-
- if (flipable) {
- /* Initialize what's needed for flip-able swap chains: */
- int must_enable;
-
- for (i = 0 ; i < buffer_count ; i++) {
- flip_queue[i].valid = EMGD_FALSE;
- flip_queue[i].flipped = EMGD_FALSE;
- flip_queue[i].cmd_completed = EMGD_FALSE;
- }
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- must_enable = (devinfo->flipable_swapchains == NULL) ? 1 : 0;
-
- /* Add this swap chain to the list of flip-able swap chains: */
- add_swap_chain_to_list(&devinfo->flipable_swapchains, swap_chain);
-
- /* Unlock here (before enabling interrupts), to prevent deadlock: */
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
- if (!devinfo->flush_commands) {
- if (must_enable) {
- /* Enable interrupts for vblanks: */
- if (!devinfo->interrupt_h || dispatch->
- enable_vblank_callback(devinfo->interrupt_h)) {
- /* For some reason (rare), interrupts weren't enabled: */
- EMGD_ERROR_EXIT("Can not enable VBlank interrupts! "
- "Therefore, cannot do buffer flipping!");
- /* Properly clean up: */
- remove_swap_chain_from_list(&devinfo->flipable_swapchains,
- swap_chain);
- free_swap_chain(swap_chain, context);
- return PVRSRV_ERROR_BAD_MAPPING;
- } else {
- devinfo->flipping_disabled = EMGD_FALSE;
- }
- }
- }
-
-#ifdef SUPPORT_FB_EVENTS
- if (must_enable) {
- /* Enable fb events: */
- if (enable_event_notification(devinfo)!= EMGD_OK) {
- EMGD_ERROR_EXIT("Can not enable framebuffer event "
- "notification");
- /* Properly clean up: */
- if (devinfo->interrupt_h) {
- dispatch->disable_vblank_callback(
- devinfo->interrupt_h);
- }
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
- remove_swap_chain_from_list(&devinfo->flipable_swapchains,
- swap_chain);
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
- free_swap_chain(swap_chain, context);
- return PVRSRV_ERROR_BAD_MAPPING;
- }
- }
-#endif /* SUPPORT_FB_EVENTS */
- } else {
- /* Add this swap chain to the list of pixmap swap chains: */
- add_swap_chain_to_list(&devinfo->pixmap_swapchains, swap_chain);
- }
-
-
- *swap_chain_id = ++devinfo->swap_chain_id_counter;
- *swap_chain_h = (IMG_HANDLE) swap_chain;
- EMGD_DEBUG("swap_chain_h = 0x%p, *swap_chain_id = %lu",
- swap_chain_h, *swap_chain_id);
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* CreateDCSwapChain() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnDestroyDCSwapChain()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h)
-{
- emgddc_devinfo_t *devinfo;
- drm_emgd_private *priv;
- igd_context_t *context;
- igd_dispatch_t *dispatch;
- emgddc_swapchain_t *swap_chain;
- unsigned long lock_flags;
-#ifdef SUPPORT_FB_EVENTS
- emgd_error_t error;
-#endif /* SUPPORT_FB_EVENTS */
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !swap_chain_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- priv = devinfo->priv;
- context = priv->context;
- dispatch = &(context->dispatch);
- swap_chain = (emgddc_swapchain_t *) swap_chain_h;
- if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
- "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- /* Remove swap chain from the appropriate list: */
- if (swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN) {
- /* De-initialize what's needed for flip-able swap chains: */
- int must_disable;
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
- must_disable =
- ((devinfo->flipable_swapchains == swap_chain) &&
- (devinfo->flipable_swapchains->next == NULL)) ? 1 : 0;
-
- /* Remove this swap chain from the list of flip-able swap chains: */
- remove_swap_chain_from_list(&devinfo->flipable_swapchains, swap_chain);
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
-#ifdef SUPPORT_FB_EVENTS
- if (must_disable) {
- /* Disable fb events: */
- error = disable_event_notification(devinfo);
- if (error != EMGD_OK) {
- EMGD_ERROR("Could not disable framebuffer event notification");
- }
- }
-#endif /* SUPPORT_FB_EVENTS */
-
- /* Disable interrupts for vblanks: */
- if (must_disable) {
- if (devinfo->interrupt_h) {
- dispatch->disable_vblank_callback(devinfo->interrupt_h);
- }
- }
-
- /* Flush any pending flips: */
- flush_flip_queue(swap_chain);
-
- /* Flip back to the system buffer: */
- emgddc_flip(swap_chain, &devinfo->system_buffer);
- } else {
- /* Remove this swap chain from the list of pixmap swap chains: */
- remove_swap_chain_from_list(&devinfo->pixmap_swapchains, swap_chain);
- }
-
- /* Free all GMM and kernel space memory for this swap chain: */
- free_swap_chain(swap_chain, context);
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* DestroyDCSwapChain() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstRect()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param rect (IN) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h,
- IMG_RECT *rect)
-{
- UNREFERENCED_PARAMETER(device_h);
- UNREFERENCED_PARAMETER(swap_chain_h);
- UNREFERENCED_PARAMETER(rect);
-
- EMGD_TRACE_STUB;
-
- return PVRSRV_ERROR_NOT_SUPPORTED;
-}
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcRect()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param rect (IN) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h,
- IMG_RECT *rect)
-{
- UNREFERENCED_PARAMETER(device_h);
- UNREFERENCED_PARAMETER(swap_chain_h);
- UNREFERENCED_PARAMETER(rect);
-
- EMGD_TRACE_STUB;
-
- return PVRSRV_ERROR_NOT_SUPPORTED;
-}
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstColourKey()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param color (IN) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h,
- IMG_UINT32 color)
-{
- UNREFERENCED_PARAMETER(device_h);
- UNREFERENCED_PARAMETER(swap_chain_h);
- UNREFERENCED_PARAMETER(color);
-
- EMGD_TRACE_STUB;
-
- return PVRSRV_ERROR_NOT_SUPPORTED;
-}
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcColourKey()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param color (IN) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h,
- IMG_UINT32 color)
-{
- UNREFERENCED_PARAMETER(device_h);
- UNREFERENCED_PARAMETER(swap_chain_h);
- UNREFERENCED_PARAMETER(color);
-
- EMGD_TRACE_STUB;
-
- return PVRSRV_ERROR_NOT_SUPPORTED;
-}
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBuffers()
- * function.
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @param buffer_count (OUT) The number of buffers in the specified swap chain.
- * @param buffer_h (IN/OUT) An array of buffer handles (an opaque pointer to a
- * emgddc_buffer_t) in the specified swap chain (memory must be allocated by
- * the caller).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h,
- IMG_UINT32 *buffer_count,
- IMG_HANDLE *buffer_h)
-{
- emgddc_devinfo_t *devinfo;
- emgddc_swapchain_t *swap_chain;
- unsigned long i;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !swap_chain_h || !buffer_count || !buffer_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- swap_chain = (emgddc_swapchain_t *) swap_chain_h;
- if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
- "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- *buffer_count = (IMG_UINT32) swap_chain->buffer_count;
-
- for (i = 0 ; i < swap_chain->buffer_count ; i++) {
- buffer_h[i] = (IMG_HANDLE) &swap_chain->buffers[i];
- }
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* GetDCBuffers() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCBuffer()
- * function. This function is supposed to cause a flip to the specified
- * buffer. However, it is no longer called by PVR services!
- *
- * NOTE: As can be seen, this function was never completely implemented
- * (i.e. in the DDK used to create this version). This is because the PVR code
- * doesn't call this function. Instead, it calls emgddc_process_flip().
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param buffer_h (IN) The handle for this buffer (an opaque pointer to a
- * emgddc_buffer_t).
- * @param swap_interval (IN) Unused.
- * @param private_tag_h (IN) Unused.
- * @param clip_rect_count (IN) Largely unused.
- * @param clip_rect (IN) Unused.
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE device_h,
- IMG_HANDLE buffer_h,
- IMG_UINT32 swap_interval,
- IMG_HANDLE private_tag_h,
- IMG_UINT32 clip_rect_count,
- IMG_RECT *clip_rect)
-{
- /* This function is never called by PVR services, and so it is stubbed: */
- UNREFERENCED_PARAMETER(device_h);
- UNREFERENCED_PARAMETER(buffer_h);
- UNREFERENCED_PARAMETER(swap_interval);
- UNREFERENCED_PARAMETER(private_tag_h);
- UNREFERENCED_PARAMETER(clip_rect_count);
- UNREFERENCED_PARAMETER(clip_rect);
-
- EMGD_TRACE_STUB;
- return PVRSRV_ERROR_NOT_SUPPORTED;
-
-} /* SwapToDCBuffer() */
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCSystem()
- * function. This function causes a flip to the "system buffer" (a.k.a. frame
- * buffer).
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
- * to a emgddc_swapchain_t).
- * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
- */
-static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE device_h,
- IMG_HANDLE swap_chain_h)
-{
- emgddc_devinfo_t *devinfo;
- emgddc_swapchain_t *swap_chain;
- unsigned long lock_flags;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!device_h || !swap_chain_h) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- devinfo = (emgddc_devinfo_t *) device_h;
- swap_chain = (emgddc_swapchain_t *) swap_chain_h;
- if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
- "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
- /* This must be a flip-able swap chain, or we can't cause a flip for it: */
- if (!(swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN)) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- flush_flip_queue(swap_chain);
- emgddc_flip(swap_chain, &devinfo->system_buffer);
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
-
- EMGD_TRACE_EXIT;
- return PVRSRV_OK;
-
-} /* SwapToDCSystem() */
-
-
-/**
- * Drains the circular queue of buffers to flip for a specified swap chain.
- * The queue is processed in order. For every item in the queue, processing is
- * as follows:
- *
- * - An item that has been "completed" (i.e. PVR services has been told that
- * the flip occured), but hasn't reached the end of its swap interval, is
- * immediately ended and cleared.
- *
- * - An item that has been flipped, but hasn't been "completed" with PVR
- * services, is "completed," ended, and cleared.
- *
- * - An item that has been queued, but hasn't been flipped, is immediately
- * flipped (i.e. given the Poulsbo hardware, this really means that the
- * hardware is told to flip them at the start of the next vertical blanking
- * period), "completed," ended, and cleared.
- *
- * Note: This function assumes that the calling function has already obtained
- * the spin lock.
- *
- * @param swap_chain (IN) The swap chain to flush the queue for.
- */
-static void flush_flip_queue(emgddc_swapchain_t *swap_chain)
-{
- emgddc_flip_queue_item_t *flip_item;
- unsigned long max_index;
- unsigned long i;
-
- EMGD_TRACE_ENTER;
-
-
- /* Get the first item to drain in the circular queue: */
- flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
- max_index = swap_chain->buffer_count - 1;
-
- for (i = 0 ; i < swap_chain->buffer_count ; i++) {
- if (flip_item->valid == EMGD_FALSE) {
- continue;
- }
-
- EMGD_DEBUG("Flushing buffer offset=0x%lx", flip_item->buffer->offset);
-
- if ((swap_chain->devinfo->flipping_disabled == EMGD_FALSE) &&
- (flip_item->flipped == EMGD_FALSE) &&
- (swap_chain->valid == EMGD_TRUE)) {
- EMGD_DEBUG("Flipping to buffer offset=0x%lx",
- flip_item->buffer->offset);
- emgddc_flip(swap_chain, flip_item->buffer);
- }
-
- if (flip_item->cmd_completed == EMGD_FALSE) {
- PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
-
- EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
- flip_item->buffer->offset);
- pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete, IMG_TRUE);
- }
-
- /* We're done with this item in the queue. Prepare for processing the
- * next item:
- */
- flip_item->flipped = EMGD_FALSE;
- flip_item->cmd_completed = EMGD_FALSE;
- flip_item->valid = EMGD_FALSE;
-
- /* Point to the next item in the circular queue: */
- swap_chain->remove_index++;
- if (swap_chain->remove_index > max_index) {
- swap_chain->remove_index = 0;
- }
-
- /* Get the next item in the circular queue: */
- flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
- }
-
- /* Reset the circular queue to the start: */
- swap_chain->insert_index = 0;
- swap_chain->remove_index = 0;
-
-
- EMGD_TRACE_EXIT;
-
-} /* flush_flip_queue() */
-
-
-static void set_flush_state_internal_nolock(emgddc_devinfo_t* devinfo,
- emgd_bool flush_state)
-{
- emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
-
- EMGD_TRACE_ENTER;
-
-
- if (flush_state) {
- if (devinfo->set_flush_state_ref_count == 0) {
- /* Don't actually disable interrupts. Just set a flag so that
- * buffer flips won't be queued, then flush the circular buffer of
- * all pending flips, for all swap chains:
- */
- devinfo->flush_commands = EMGD_TRUE;
- while (swap_chain != NULL) {
- flush_flip_queue(swap_chain);
- swap_chain = swap_chain->next;
- }
- }
- devinfo->set_flush_state_ref_count++;
- } else {
- if (devinfo->set_flush_state_ref_count != 0) {
- devinfo->set_flush_state_ref_count--;
- if (devinfo->set_flush_state_ref_count == 0) {
- /* Don't actually enable interrupts. Just set a flag so that
- * buffer flips will be queued:
- */
- devinfo->flush_commands = EMGD_FALSE;
- }
- }
- }
-
-
- EMGD_TRACE_EXIT;
-}
-
-
-static void set_flush_state_external(emgddc_devinfo_t* devinfo,
- emgd_bool flush_state)
-{
- unsigned long lock_flags;
-
- EMGD_TRACE_ENTER;
-
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- if (devinfo->flush_commands != flush_state) {
- devinfo->flush_commands = flush_state;
- set_flush_state_internal_nolock(devinfo, flush_state);
- }
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
-
- EMGD_TRACE_EXIT;
-}
-
-
-/**
- * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCState() function.
- * This function is supposed to set some state flags in the driver, affecting
- * interrupt-driven buffer flips.
- *
- * Note: The following function used to never be called, but now is called when
- * X11 is rotated 90 degrees (it is called as a result of an interrupt handler
- * dealing with an SGX hardware reset). As such, the code that this calls
- * cannot enable/disable interrupts (which may cause an interrupt handler to be
- * registered/unregistered).
- *
- * Note: The code that this calls seems overly complicated. If we never enable
- * SUPPORT_FB_EVENTS, it can be simplified (e.g. no use of
- * set_flush_state_ref_count).
- *
- * @param device_h (IN) The handle for this device (an opaque pointer to
- * devinfo).
- * @param state (IN) Either DC_STATE_FLUSH_COMMANDS or
- * DC_STATE_NO_FLUSH_COMMANDS.
- */
-static IMG_VOID SetDCState(IMG_HANDLE device_h, IMG_UINT32 state)
-{
- emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) device_h;
-
- EMGD_TRACE_ENTER;
- EMGD_DEBUG("device_h = 0x%p", device_h);
-
-
- if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
- __FUNCTION__, device_h);
- return;
- }
-
- switch (state) {
- case DC_STATE_FLUSH_COMMANDS:
- set_flush_state_external(devinfo, EMGD_TRUE);
- break;
- case DC_STATE_NO_FLUSH_COMMANDS:
- set_flush_state_external(devinfo, EMGD_FALSE);
- break;
- default:
- break;
- }
-
-
- EMGD_TRACE_EXIT;
-} /* SetDCState() */
-
-
-#ifdef SUPPORT_FB_EVENTS
-/* NOTE -- The following code is probably not correct. It was inherited from
- * an early IMG/UMG DDK, and has never been used. If we ever decide to use
- * this code, we should look at the latest DDK and UMG code, to glean what may
- * be really needed. At a minimum, the following code needs to affect all swap
- * chains.
- */
-
-static int emgddc_fb_events(struct notifier_block *notif,
- unsigned long event, void *data)
-{
- emgddc_devinfo_t *devinfo;
- emgddc_swapchain_t *swap_chain;
- struct fb_event *fb_event = (struct fb_event *) data;
- emgd_bool blanked;
- unsigned long lock_flags;
-
- EMGD_TRACE_ENTER;
-
-
- if (event != FB_EVENT_BLANK) {
- return 0;
- }
-
- /* Look up the device (for DIH/Extended mode): */
- if (notif == &(global_devinfo[0]->lin_notif_block)) {
- devinfo = global_devinfo[0];
- } else if (notif == &(global_devinfo[1]->lin_notif_block)) {
- devinfo = global_devinfo[1];
- } else {
- printk(KERN_ERR "[EMGD] emgddc_fb_events() cannot find its device\n");
- return -ENODEV;
- }
- swap_chain = devinfo->flipable_swapchains;
-
- blanked = (*(IMG_INT *) fb_event->data != 0) ? EMGD_TRUE : EMGD_FALSE;
-
- if (blanked != swap_chain->blanked) {
- swap_chain->blanked = blanked;
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- if (blanked) {
- set_flush_state_internal_nolock(devinfo, EMGD_TRUE);
- } else {
- set_flush_state_internal_nolock(devinfo, EMGD_FALSE);
- }
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
- }
-
-
- EMGD_TRACE_EXIT;
-
- return 0;
-}
-
-
-static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo)
-{
- int res;
- emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
-
- EMGD_TRACE_ENTER;
-
-
- memset(&devinfo->lin_notif_block, 0, sizeof(devinfo->lin_notif_block));
-
- devinfo->lin_notif_block.notifier_call = emgddc_fb_events;
- swap_chain->blanked = EMGD_FALSE;
- res = fb_register_client(&devinfo->lin_notif_block);
- if (res != 0) {
- EMGD_ERROR_EXIT("fb_register_client() failed (%d)", res);
- return EMGD_ERROR_GENERIC;
- }
-
-
- EMGD_TRACE_EXIT;
-
- return EMGD_OK;
-}
-
-
-static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo)
-{
- int res;
-
-
- EMGD_TRACE_ENTER;
-
-
- res = fb_unregister_client(&devinfo->lin_notif_block);
- if (res != 0) {
- EMGD_ERROR_EXIT("fb_unregister_client() failed (%d)", res);
- return EMGD_ERROR_GENERIC;
- }
-
-
- EMGD_TRACE_EXIT;
-
- return EMGD_OK;
-}
-#endif /* SUPPORT_FB_EVENTS */
-
-
-/**
- * This function does per-vblank processing of the circular queue of buffers to
- * flip. It is called for each flip-able swap chain, during a VBlank
- * interrupt. The first item in the queue is processed, and if it is cleared
- * (see below), the next item is processed, etc. Items are processed as
- * follows:
- *
- * - An item that hasn't been flipped, is flipped. In this case, processing
- * stops. It is assumed that the swap interval for this item is at least
- * one, and therefore, another vblank is needed for this flip.
- *
- * - An item that has been flipped, but hasn't been "completed" (i.e. PVR
- * services has been told that the flip occured), is "completed" and has its
- * swap interval decremented by 1. If the swap interval is now 0, the item
- * is cleared, allowing processing of the next item to start.
- *
- * - An item that has been "completed," but hasn't reached the end of its swap
- * interval, has its swap interval decremented by 1. If the swap interval is
- * now 0, the item is cleared, allowing processing of the next item to start.
- *
- * @param swap_chain (IN) The swap chain to process the queue for.
- */
-emgd_bool emgddc_process_flip_queue_for_vblank(emgddc_swapchain_t *swap_chain)
-{
- PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
- IMG_BOOL status = IMG_TRUE;
- emgddc_flip_queue_item_t *flip_item;
- unsigned long max_index;
-
- EMGD_TRACE_ENTER;
-
-
- if (swap_chain->devinfo->flush_commands) {
- EMGD_TRACE_EXIT;
- return status;
- }
-
- /* Get the first item to process in the circular queue: */
- flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
- max_index = swap_chain->buffer_count - 1;
-
- while (flip_item->valid) {
- if (flip_item->flipped) {
- if (!flip_item->cmd_completed) {
- EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer "
- "offset=0x%lx", flip_item->buffer->offset);
- pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete,
- IMG_TRUE);
- flip_item->cmd_completed = EMGD_TRUE;
- }
-
- flip_item->swap_interval--;
- EMGD_DEBUG("Swap interval is %lu for buffer offset=0x%lx",
- flip_item->swap_interval, flip_item->buffer->offset);
-
- if (flip_item->swap_interval == 0) {
- /* We're done with this item in the queue. Prepare for
- * processing the next item:
- */
- flip_item->cmd_completed = EMGD_FALSE;
- flip_item->flipped = EMGD_FALSE;
- flip_item->valid = EMGD_FALSE;
-
- /* Point to the next item in the circular queue: */
- swap_chain->remove_index++;
- if (swap_chain->remove_index > max_index) {
- swap_chain->remove_index = 0;
- }
- } else {
- /* Wait for more vblanks before doing more queue processing: */
- break;
- }
- } else {
- EMGD_DEBUG("Flipping to buffer offset=0x%lx",
- flip_item->buffer->offset);
- emgddc_flip(swap_chain, flip_item->buffer);
- flip_item->flipped = EMGD_TRUE;
- /* Wait for more vblanks before doing more queue processing: */
- break;
- }
-
- /* Get the next item in the circular queue: */
- flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
- }
-
-
- EMGD_TRACE_EXIT;
-
- return status;
-
-} /* emgddc_process_flip_queue_for_vblank() */
-
-
-/**
- * This is called by a HAL-implemented, Linux interrupt handler. It is called
- * when a VBlank interrupt occurs. All device-specific functionality was
- * implemented by the HAL, and only 3DD-specific functionality needs to be
- * provided by this function.
- *
- * @param pdevinfo (IN) Pointer to the devinfo that had a VBlank interrupt.
- * @return Non-zero for success, zeron for failure.
- */
-static int emgddc_process_vblank(void* pdevinfo)
-{
- emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) pdevinfo;
- emgddc_swapchain_t *swap_chain;
- unsigned long lock_flags;
-
- EMGD_TRACE_ENTER;
-
-
- if ((devinfo != global_devinfo[0]) && (devinfo != global_devinfo[1])) {
- return 0;
- }
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- swap_chain = devinfo->flipable_swapchains;
- while (swap_chain != NULL) {
- (void) emgddc_process_flip_queue_for_vblank(swap_chain);
- swap_chain = swap_chain->next;
- }
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
- return 1;
-
-} /* emgddc_process_vblank() */
-
-
-/**
- * Called by PVR services to flip a buffer. When interrupts are supported, the
- * flip may be queued (in a circular buffer) to happen later. When interrupts
- * are not supported, the flip always happens immediately
- *
- * @param cmd_cookie_h (IN) An opaque pointer to a PVR service data structure
- * that must be handed back when the flip is "completed" (i.e. PVR services
- * is told that the flip occured).
- * @param data_size (IN) Size of the flip command and all clipping rectangles
- * (which isn't supported). This is only used for consistency-checking.
- * @param data (IN) A pointer to information about what to flip.
- */
-static IMG_BOOL emgddc_process_flip(IMG_HANDLE cmd_cookie_h,
- IMG_UINT32 data_size,
- IMG_VOID *data)
-{
- DISPLAYCLASS_FLIP_COMMAND *flip_cmd;
- emgddc_devinfo_t *devinfo;
- emgddc_buffer_t *buffers;
- emgddc_swapchain_t *swap_chain;
- unsigned long max_index;
- emgddc_flip_queue_item_t* flip_item;
- unsigned long lock_flags;
- int must_flip = 0;
- int must_complete = 0;
- igd_context_t *context;
-
- EMGD_TRACE_ENTER;
-
-
- /*
- * Unpack the flip command and look for errors:
- */
-
- if (!cmd_cookie_h || !data) {
- EMGD_ERROR_EXIT("NULL parameter(s)");
- return IMG_FALSE;
- }
-
- flip_cmd = (DISPLAYCLASS_FLIP_COMMAND *) data;
-
- /* Note: the data_size actually accounts for both the flip command and
- * all of the clipping rectangles. As such, the only error is if
- * data_size is smaller than the sizeof the flip command:
- */
- if (flip_cmd == IMG_NULL ||
- (sizeof(DISPLAYCLASS_FLIP_COMMAND) > data_size)) {
- EMGD_ERROR_EXIT("Invalid flip_cmd (0x%p)", flip_cmd);
- return IMG_FALSE;
- }
-
- devinfo = (emgddc_devinfo_t *) flip_cmd->hExtDevice;
- buffers = (emgddc_buffer_t *) flip_cmd->hExtBuffer;
- swap_chain = (emgddc_swapchain_t *) flip_cmd->hExtSwapChain;
-
- if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
- /* Note: I (Ian Elliott) have noticed with hardware video decode, that
- * it creates pixmap swap chains, and when they are being destroyed (at
- * the end of video playback), something tries to flip these
- * non-flipable swap chains. The only way to avoid a hang is to
- * "complete" the flip command.
- */
- printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
- "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
- swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
- EMGD_TRACE_EXIT;
- return IMG_TRUE;
- }
-
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
-
- if ((devinfo->flipping_disabled == EMGD_TRUE) ||
- (swap_chain->valid != EMGD_TRUE)) {
- /* We won't flip, but must tell PVR services that the flip occured: */
- EMGD_DEBUG("Something (e.g. a mode change) has invalidated\n"
- "this swap chain. As such buffer flips are not allowed.\n"
- "If a mode change caused this problem, this swap chain\n"
- "needs to be destroyed, and a new one created.");
- swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
- EMGD_TRACE_EXIT;
- return IMG_TRUE;
- }
-
- context = devinfo->priv->context;
- if (context->device_context.power_state != IGD_POWERSTATE_D0) {
- /* If device is in a suspended state, but PVR services asks the driver
- * to perform a buffer flip, basically ignore it except for telling PVR
- * services that we did the flip:
- */
- EMGD_DEBUG("Device in suspended state--completing command");
- swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
- EMGD_TRACE_EXIT;
- return IMG_TRUE;
- }
-
- /* Get the first item to add to the circular queue: */
- flip_item = &swap_chain->flip_queue[swap_chain->insert_index];
- max_index = swap_chain->buffer_count - 1;
-
-
- /*
- * Decide what needs to be done:
- */
- if ((flip_cmd->ui32SwapInterval == 0) ||
- (devinfo->flush_commands == EMGD_TRUE)) {
- /* Perform and complete the flip now: */
- must_flip = 1;
- must_complete = 1;
- } else {
- /* PVR services only calls emgddc_process_flip() when the 3DD completes
- * the previous flip. Thus, the circular flip_item queue should never
- * overflow. However, just in case, check whether the flip_item
- * already contains a valid/queued flip (i.e. we've overflowed the
- * circular queue).
- */
- if (flip_item->valid == EMGD_FALSE) {
- if (swap_chain->insert_index == swap_chain->remove_index) {
- /* Perform the flip now, but queue it for completion: */
- must_flip = 1;
- }
- /* else - queue the flip for later: */
- } else {
- /* Just in case we overflow the circular queue, generate an error */
- swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
- EMGD_ERROR_EXIT("Overflowed the circular flip_item queue");
- return IMG_FALSE;
- }
- }
-
-
- /*
- * Do what needs to be done:
- */
- if (must_flip) {
- /* Perform the flip now: */
- EMGD_DEBUG("Flipping to buffer offset=0x%lx", buffers->offset);
- emgddc_flip(swap_chain, buffers);
- }
- if (must_complete) {
- /* Tell the PVR services that the flip occured: */
- EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
- buffers->offset);
- swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
- } else {
- /* Queue the flip for later completion: */
- EMGD_DEBUG("Queueing buffer offset=0x%lx", buffers->offset);
- if (must_flip) {
- flip_item->flipped = EMGD_TRUE;
- }
- flip_item->cmd_complete = cmd_cookie_h;
- flip_item->swap_interval = (unsigned long) flip_cmd->ui32SwapInterval;
- flip_item->valid = EMGD_TRUE;
- flip_item->buffer = buffers;
-
- swap_chain->insert_index++;
- if (swap_chain->insert_index > max_index) {
- swap_chain->insert_index = 0;
- }
- }
-
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
- EMGD_TRACE_EXIT;
- return IMG_TRUE;
-} /* emgddc_process_flip() */
-
-
-/**
- * For a given devinfo, unmap's the frame buffer, and frees the devinfo and
- * it's surfaces.
- *
- * @param dev (IN) The drm_device for this driver connection.
- */
-void emgddc_free_a_devinfo(emgddc_devinfo_t *devinfo)
-{
- igd_context_t *context = devinfo->priv->context;
-
- EMGD_TRACE_ENTER;
-
- if (devinfo->priv->hal_running) {
- /* Un-register (if needed) the interrupt connection with the HAL: */
- if (devinfo->interrupt_h) {
- context->dispatch.unregister_vblank_callback(devinfo->interrupt_h);
- devinfo->interrupt_h = NULL;
- }
-
- if (devinfo->system_buffer.virt_addr) {
- context->dispatch.gmm_unmap(devinfo->system_buffer.virt_addr);
- }
- }
- OS_FREE(devinfo);
-
- EMGD_TRACE_EXIT;
-} /* emgddc_free_a_devinfo() */
-
-
-/**
- * Frees all devinfo structures and their surfaces. This is called during
- * de-init time, or when init fails.
- */
-void emgddc_free_all_devinfos(void)
-{
- emgddc_devinfo_t *devinfo;
-
- EMGD_TRACE_ENTER;
-
- /* Free the primary display's structures: */
- devinfo = global_devinfo[0];
- emgddc_free_a_devinfo(devinfo);
- global_devinfo[0] = NULL;
-
- /* Free the secondary display's structures, if applicable: */
- if (NULL == (devinfo = global_devinfo[1])) {
- emgddc_free_a_devinfo(devinfo);
- global_devinfo[1] = NULL;
- }
-
- EMGD_TRACE_EXIT;
-} /* emgddc_free_all_devinfos() */
-
-
-/**
- * Initialize the "static" (i.e. doesn't vary with alter_display) portion of
- * a devinfo structure.
- *
- * @param dev (IN) The drm_device for this driver connection.
- * @param devinfo (IN/OUT) The devinfo to initialize.
- * @param port_number (IN) Which devinfo (0 for primary, 1 for secondary/DIH).
- * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
- */
-static emgd_error_t emgddc_init_devinfo(struct drm_device *dev,
- emgddc_devinfo_t *devinfo, int which_devinfo)
-{
- drm_emgd_private *priv = dev->dev_private;
- PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable;
- PFN_CMD_PROC cmd_proc_list[EMGDDC_COMMAND_COUNT];
- IMG_UINT32 sync_count_list[EMGDDC_COMMAND_COUNT][2];
-
- EMGD_TRACE_ENTER;
-
-
- /*
- * Initialize the static/display-independent devinfo values:
- */
- devinfo->which_devinfo = which_devinfo;
- devinfo->priv = priv;
- devinfo->drm_device = dev;
- devinfo->flipable_swapchains = NULL;
- devinfo->swap_chain_id_counter = 0;
- devinfo->display_info.ui32MaxSwapChainBuffers = 5;
- devinfo->display_info.ui32MaxSwapChains = 1024 * 1024;
- /* Note: change from zero if we support interrupts and see the need: */
- devinfo->display_info.ui32MaxSwapInterval = 2;
- devinfo->display_info.ui32MinSwapInterval = 0;
- EMGD_DEBUG("Maximum number of swap chains: %lu",
- devinfo->display_info.ui32MaxSwapChains);
- EMGD_DEBUG("Maximum number of swap chain buffers: %lu",
- devinfo->display_info.ui32MaxSwapChainBuffers);
- strncpy(devinfo->display_info.szDisplayName, DISPLAY_DEVICE_NAME,
- MAX_DISPLAY_NAME_SIZE);
- devinfo->flush_commands = EMGD_FALSE;
- spin_lock_init(&devinfo->swap_chain_lock);
-
-
- /*
- * Get the PVR services jump table, which this 3rd-party display driver can
- * use to call PVR services:
- */
- if (!PVRGetDisplayClassJTable(&devinfo->pvr_jtable)) {
- EMGD_ERROR_EXIT("Can not get PVR services jump table");
- return EMGD_ERROR_INIT_FAILURE;
- }
- pvr_jtable = &devinfo->pvr_jtable;
-
-
- /*
- * Setup the jump table that PVR services uses to call this 3rd-party
- * display driver:
- */
- devinfo->dc_jtable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
- devinfo->dc_jtable.pfnOpenDCDevice = OpenDCDevice;
- devinfo->dc_jtable.pfnCloseDCDevice = CloseDCDevice;
- devinfo->dc_jtable.pfnEnumDCFormats = EnumDCFormats;
- devinfo->dc_jtable.pfnEnumDCDims = EnumDCDims;
- devinfo->dc_jtable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
- devinfo->dc_jtable.pfnGetDCInfo = GetDCInfo;
- devinfo->dc_jtable.pfnGetBufferAddr = GetDCBufferAddr;
- devinfo->dc_jtable.pfnCreateDCSwapChain = CreateDCSwapChain;
- devinfo->dc_jtable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
- devinfo->dc_jtable.pfnSetDCDstRect = SetDCDstRect;
- devinfo->dc_jtable.pfnSetDCSrcRect = SetDCSrcRect;
- devinfo->dc_jtable.pfnSetDCDstColourKey = SetDCDstColourKey;
- devinfo->dc_jtable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
- devinfo->dc_jtable.pfnGetDCBuffers = GetDCBuffers;
- devinfo->dc_jtable.pfnSwapToDCBuffer = SwapToDCBuffer;
- devinfo->dc_jtable.pfnSwapToDCSystem = SwapToDCSystem;
- devinfo->dc_jtable.pfnSetDCState = SetDCState;
-
-
- /*
- * Register this device with PVR services:
- */
- if (pvr_jtable->pfnPVRSRVRegisterDCDevice(&devinfo->dc_jtable,
- &devinfo->device_id ) != PVRSRV_OK) {
- EMGD_ERROR_EXIT("Device registration failed");
- return EMGD_ERROR_DEVICE_REGISTER_FAILED;
- }
-
- EMGD_DEBUG("Device ID: %d", (int)devinfo->device_id);
-
-
- /*
- * Tell PVR services about the function to process swap-chain buffer
- * flips:
- */
- cmd_proc_list[DC_FLIP_COMMAND] = emgddc_process_flip;
-
- /* XXX - Not sure what these are for: */
- sync_count_list[DC_FLIP_COMMAND][0] = 0;
- sync_count_list[DC_FLIP_COMMAND][1] = 2;
-
- if (pvr_jtable->pfnPVRSRVRegisterCmdProcList(devinfo->device_id,
- &cmd_proc_list[0],
- sync_count_list,
- EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
- EMGD_ERROR_EXIT("Can't register callback\n");
- return EMGD_ERROR_CANT_REGISTER_CALLBACK;
- }
-
-
- EMGD_TRACE_EXIT;
- return EMGD_OK;
-
-} /* emgddc_init_devinfo() */
-
-
-/**
- * Initializes the display/device-specific values of the devinfo structure for
- * a specified display (primary or secondary). This function is called during
- * initialization time, and whenever the EMGD driver does a potential mode
- * change, via alter_displays().
- *
- * @param devinfo (IN/OUT) The devinfo to initialize for the display.
- * @param display (IN) The specified display (primary or secondary).
- * @param port_number (IN) The port number of the specified display.
- * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
- */
-static emgd_error_t init_display(emgddc_devinfo_t *devinfo,
- igd_display_h display,
- unsigned short port_number)
-{
- drm_emgd_private *priv = devinfo->priv;
- igd_context_t *context = priv->context;
- unsigned long dc = priv->dc;
- igd_framebuffer_info_t fb_info;
- DISPLAY_FORMAT *display_format_list;
- igd_display_info_t pt_info;
- unsigned long *fb_list_pfs;
- DISPLAY_DIMS *display_dim_list;
- igd_display_info_t *mode_list = NULL;
- igd_display_info_t *mode;
- int mode_flags = IGD_QUERY_LIVE_MODES;
- emgddc_buffer_t *buffer = &(devinfo->system_buffer);
- int i = 1, j, ret;
- emgddc_swapchain_t *swap_chain;
- unsigned long lock_flags;
-
- EMGD_TRACE_ENTER;
-
- EMGD_DEBUG("Parameters:");
- EMGD_DEBUG(" devinfo=0x%p", devinfo);
- EMGD_DEBUG(" devinfo->which_devinfo=%d", devinfo->which_devinfo);
- EMGD_DEBUG(" display=0x%p", display);
- EMGD_DEBUG(" port_number=%u", port_number);
-
-
- /* Mode changes invalidate flip-able swap chains. We can't destroy them
- * behind the back of PVR services, but we can and should ignore all
- * pending and future buffer flips for existing swap chains.
- *
- * Note: new swap chains will be valid, and be able to perform flips.
- */
- /* Obtain the lock, to hold-off future interrupt handling for a bit */
- spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
- swap_chain = devinfo->flipable_swapchains;
- while (swap_chain != NULL) {
- swap_chain->valid = EMGD_FALSE;
- flush_flip_queue(swap_chain);
- swap_chain = swap_chain->next;
- }
- /* Now that we've invalidated pending flips, release the lock */
- spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
-
-
- /* Clear the following lists, in case we are re-initializing: */
- OS_MEMSET(devinfo->display_format_list, 0,
- sizeof(devinfo->display_format_list));
- OS_MEMSET(devinfo->display_dim_list, 0,
- sizeof(devinfo->display_dim_list));
- display_format_list = devinfo->display_format_list;
- display_dim_list = devinfo->display_dim_list;
-
-
- /* Call get_display() to get some of the following info: */
- ret = context->dispatch.get_display(display, port_number,
- &fb_info, &pt_info, 0);
- if (0 != ret) {
- EMGD_ERROR_EXIT("get_display() returned %d", ret);
- return EMGD_ERROR_GENERIC;
- }
-
-
- /*
- * Obtain the following addresses:
- *
- * - buffer->offset = Framebuffer GTT address
- * - virt_addr = gmm_map(framebuffer offset);
- */
- buffer->offset = fb_info.fb_base_offset;
- buffer->virt_addr = context->dispatch.gmm_map(fb_info.fb_base_offset);
- EMGD_DEBUG("buffer->virt_addr = 0x%p", buffer->virt_addr);
- /* This is the offset of the allocated framebuffer (e.g. the
- * 1024x768 surface of gmm-managed memory):
- */
- EMGD_DEBUG("fb_info->fb_base_offset = 0x%lx", fb_info.fb_base_offset);
-
-
- /* Register (if we haven't) with the HAL to be able to use interrupts: */
- if (!devinfo->interrupt_h) {
- devinfo->interrupt_h =
- context->dispatch.register_vblank_callback(emgddc_process_vblank,
- devinfo, port_number);
- if (!devinfo->interrupt_h) {
- /* This should not happen, but just in case, provide an error: */
- printk(KERN_ERR "Cannot establish the ability to perform VBlank "
- "interrupts for port number %u.", port_number);
- }
- }
-
-
- /*
- * Obtain and translate pixel formats:
- */
- /* Note: We always care about the current pixel format: */
- devinfo->emgd_pf = fb_info.pixel_format;
- devinfo->pvr_pf = emgd2pvr_pf(fb_info.pixel_format);
- display_format_list[0].pixelformat = emgd2pvr_pf(fb_info.pixel_format);
- EMGD_DEBUG("FB's native EMGD pixel format = 0x%08lx", devinfo->emgd_pf);
- EMGD_DEBUG("FB's PVR pixel format = %u",display_format_list[0].pixelformat);
- if (!priv->xserver_running) {
- /* In addition, provide an entire list of pixel formats: */
- ret = context->dispatch.get_pixelformats(display, &fb_list_pfs, NULL,
- NULL, NULL, NULL);
- if (0 != ret) {
- EMGD_ERROR_EXIT("get_pixelformats() returned %d", ret);
- return EMGD_ERROR_GENERIC;
- }
- while (*fb_list_pfs) {
- if ((devinfo->pvr_pf != emgd2pvr_pf(*fb_list_pfs)) &&
- (PVRSRV_PIXEL_FORMAT_UNKNOWN != emgd2pvr_pf(*fb_list_pfs))) {
- display_format_list[i].pixelformat = emgd2pvr_pf(*fb_list_pfs);
- EMGD_DEBUG(" Add'l (%d) PVR pixel format = "
- "%u", i, emgd2pvr_pf(*fb_list_pfs));
- }
- fb_list_pfs++;
- if (++i >= EMGDDC_MAXFORMATS) {
- /* Don't write past the end of the array */
- EMGD_ERROR("Reached end of display_format_list! Consider "
- "increasing EMGDDC_MAXFORMATS.");
- break;
- }
- }
- }
- devinfo->num_formats = i;
- EMGD_DEBUG("Total number of translated pixel formats = %d", i);
-
-
- /*
- * Obtain the possible dimensions, from the EMGD modes:
- */
- /* Note: we always care about the current dimensions: */
- devinfo->width = fb_info.width;
- devinfo->height = fb_info.height;
- devinfo->byte_stride = fb_info.screen_pitch;
- EMGD_DEBUG("FB's width = %ld, height = %ld, stride = %ld",
- devinfo->width, devinfo->height, devinfo->byte_stride);
- display_dim_list[0].ui32Width = fb_info.width;
- display_dim_list[0].ui32Height = fb_info.height;
- display_dim_list[0].ui32ByteStride = fb_info.screen_pitch;
- i = 1;
- if (!priv->xserver_running) {
- /* In addition, provide an entire list of dimensions: */
- ret = context->dispatch.query_mode_list((igd_driver_h) context, dc,
- &mode_list, mode_flags);
- if (0 != ret) {
- EMGD_ERROR_EXIT("query_mode_list() returned %d", ret);
- return EMGD_ERROR_GENERIC;
- }
- mode = mode_list;
- while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
- int seen = 0;
- for (j = i - 1 ; j >= 0 ; j--) {
- if ((display_dim_list[j].ui32Width == mode->width) &&
- (display_dim_list[j].ui32Height == mode->height)) {
- seen = 1;
- }
- }
- if (!seen) {
- display_dim_list[i].ui32Width = mode->width;
- display_dim_list[i].ui32Height = mode->height;
- display_dim_list[i].ui32ByteStride =
- (mode->width * IGD_PF_BPP(devinfo->emgd_pf) + 7) >>3;
- EMGD_DEBUG(" Add'l width = %d, height = %d, stride = %ld",
- mode->width, mode->height,
- display_dim_list[i].ui32ByteStride);
- if (++i >= EMGDDC_MAXDIMS) {
- /* Don't write past the end of the array */
- EMGD_ERROR("Reached end of display_dim_list! Consider "
- "increasing EMGDDC_MAXDIMS.");
- break;
- }
- }
- mode++;
- }
- }
- devinfo->num_dims = i;
- EMGD_DEBUG("Total number of dimensions = %d", i);
-
-
- /*
- * Obtain the size of the frame buffer, which will also be the size of any
- * swap chain buffers:
- */
- devinfo->fb_size = devinfo->height * devinfo->byte_stride;
- EMGD_DEBUG("Frame buffer size = %lu = %luMB = 0x%lx", devinfo->fb_size,
- devinfo->fb_size / (1024 * 1024), devinfo->fb_size);
-
-
- /*
- * Initialize the igd_surface_t structure for the frame buffer, in order
- * allow the buffer flipping code to flip back to the frame buffer:
- */
- buffer->priv = priv;
- buffer->offset = fb_info.fb_base_offset;
- buffer->pitch = devinfo->byte_stride;
- buffer->width = devinfo->width;
- buffer->height = devinfo->height;
- buffer->pixel_format = fb_info.pixel_format;
- buffer->size = devinfo->fb_size;
-
-
- EMGD_TRACE_EXIT;
- return EMGD_OK;
-
-} /* init_display() */
-
-
-/**
- * [Re-]Initializes the 3DD's display/device-specific values for both devinfo
- * structures. This function is called during initializatio time, and whenever
- * the EMGD driver does a potential mode change, via alter_displays().
- *
- * @param dev (IN) The drm_device associated with this driver.
- * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
- */
-static int emgddc_reinit_3dd(struct drm_device *dev)
-{
- emgddc_devinfo_t *devinfo;
- drm_emgd_private *priv = dev->dev_private;
- int ret;
-
- EMGD_TRACE_ENTER;
-
- if (0 == priv->dc) {
- EMGD_DEBUG("not ready to re-init, because no dc has been set");
- if (!priv->hal_running) {
- /* Ensure that devinfo->interrupt_h is NULL: */
- if (NULL != (devinfo = global_devinfo[0])) {
- devinfo->interrupt_h = NULL;
- }
- if (NULL != (devinfo = global_devinfo[1])) {
- devinfo->interrupt_h = NULL;
- }
- }
- return EMGD_OK;
- }
-
- EMGD_DEBUG("The DC is 0x%08lx", priv->dc);
- EMGD_DEBUG("IGD_DC_CLONE(priv->dc) is %d", IGD_DC_CLONE(priv->dc));
- EMGD_DEBUG("IGD_DC_EXTENDED(priv->dc) is %d", IGD_DC_EXTENDED(priv->dc));
-
- /* Always initialize the primary devinfo: */
- ret = init_display(global_devinfo[0], priv->primary,
- priv->primary_port_number);
- if (ret != EMGD_OK) {
- return ret;
- }
-
- /* Initialize the secondary devinfo if we're in DIH/extended mode: */
- if (IGD_DC_EXTENDED(priv->dc)) {
- EMGD_DEBUG("Detected that we're in DIH/EXTENDED mode");
-
- /* Allocate the devinfo if it hasn't already been allocated: */
- if (NULL == (devinfo = global_devinfo[1])) {
- EMGD_DEBUG("Allocating devinfo structure for DIH/EXTENDED mode");
- devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
- if (!devinfo) {
- EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
- return EMGD_ERROR_OUT_OF_MEMORY;
- }
- OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
-
- /* Perform static/display-independent initialization: */
- ret = emgddc_init_devinfo(dev, devinfo, 1);
- if (ret != EMGD_OK) {
- EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
- emgddc_free_a_devinfo(devinfo);
- return ret;
- }
- }
-
- /* Perform dynamic/display-dependent initialization: */
- ret = init_display(devinfo, priv->secondary,
- priv->secondary_port_number);
- if (ret != EMGD_OK) {
- EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
- emgddc_free_a_devinfo(devinfo);
- global_devinfo[1] = NULL;
- return ret;
- }
-
- /* Remember the devinfo, for other functions that aren't passed it: */
- global_devinfo[1] = devinfo;
- }
-
-
- EMGD_TRACE_EXIT;
- return EMGD_OK;
-
-} /* emgddc_reinit_3dd() */
-
-
-/**
- * Master initialization function. This is called when the EMGD DRM module
- * tells PVR services to start, which calls this function.
- *
- * @param dev (IN) The drm_device for this driver connection.
- * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
- */
-emgd_error_t emgddc_init(struct drm_device *dev)
-{
- emgddc_devinfo_t *devinfo;
- drm_emgd_private *priv = dev->dev_private;
- int ret;
-
- EMGD_TRACE_ENTER;
-
-
- /* Exit early if trying to initialize again: */
- devinfo = global_devinfo[0];
- if (devinfo != NULL) {
- EMGD_TRACE_EXIT;
- return EMGD_OK;
- }
-
- /* Always allocate the primary display's devinfo structure: */
- devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
- if (!devinfo) {
- EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
- return EMGD_ERROR_OUT_OF_MEMORY;
- }
- OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
- global_devinfo[0] = devinfo;
-
- /* Perform static/display-independent initialization: */
- ret = emgddc_init_devinfo(dev, devinfo, 0);
- if (ret != EMGD_OK) {
- emgddc_free_all_devinfos();
- return ret;
- }
-
- /* Perform dynamic/display-dependent initialization (if we're in
- * DIH/Extended mode, the secondary devinfo will also be allocated and
- * initialized):
- */
- priv->reinit_3dd = emgddc_reinit_3dd;
- ret = emgddc_reinit_3dd(dev);
- if (ret != EMGD_OK) {
- emgddc_free_all_devinfos();
- return ret;
- }
-
- /* Remember the devinfo, for other functions that aren't passed it: */
- global_devinfo[0] = devinfo;
-
-
- EMGD_TRACE_EXIT;
- return EMGD_OK;
-
-} /* emgddc_init() */
-
-
-/**
- * Master de-initialization function. This is called when the EMGD DRM module
- * is being unloaded (it tells PVR services to exit, which calls this
- * function).
- *
- * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
- */
-emgd_error_t emgddc_deinit(void)
-{
- emgddc_devinfo_t *devinfo;
- int i;
- emgd_error_t ret = EMGD_OK;
-
- EMGD_TRACE_ENTER;
-
-
- for (i = 0 ; i < 2 ; i++) {
- devinfo = global_devinfo[i];
- if (devinfo == NULL) {
- continue;
- }
-
-
- /* Unhook and unregister from PVR services: */
- if (devinfo->pvr_jtable.pfnPVRSRVRemoveCmdProcList(devinfo->device_id,
- EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
- ret = EMGD_ERROR_GENERIC;
- }
- if (devinfo->pvr_jtable.pfnPVRSRVRemoveDCDevice(devinfo->device_id) !=
- PVRSRV_OK) {
- ret = EMGD_ERROR_GENERIC;
- }
-
-
- /* Delete any/all swap chains now: */
- /* Note: If we ever support interrupts, there may be a race condition
- * of pending flips. This was placed here, after the PVR services
- * thinks the driver has gone away, so that no flips should come by
- * this time.
- */
- while (devinfo->flipable_swapchains) {
- if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
- devinfo->flipable_swapchains)) {
- ret = EMGD_ERROR_GENERIC;
- }
- }
- while (devinfo->pixmap_swapchains) {
- if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
- devinfo->pixmap_swapchains)) {
- ret = EMGD_ERROR_GENERIC;
- }
- }
-
-
- emgddc_free_a_devinfo(devinfo);
- global_devinfo[i] = NULL;
- }
-
-
- EMGD_TRACE_EXIT;
- return ret;
-
-} /* emgddc_deinit() */
-
-
-/*
- * Potentially perform a mode change.
- *
- * If the X server is running, PVR services (including this function) can't
- * do mode changes. To avoid having to switch modes, ensure that the
- * current pixel format and dimension is specified:
- *
- * If the X server is NOT running, PVR services (including this function)
- * can do mode changes. In this case, if the pixel format and/or
- * dimensions don't match the current mode, perform a mode change (as long
- * as valid values are provided):
- */
-static PVRSRV_ERROR do_mode_change(igd_context_t *context,
- emgddc_devinfo_t *devinfo,
- drm_emgd_private *priv,
- DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib)
-{
- struct drm_device* drm_dev;
- int err = PVRSRV_OK;
-
- drm_dev = devinfo->drm_device;
-
- if (priv->xserver_running) {
- if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
- (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride) ||
- (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
- (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
- } else if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
- (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride)||
- (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
- (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
- unsigned long emgd_pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
- igd_display_info_t *mode_list = NULL;
- igd_display_info_t *mode = NULL;
- igd_display_info_t *desired_mode = NULL;
- int mode_flags = IGD_QUERY_LIVE_MODES;
- unsigned long byte_stride;
- igd_framebuffer_info_t primary_fb_info;
- igd_framebuffer_info_t secondary_fb_info;
- igd_display_h primary;
- igd_display_h secondary;
-
- printk("[EMGD] A mode change is requested. The following new values\n"
- "[EMGD] will be checked, and if good, take effect:\n");
- printk("[EMGD] pixel format = %u (PVR) = 0x%08lx (EMGD)\n",
- dst_surf_attrib->pixelformat, emgd_pf);
- printk("[EMGD] width = %lu, height = %lu\n",
- dst_surf_attrib->sDims.ui32Width,
- dst_surf_attrib->sDims.ui32Height);
- printk("[EMGD] stride = %lu\n",dst_surf_attrib->sDims.ui32ByteStride);
-
-
- /* Check the pixel format: */
- if (IGD_PF_UNKNOWN == emgd_pf) {
- printk(KERN_ERR "Unknown pixel format %u\n",
- dst_surf_attrib->pixelformat);
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
-
- /* Check the width, height, and stride: */
- EMGD_DEBUG("Calling query_mode_list()");
- err = context->dispatch.query_mode_list(context, priv->dc,
- &mode_list, mode_flags);
- if (err) {
- printk(KERN_ERR "The query_mode_list() function returned %d.", err);
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
- }
- EMGD_DEBUG("Comparing the mode list with the desired width, height, "
- "and stride...");
- mode = mode_list;
- while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
- byte_stride = IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
- EMGD_DEBUG(" ... Found a mode with width=%d, height=%d, "
- "refresh=%d;", mode->width, mode->height, mode->refresh);
- if ((mode->width == dst_surf_attrib->sDims.ui32Width) &&
- (mode->height == dst_surf_attrib->sDims.ui32Height) &&
- (byte_stride == dst_surf_attrib->sDims.ui32ByteStride)) {
- EMGD_DEBUG(" ... This mode is a match!");
- desired_mode = mode;
- break;
- }
- mode++;
- }
- if (NULL == desired_mode) {
- printk(KERN_ERR "No mode matching the desired width (%lu), height "
- "(%lu), and stride (%lu) was found.",
- dst_surf_attrib->sDims.ui32Width,
- dst_surf_attrib->sDims.ui32Height,
- dst_surf_attrib->sDims.ui32ByteStride);
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
- } else {
- /* Must set this in order to get the timings setup: */
- desired_mode->flags |= IGD_DISPLAY_ENABLE;
- }
-
-
- /* Make the mode change by calling alter_displays(): */
- primary_fb_info.width = desired_mode->width;
- primary_fb_info.height = desired_mode->height;
- primary_fb_info.pixel_format = emgd_pf;
- primary_fb_info.flags = 0;
- primary_fb_info.allocated = 0;
- memcpy(&secondary_fb_info, &primary_fb_info,
- sizeof(igd_framebuffer_info_t));
-
- EMGD_DEBUG("Calling alter_displays()");
- err = context->dispatch.alter_displays(context,
- &primary, desired_mode, &primary_fb_info,
- &secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
- if (err) {
- printk(KERN_ERR "The alter_displays() function returned %d.", err);
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
- }
-
-
- /* Update the private copy, like emgd_alter_displays() would do: */
- priv->primary = primary;
- priv->secondary = secondary;
- priv->primary_port_number = (priv->dc & 0xf0) >> 4;
- priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
-
-
- /* Re-initialize the display values: */
- err = priv->reinit_3dd(drm_dev);
- if (err != EMGD_OK) {
- printk(KERN_ERR "The reinit_3dd() function returned %d.", err);
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
- }
- } /* end of mode-change code */
-
- return err;
-} /* do_mode_change() */