1 /**********************************************************************
2 * Copyright (c) 2002-2010, Intel Corporation.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ******************************************************************************/
22 #define MODULE_NAME hal.pvr3dd
24 #include <linux/spinlock.h>
26 #include "drm_emgd_private.h"
29 #include "servicesext.h"
30 #include "kerneldisplay.h"
35 #if !defined(SUPPORT_DRI_DRM)
36 #error "SUPPORT_DRI_DRM must be set"
40 /* Function to get the PVR services jump table */
41 extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *jtable);
43 #ifdef SUPPORT_FB_EVENTS
44 static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo);
45 static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo);
46 #endif /* SUPPORT_FB_EVENTS */
47 static void flush_flip_queue(emgddc_swapchain_t *swap_chain);
48 static PVRSRV_ERROR do_mode_change(igd_context_t *context,
49 emgddc_devinfo_t *devinfo,
50 drm_emgd_priv_t *priv,
51 DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib);
54 /* Special value used to register with the PVR services command queue: */
55 #define EMGDDC_COMMAND_COUNT 1
59 * This is a pointer to the global emgddc_devinfo_t structure, used in various
62 static emgddc_devinfo_t *global_devinfo[] = {NULL, NULL};
66 * Pairs of equivalent pixel formats, in EMGD and PVR formats:
68 emgddc_pixelformat_translator_t known_pfs[] = {
69 /* 1 Byte-per-pixel [A]RGB Pixel Formats: */
70 {IGD_PF_ARGB8_INDEXED, PVRSRV_PIXEL_FORMAT_PAL8}, /* IMG numbered */
71 {IGD_PF_ARGB4_INDEXED, PVRSRV_PIXEL_FORMAT_PAL4}, /* IMG numbered */
73 /* 2 Byte-per-pixel [A]RGB Pixel Formats: */
74 {IGD_PF_ARGB16_4444, PVRSRV_PIXEL_FORMAT_ARGB4444}, /* IMG# & PVR2D-known */
75 {IGD_PF_ARGB16_1555, PVRSRV_PIXEL_FORMAT_ARGB1555}, /* IMG# & PVR2D-known */
76 {IGD_PF_RGB16_565, PVRSRV_PIXEL_FORMAT_RGB565}, /* IMG# & PVR2D-known */
77 {IGD_PF_xRGB16_555, PVRSRV_PIXEL_FORMAT_RGB555}, /* IMG numbered */
79 /* 3 Byte-per-pixel [A]RGB Pixel Formats: */
80 {IGD_PF_RGB24, PVRSRV_PIXEL_FORMAT_RGB888}, /* IMG numbered */
82 /* 4 Byte-per-pixel [A]RGB Pixel Formats: */
83 {IGD_PF_xRGB32_8888, PVRSRV_PIXEL_FORMAT_XRGB8888}, /* IMG numbered */
84 /* a.k.a. IGD_PF_ARGB32_8888 */
85 {IGD_PF_ARGB32, PVRSRV_PIXEL_FORMAT_ARGB8888}, /* IMG# & PVR2D-known */
86 {IGD_PF_xBGR32_8888, PVRSRV_PIXEL_FORMAT_XBGR8888}, /* IMG numbered */
87 {IGD_PF_ABGR32_8888, PVRSRV_PIXEL_FORMAT_ABGR8888}, /* IMG numbered */
89 /* YUV Packed Pixel Formats: */
90 {IGD_PF_YUV422_PACKED_YUY2, PVRSRV_PIXEL_FORMAT_YUY2},
91 {IGD_PF_YUV422_PACKED_YVYU, PVRSRV_PIXEL_FORMAT_YVYU},
92 {IGD_PF_YUV422_PACKED_UYVY, PVRSRV_PIXEL_FORMAT_UYVY},
93 {IGD_PF_YUV422_PACKED_VYUY, PVRSRV_PIXEL_FORMAT_VYUY},
95 {IGD_PF_YUV411_PACKED_Y41P, PVRSRV_PIXEL_FORMAT_UNKNOWN},
98 /* YUV Planar Pixel Formats: */
99 /* a.k.a. IGD_PF_YUV420_PLANAR_IYUV */
100 {IGD_PF_YUV420_PLANAR_I420, PVRSRV_PIXEL_FORMAT_I420},/* IMG numbered */
101 {IGD_PF_YUV420_PLANAR_YV12, PVRSRV_PIXEL_FORMAT_YV12},/* IMG numbered */
103 {IGD_PF_YUV410_PLANAR_YVU9, PVRSRV_PIXEL_FORMAT_UNKNOWN},
105 {IGD_PF_YUV420_PLANAR_NV12, PVRSRV_PIXEL_FORMAT_NV12},
107 unsigned int num_known_pfs =
108 sizeof(known_pfs) / sizeof(emgddc_pixelformat_translator_t);
112 * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
114 * @param emgd_pf (IN) EMGD-specific pixel format.
115 * @return Translated PVR-specific pixel format.
117 static unsigned long pvr2emgd_pf(PVRSRV_PIXEL_FORMAT pvr_pf)
120 for (i = 0 ; i < num_known_pfs ; i++) {
121 if (known_pfs[i].pvr_pf == pvr_pf) {
122 return known_pfs[i].emgd_pf;
126 /* If we get to here, we didn't find a known PVR pixel format: */
127 return IGD_PF_UNKNOWN;
132 * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
134 * @param emgd_pf (IN) EMGD-specific pixel format.
135 * @return Translated PVR-specific pixel format.
137 static PVRSRV_PIXEL_FORMAT emgd2pvr_pf(unsigned long emgd_pf)
140 for (i = 0 ; i < num_known_pfs ; i++) {
141 if (known_pfs[i].emgd_pf == emgd_pf) {
142 return known_pfs[i].pvr_pf;
146 /* If we get to here, we didn't find a known PVR pixel format: */
147 return IGD_PF_UNKNOWN;
152 * Determines if the user-space-provided pointer (to a devinfo) is valid.
154 * @param devinfo (IN) The user-space-provided pointer to a devinfo.
156 static int is_valid_devinfo(emgddc_devinfo_t *devinfo)
158 if ((devinfo == global_devinfo[0]) || (devinfo == global_devinfo[1])) {
163 } /* is_valid_devinfo() */
167 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnOpenDCDevice()
168 * function. This function is called when a client wants to use PVR services
169 * with the specified device.
171 * @param device_id (IN) The device_id associated with this device (i.e.
172 * obtained when emgddc_init() called
173 * PVRSRV_DC_DISP2SRV_KMJTABLE.pfnPVRSRVRegisterDCDevice()).
174 * @param device_h (OUT) The handle for this device (an opaque pointer to
176 * @param system_buffer_sync_data (IN) Sync data for this device's system
178 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
180 static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 device_id,
181 IMG_HANDLE *device_h,
182 PVRSRV_SYNC_DATA* system_buffer_sync_data)
184 emgddc_devinfo_t *devinfo;
189 UNREFERENCED_PARAMETER(device_id);
191 /* Look up the device (for DIH/Extended mode): */
192 if (device_id == global_devinfo[0]->device_id) {
193 devinfo = global_devinfo[0];
194 EMGD_DEBUG("devinfo = global_devinfo[0] = 0x%p", devinfo);
195 } else if (device_id == global_devinfo[1]->device_id) {
196 devinfo = global_devinfo[1];
197 EMGD_DEBUG("devinfo = global_devinfo[1] = 0x%p", devinfo);
199 printk(KERN_ERR "[EMGD] OpenDCDevice() called with unknown device ID "
201 return PVRSRV_ERROR_INVALID_DEVICE;
203 devinfo->system_buffer.sync_data = system_buffer_sync_data;
204 *device_h = (IMG_HANDLE) devinfo;
210 } /* OpenDCDevice() */
214 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCloseDCDevice()
215 * function. This function is called when a client is finished using PVR
216 * services with the specified device.
218 * @param device_h (IN) The handle for this device (an opaque pointer to
220 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
222 static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE device_h)
226 EMGD_DEBUG("device_h = 0x%p", device_h);
227 if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
228 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
229 __FUNCTION__, device_h);
230 return PVRSRV_ERROR_INVALID_PARAMS;
234 } /* CloseDCDevice() */
238 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCFormats()
239 * function. This function is called when a client wants to determine the
240 * pixel format currently being used with, and potentially, to determine which
241 * pixel formats can be used with the specified device. The first entry in the
242 * array is the current pixel format.
244 * Note: this function must be called twice. The first time, the formats
245 * parameter is set to NULL, and the client is trying to determine the number
246 * of pixel formats. The second time, the formats parameter is non-NULL, and
247 * points to enough memory for num_formats-worth of pixel formats. Note: this
248 * creates a small window of time between calls where a mode change could
249 * occur; the probability is considered so small, as to not be a worry.
251 * @param device_h (IN) The handle for this device (an opaque pointer to
253 * @param num_formats (OUT) The number of pixel formats for this device.
254 * @param format (IN/OUT) An array of the pixel formats for this device (ignore
256 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
258 static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE device_h,
259 IMG_UINT32 *num_formats,
260 DISPLAY_FORMAT *format)
262 emgddc_devinfo_t *devinfo;
265 EMGD_DEBUG("device_h = 0x%p", device_h);
268 if (!device_h || !num_formats) {
269 return PVRSRV_ERROR_INVALID_PARAMS;
272 devinfo = (emgddc_devinfo_t *) device_h;
273 if (!is_valid_devinfo(devinfo)) {
274 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
275 __FUNCTION__, devinfo);
276 return PVRSRV_ERROR_INVALID_PARAMS;
279 *num_formats = devinfo->num_formats;
284 for (i = 0 ; i < devinfo->num_formats ; i++) {
285 format[i] = devinfo->display_format_list[i];
293 } /* EnumDCFormats() */
297 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCDims() function.
298 * This function is called when a client wants to determine the current
299 * dimensions (similar to an EMGD mode, but just the dimensions) of, and
300 * potentially, to determine the possible dimensions that can be used with this
301 * device. The first entry in the array is the current dimension.
303 * Note: this function must be called twice. The first time, the dims
304 * parameter is set to NULL, and the client is trying to determine the number
305 * of dimensions. The second time, the dims parameter is non-NULL, and points
306 * to enough memory for num_dims-worth of dimensions. Note: this
307 * creates a small window of time between calls where a mode change could
308 * occur; the probability is considered so small, as to not be a worry.
310 * @param device_h (IN) The handle for this device (an opaque pointer to
312 * @param format (IN) A pointer to a pixel format (unused).
313 * @param num_dims (OUT) The number of dimensions for this device.
314 * @param dims (IN/OUT) An array of the dimensions for this device (ignore
316 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
318 static PVRSRV_ERROR EnumDCDims(IMG_HANDLE device_h,
319 DISPLAY_FORMAT *format,
320 IMG_UINT32 *num_dims,
323 emgddc_devinfo_t *devinfo;
326 EMGD_DEBUG("device_h = 0x%p", device_h);
329 if (!device_h || !format || !num_dims) {
330 return PVRSRV_ERROR_INVALID_PARAMS;
333 devinfo = (emgddc_devinfo_t *) device_h;
334 if (!is_valid_devinfo(devinfo)) {
335 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
336 __FUNCTION__, devinfo);
337 return PVRSRV_ERROR_INVALID_PARAMS;
340 *num_dims = devinfo->num_dims;
345 for (i = 0 ; i < devinfo->num_dims ; i++) {
346 dims[i] = devinfo->display_dim_list[i];
358 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCSystemBuffer()
359 * function. This function returns a handle to the system buffer
360 * (a.k.a. "frame buffer" or "front buffer") of the specified device. The
361 * handle is an opaque pointer to the buffer.
363 * @param device_h (IN) The handle for this device (an opaque pointer to
365 * @param buffer_h (OUT) The handle for this buffer (an opaque pointer to
366 * devinfo->system_buffer).
367 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
369 static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE device_h, IMG_HANDLE *buffer_h)
371 emgddc_devinfo_t *devinfo;
374 EMGD_DEBUG("device_h = 0x%p", device_h);
377 if (!device_h || !buffer_h) {
378 return PVRSRV_ERROR_INVALID_PARAMS;
381 devinfo = (emgddc_devinfo_t *) device_h;
382 if (!is_valid_devinfo(devinfo)) {
383 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
384 __FUNCTION__, devinfo);
385 return PVRSRV_ERROR_INVALID_PARAMS;
388 *buffer_h = (IMG_HANDLE) &devinfo->system_buffer;
394 } /* GetDCSystemBuffer() */
398 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCInfo() function.
399 * This function returns a pointer to the DISPLAY_INFO structure associated
400 * with this device, which contains the driver's name, and information about
401 * swap chains that can be created (i.e. all static information).
403 * @param device_h (IN) The handle for this device (an opaque pointer to
405 * @param dc_info (OUT) The DISPLAY_INFO structure associated with this device.
406 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
408 static PVRSRV_ERROR GetDCInfo(IMG_HANDLE device_h, DISPLAY_INFO *dc_info)
410 emgddc_devinfo_t *devinfo;
413 EMGD_DEBUG("device_h = 0x%p", device_h);
416 if (!device_h || !dc_info) {
417 return PVRSRV_ERROR_INVALID_PARAMS;
420 devinfo = (emgddc_devinfo_t *) device_h;
421 if (!is_valid_devinfo(devinfo)) {
422 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
423 __FUNCTION__, devinfo);
424 return PVRSRV_ERROR_INVALID_PARAMS;
427 *dc_info = devinfo->display_info;
437 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBufferAddr()
440 * @param device_h (IN) The handle for this device (an opaque pointer to
442 * @param buffer_h (IN) The handle of a buffer (an opaque pointer to an
443 * emgddc_buffer_t) to return information of.
444 * @param phys_addr (OUT) A pointer to an array pointer of page addresses of
445 * the buffer. For many devices, this would be a pointer to the physical
446 * address of a contiguous set of memory associated with the buffer, but since
447 * EMGD doesn't use contiguous memory for a buffer, it returns the array of
449 * @param fb_size (OUT) The size (in bytes) of the buffer.
450 * @param virt_addr (OUT) A pointer to the virtual address (in kernel space) of
452 * @param os_map_info_h (OUT) Ununsed by PVR services.
453 * @param is_contiguous (OUT) A pointer to a boolean that is set to IMG_FALSE,
454 * because EMGD uses non-contiguous pages of memory for buffers.
455 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
457 static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE device_h,
459 IMG_SYS_PHYADDR **phys_addr,
461 IMG_VOID **virt_addr,
462 IMG_HANDLE *os_map_info_h,
463 IMG_BOOL *is_contiguous)
465 emgddc_devinfo_t *devinfo;
466 igd_context_t *context;
467 emgddc_buffer_t *system_buffer;
468 unsigned long page_count = 0;
472 EMGD_DEBUG("device_h = 0x%p", device_h);
476 printk(KERN_ERR "[EMGD] %s() Null device handle.\n", __FUNCTION__);
477 return PVRSRV_ERROR_INVALID_PARAMS;
480 devinfo = (emgddc_devinfo_t *) device_h;
481 if (!is_valid_devinfo(devinfo)) {
482 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
483 __FUNCTION__, devinfo);
484 return PVRSRV_ERROR_INVALID_PARAMS;
487 context = devinfo->priv->context;
488 if (!context || (context->dispatch.gmm_get_page_list == NULL)) {
489 printk(KERN_ERR "[EMGD] %s() HAL not configured.\n", __FUNCTION__);
490 return PVRSRV_ERROR_INVALID_PARAMS;
494 printk(KERN_ERR "[EMGD] %s() Null buffer handle.\n", __FUNCTION__);
495 return PVRSRV_ERROR_INVALID_PARAMS;
498 system_buffer = (emgddc_buffer_t *) buffer_h;
501 return PVRSRV_ERROR_INVALID_PARAMS;
504 EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
505 EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
507 if ((ret = context->dispatch.gmm_get_page_list(system_buffer->offset,
508 (unsigned long **) phys_addr, &page_count)) != 0) {
509 printk(KERN_ERR"Cannot get the page addresses for the buffer at offset "
510 "0x%08lx\n", system_buffer->offset);
512 return PVRSRV_ERROR_OUT_OF_MEMORY;
514 EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
515 EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
516 EMGD_DEBUG(" (*phys_addr)->uiAddr = 0x%lx", (*phys_addr)->uiAddr);
519 return PVRSRV_ERROR_INVALID_PARAMS;
523 *fb_size = (IMG_UINT32) system_buffer->size;
524 EMGD_DEBUG(" fb_size = 0x%lx", *fb_size);
528 *virt_addr = system_buffer->virt_addr;
529 EMGD_DEBUG(" virt_addr = 0x%p", *virt_addr);
532 /* Note: this value is ignored by the PVR services code: */
534 *os_map_info_h = (IMG_HANDLE)system_buffer->offset;
535 EMGD_DEBUG(" os_map_info_h = 0x%p", *os_map_info_h);
539 * Other than cursor, memory allocations are not contiguous pages
542 if(system_buffer->is_contiguous == IMG_TRUE)
543 { *is_contiguous = IMG_TRUE;
547 *is_contiguous = IMG_FALSE;
555 } /* GetDCBufferAddr() */
559 * Determines if the user-space-provided pointers (to a devinfo and swap chain)
562 * @param devinfo (IN) The user-space-provided pointer to a devinfo.
563 * @param swap_chain (IN) The swap chain to add to the list.
564 * @param must_be_flipable (IN) Non-zero if swap_chain must be flip-able.
565 * @return non-zero if valid, zero if not.
567 static int is_valid_swap_chain(emgddc_devinfo_t *devinfo,
568 emgddc_swapchain_t *swap_chain, int must_be_flipable)
570 if (!is_valid_devinfo(devinfo)) {
573 /* Search both lists for this swap chain: */
574 emgddc_swapchain_t *swap = devinfo->flipable_swapchains;
576 if (swap == swap_chain) {
581 if (!must_be_flipable) {
582 swap = devinfo->pixmap_swapchains;
584 if (swap == swap_chain) {
591 /* We didn't find this swap chain pointer, so it's not valid: */
593 } /* is_valid_swap_chain() */
597 * Called by CreateDCSwapChain() to add a new swap chain to one of the lists of
600 * @param list (IN) A pointer to a list of swap chains.
601 * @param swap_chain (IN) The swap chain to add to the list.
603 static void add_swap_chain_to_list(emgddc_swapchain_t **list,
604 emgddc_swapchain_t *swap_chain)
606 /* It's simplest to add to the front of the list: */
610 swap_chain->next = *list;
613 } /* add_swap_chain_to_list() */
617 * Called by DestroyDCSwapChain() to remove an about-to-be-deleted swap chain
618 * from one of the lists of swap chains.
620 * @param list (IN) A pointer to a list of swap chains.
621 * @param swap_chain (IN) The swap chain to remove from the list.
623 static void remove_swap_chain_from_list(emgddc_swapchain_t **list,
624 emgddc_swapchain_t *swap_chain)
626 emgddc_swapchain_t *swap, *prev;
631 if (swap == swap_chain) {
636 prev->next = swap->next;
643 } /* remove_swap_chain_from_list() */
647 * Called by either CreateDCSwapChain() or DestroyDCSwapChain() to free all GMM
648 * and kernel space memory memory of the specified swap chain.
650 * @param swap_chain (IN) The swap chain to free.
651 * @param context (IN) The EMGD context to use to call gmm_free().
653 static void free_swap_chain(emgddc_swapchain_t *swap_chain,
654 igd_context_t *context)
656 emgddc_buffer_t *buffers;
660 * Free and unmap the buffers. Must ensure that the HAL is running before
661 * calling it, and ensure that we don't free/unmap the first buffer if is
662 * actually the frame buffer.
664 if (swap_chain->devinfo->priv->hal_running) {
665 buffers = swap_chain->buffers;
667 for (i = 0 ; i < swap_chain->buffer_count ; i++) {
668 if(!buffers[i].is_contiguous){
669 if (!buffers[i].is_fb) {
670 if (buffers[i].virt_addr) {
671 context->dispatch.gmm_unmap(buffers[i].virt_addr);
673 if (buffers[i].offset) {
674 context->dispatch.gmm_free(buffers[i].offset);
679 context->dispatch.gmm_unmap_ci((unsigned long)buffers[i].virt_addr);
685 if (swap_chain->flip_queue) {
686 OS_FREE(swap_chain->flip_queue);
688 OS_FREE(swap_chain->buffers);
692 } /* free_swap_chain() */
696 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCreateDCSwapChain()
697 * function. This function was originally designed to create a flip-able swap
698 * chain on the specified device, but has also been augmented to allow the X
699 * driver to create pixmaps or other buffers in GTT memory. A flip-able swap
700 * chain consists of a front buffer (the "system buffer, a.k.a. the "frame
701 * buffer") and one or more back buffers (therefore, the number of buffers
702 * includes the frame buffer).
704 * Note: Only full-screen flipping is supported (the hardware is pointed at one
705 * complete buffer at a time). There is no support for the
706 * SetDC{Src|Dst}Rect() functions to define a smaller region of the display for
707 * the buffers/flipping.
709 * Note: The DDK documentation says that the mode should be changed if the
710 * dimensions and pixel format do not match the current dimensions and pixel
711 * format. However, this can only be supported if the X server isn't running
712 * (which is in charge of changing modes when it is running). If the X server
713 * is running, an error is returned unless the current dimensions and pixel
714 * format are specified.
716 * @param device_h (IN) The handle for this device (an opaque pointer to
718 * @param flags (IN) Unused.
719 * @param dst_surf_attrib (IN) While not described in the DDK documentation,
720 * this presumably specifies the desired dimensions and pixel format of the
722 * @param src_surf_attrib (IN) Specifies the desired dimensions and pixel
723 * format of the back buffers.
724 * @param buffer_count (IN) Number of buffers required in this swap chain.
725 * @param sync_data (IN) While not described in the DDK documentation,
726 * this is an array of sync data for each buffer.
727 * @param oem_flags (IN) Unused.
728 * @param swap_chain_h (OUT) The handle for this swap chain (an opaque pointer
729 * to a emgddc_swapchain_t).
730 * @param swap_chain_id (OUT) Unused.
731 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
733 static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE device_h,
735 DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib,
736 DISPLAY_SURF_ATTRIBUTES *src_surf_attrib,
737 IMG_UINT32 buffer_count,
738 PVRSRV_SYNC_DATA **sync_data,
739 IMG_UINT32 oem_flags,
740 IMG_HANDLE *swap_chain_h,
741 IMG_UINT32 *swap_chain_id)
743 emgddc_devinfo_t *devinfo;
744 emgddc_swapchain_t *swap_chain;
745 emgddc_buffer_t *buffers;
747 emgddc_flip_queue_item_t *flip_queue = NULL;
748 unsigned long lock_flags;
750 struct drm_device* drm_dev;
751 drm_emgd_priv_t *priv;
752 igd_context_t *context;
753 igd_dispatch_t *dispatch;
756 IMG_UINT32 ci_offset=0;
760 EMGD_DEBUG("device_h = 0x%p, buffer_count = %lu", device_h, buffer_count);
761 EMGD_DEBUG("flags = 0x%08lx, oem_flags = 0x%08lx", flags, oem_flags);
763 if(flags & PVR2D_CREATE_FLIPCHAIN_CI)
765 ci_offset = src_surf_attrib->ui32Reseved;
770 * Check the parameters and dependencies:
772 if (!device_h || !dst_surf_attrib || !src_surf_attrib || !sync_data ||
774 return PVRSRV_ERROR_INVALID_PARAMS;
778 * The oem_flags will determine what type of swapchain this is. The
779 * following types are for a non-flip-able swap chain (e.g. for a pixmap):
781 * PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY - General purpose displayable
782 * PVR2D_CREATE_FLIPCHAIN_OEMGENERAL - General purpose non-displayable
783 * PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY - Overlay
785 * Currently, if none of these flags are set, assume this is going
786 * to create a set of back buffers, or a "flip-able" swap chain:
788 * PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN - Flip-able buffers
790 /* Is this is an OEM call (I.E. allocating a buffer)? */
791 if ((oem_flags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
792 PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
793 PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY |
794 PVR2D_CREATE_FLIPCHAIN_CI))) {
799 * If this is suppose to be an actual flip-able swap chain, then
800 * make sure there are at least 2 buffers.
802 if (buffer_count < 2) {
803 return PVRSRV_ERROR_TOO_FEW_BUFFERS;
809 devinfo = (emgddc_devinfo_t *) device_h;
810 if (!is_valid_devinfo(devinfo)) {
811 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
812 __FUNCTION__, devinfo);
813 return PVRSRV_ERROR_INVALID_PARAMS;
815 drm_dev = devinfo->drm_device;
816 priv = drm_dev->dev_private;
817 context = priv->context;
818 dispatch = &(context->dispatch);
821 if (buffer_count > devinfo->display_info.ui32MaxSwapChainBuffers) {
822 return PVRSRV_ERROR_TOOMANYBUFFERS;
825 /* Ensure the source & destination attributes match each other: */
826 if ((dst_surf_attrib->pixelformat != src_surf_attrib->pixelformat) ||
827 (dst_surf_attrib->sDims.ui32ByteStride !=
828 src_surf_attrib->sDims.ui32ByteStride) ||
829 (dst_surf_attrib->sDims.ui32Width != src_surf_attrib->sDims.ui32Width)||
830 (dst_surf_attrib->sDims.ui32Height !=
831 src_surf_attrib->sDims.ui32Height)) {
832 return PVRSRV_ERROR_INVALID_PARAMS;
837 do_mode_change(context, devinfo, priv, dst_surf_attrib);
838 if (err != PVRSRV_OK) {
839 EMGD_DEBUG("Exiting early because of an error in do_mode_change()");
846 * Allocate data structures:
848 swap_chain = (emgddc_swapchain_t *) OS_ALLOC(sizeof(emgddc_swapchain_t));
850 EMGD_ERROR_EXIT("Can not allocate memory for a swap chain");
851 return PVRSRV_ERROR_OUT_OF_MEMORY;
853 OS_MEMSET(swap_chain, 0, sizeof(emgddc_swapchain_t));
855 buffers = (emgddc_buffer_t *) OS_ALLOC(sizeof(emgddc_buffer_t) *
859 EMGD_ERROR_EXIT("Can not allocate memory for swap chain buffers");
860 return PVRSRV_ERROR_OUT_OF_MEMORY;
862 OS_MEMSET(buffers, 0, sizeof(emgddc_buffer_t) * buffer_count);
865 flip_queue = (emgddc_flip_queue_item_t *)
866 OS_ALLOC(sizeof(emgddc_flip_queue_item_t) * buffer_count);
870 EMGD_ERROR_EXIT("Can not allocate memory for flip queue");
871 return PVRSRV_ERROR_OUT_OF_MEMORY;
873 OS_MEMSET(flip_queue, 0,
874 sizeof(emgddc_flip_queue_item_t) * buffer_count);
878 * Initialize data structures:
880 swap_chain->devinfo = devinfo;
881 swap_chain->valid = EMGD_TRUE;
882 swap_chain->buffer_count = (unsigned long) buffer_count;
883 swap_chain->buffers = buffers;
884 swap_chain->flags = flags;
885 swap_chain->next = NULL;
887 swap_chain->flip_queue = flip_queue;
888 swap_chain->insert_index = 0;
889 swap_chain->remove_index = 0;
891 swap_chain->pvr_jtable = &devinfo->pvr_jtable;
893 /* Link the buffers of the swap chain: */
894 for (i = 0 ; i < buffer_count-1 ; i++) {
895 buffers[i].next = &buffers[i+1];
897 buffers[i].next = &buffers[0];
901 /* The first buffer is the frame buffer (a.k.a. the front buffer). */
902 buffers[i].priv = priv;
903 buffers[i].offset = devinfo->system_buffer.offset;
904 buffers[i].pixel_format = devinfo->system_buffer.pixel_format;
905 buffers[i].width = devinfo->system_buffer.width;
906 buffers[i].height = devinfo->system_buffer.height;
907 buffers[i].pitch = devinfo->system_buffer.pitch;
908 buffers[i].size = devinfo->system_buffer.size;
909 buffers[i].virt_addr = devinfo->system_buffer.virt_addr;
910 buffers[i].sync_data = sync_data[0];
911 buffers[i].is_fb = 1;
912 swap_chain->flags |= PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN;
917 * Allocate memory for the buffers
919 for (; i < buffer_count ; i++) {
920 unsigned long offset;
921 unsigned long virt_addr;
922 unsigned int width = 0;
923 unsigned int height = 0;
924 unsigned int pitch = 0;
925 unsigned long size = 0;
927 unsigned long flags = IGD_SURFACE_RENDER;
929 unsigned int map_method=1; /*1: gtt map by va driver*/
931 if (!(oem_flags & PVR2D_CREATE_FLIPCHAIN_OEMGENERAL)) {
932 flags |= IGD_SURFACE_DISPLAY;
935 buffers[i].priv = priv;
938 * What should be used for the surface attributes, the source
939 * surface attributes or the destination surface attributes?
940 * Can we assume that source is the surface requested?
942 pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
943 width = dst_surf_attrib->sDims.ui32Width;
944 height = dst_surf_attrib->sDims.ui32Height;
945 pitch = dst_surf_attrib->sDims.ui32ByteStride;
946 flags |= IGD_MIN_PITCH;
948 if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
949 if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI_V4L2_MAP)
954 ret = dispatch->gmm_map_ci(&offset,
962 free_swap_chain(swap_chain, context);
963 EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
964 return PVRSRV_ERROR_OUT_OF_MEMORY;
966 buffers[i].is_contiguous = IMG_TRUE;
971 ret = dispatch->gmm_alloc_surface(&offset,
975 IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
977 free_swap_chain(swap_chain, context);
978 EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
979 return PVRSRV_ERROR_OUT_OF_MEMORY;
981 buffers[i].is_contiguous = IMG_FALSE;
984 dst_surf_attrib->sDims.ui32ByteStride = pitch;
985 src_surf_attrib->sDims.ui32ByteStride = pitch;
987 buffers[i].pixel_format = pf;
988 buffers[i].width = width;
989 buffers[i].height = height;
990 buffers[i].pitch = pitch;
991 buffers[i].size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
993 buffers[i].offset = offset;
995 if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
997 buffers[i].virt_addr = (IMG_CPU_VIRTADDR)virt_addr;
1000 buffers[i].virt_addr = dispatch->gmm_map(offset);
1001 buffers[i].sync_data = sync_data[i];
1002 buffers[i].is_fb = 0;
1007 /* Initialize what's needed for flip-able swap chains: */
1010 for (i = 0 ; i < buffer_count ; i++) {
1011 flip_queue[i].valid = EMGD_FALSE;
1012 flip_queue[i].flipped = EMGD_FALSE;
1013 flip_queue[i].cmd_completed = EMGD_FALSE;
1016 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1018 must_enable = (devinfo->flipable_swapchains == NULL) ? 1 : 0;
1020 /* Add this swap chain to the list of flip-able swap chains: */
1021 add_swap_chain_to_list(&devinfo->flipable_swapchains, swap_chain);
1023 /* Unlock here (before enabling interrupts), to prevent deadlock: */
1024 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1026 if (!devinfo->flush_commands) {
1028 /* Enable interrupts for vblanks: */
1029 if (!devinfo->interrupt_h || dispatch->
1030 enable_vblank_callback(devinfo->interrupt_h)) {
1031 /* For some reason (rare), interrupts weren't enabled: */
1032 EMGD_ERROR_EXIT("Can not enable VBlank interrupts! "
1033 "Therefore, cannot do buffer flipping!");
1034 /* Properly clean up: */
1035 remove_swap_chain_from_list(&devinfo->flipable_swapchains,
1037 free_swap_chain(swap_chain, context);
1038 return PVRSRV_ERROR_BAD_MAPPING;
1040 devinfo->flipping_disabled = EMGD_FALSE;
1045 #ifdef SUPPORT_FB_EVENTS
1047 /* Enable fb events: */
1048 if (enable_event_notification(devinfo)!= EMGD_OK) {
1049 EMGD_ERROR_EXIT("Can not enable framebuffer event "
1051 /* Properly clean up: */
1052 if (devinfo->interrupt_h) {
1053 dispatch->disable_vblank_callback(
1054 devinfo->interrupt_h);
1056 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1057 remove_swap_chain_from_list(&devinfo->flipable_swapchains,
1059 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1060 free_swap_chain(swap_chain, context);
1061 return PVRSRV_ERROR_BAD_MAPPING;
1064 #endif /* SUPPORT_FB_EVENTS */
1066 /* Add this swap chain to the list of pixmap swap chains: */
1067 add_swap_chain_to_list(&devinfo->pixmap_swapchains, swap_chain);
1071 *swap_chain_id = ++devinfo->swap_chain_id_counter;
1072 *swap_chain_h = (IMG_HANDLE) swap_chain;
1073 EMGD_DEBUG("swap_chain_h = 0x%p, *swap_chain_id = %lu",
1074 swap_chain_h, *swap_chain_id);
1079 } /* CreateDCSwapChain() */
1083 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnDestroyDCSwapChain()
1086 * @param device_h (IN) The handle for this device (an opaque pointer to
1088 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1089 * to a emgddc_swapchain_t).
1090 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1092 static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE device_h,
1093 IMG_HANDLE swap_chain_h)
1095 emgddc_devinfo_t *devinfo;
1096 drm_emgd_priv_t *priv;
1097 igd_context_t *context;
1098 igd_dispatch_t *dispatch;
1099 emgddc_swapchain_t *swap_chain;
1100 unsigned long lock_flags;
1101 #ifdef SUPPORT_FB_EVENTS
1103 #endif /* SUPPORT_FB_EVENTS */
1106 EMGD_DEBUG("device_h = 0x%p", device_h);
1109 if (!device_h || !swap_chain_h) {
1110 return PVRSRV_ERROR_INVALID_PARAMS;
1113 devinfo = (emgddc_devinfo_t *) device_h;
1114 priv = devinfo->priv;
1115 context = priv->context;
1116 dispatch = &(context->dispatch);
1117 swap_chain = (emgddc_swapchain_t *) swap_chain_h;
1118 if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
1119 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
1120 "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
1121 return PVRSRV_ERROR_INVALID_PARAMS;
1124 /* Remove swap chain from the appropriate list: */
1125 if (swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN) {
1126 /* De-initialize what's needed for flip-able swap chains: */
1128 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1130 ((devinfo->flipable_swapchains == swap_chain) &&
1131 (devinfo->flipable_swapchains->next == NULL)) ? 1 : 0;
1133 /* Remove this swap chain from the list of flip-able swap chains: */
1134 remove_swap_chain_from_list(&devinfo->flipable_swapchains, swap_chain);
1136 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1138 #ifdef SUPPORT_FB_EVENTS
1140 /* Disable fb events: */
1141 error = disable_event_notification(devinfo);
1142 if (error != EMGD_OK) {
1143 EMGD_ERROR("Could not disable framebuffer event notification");
1146 #endif /* SUPPORT_FB_EVENTS */
1148 /* Disable interrupts for vblanks: */
1150 if (devinfo->interrupt_h) {
1151 dispatch->disable_vblank_callback(devinfo->interrupt_h);
1155 /* Flush any pending flips: */
1156 flush_flip_queue(swap_chain);
1158 /* Flip back to the system buffer: */
1159 emgddc_flip(swap_chain, &devinfo->system_buffer);
1161 /* Remove this swap chain from the list of pixmap swap chains: */
1162 remove_swap_chain_from_list(&devinfo->pixmap_swapchains, swap_chain);
1165 /* Free all GMM and kernel space memory for this swap chain: */
1166 free_swap_chain(swap_chain, context);
1171 } /* DestroyDCSwapChain() */
1175 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstRect()
1178 * @param device_h (IN) The handle for this device (an opaque pointer to
1180 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1181 * to a emgddc_swapchain_t).
1182 * @param rect (IN) Unused.
1183 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1185 static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE device_h,
1186 IMG_HANDLE swap_chain_h,
1189 UNREFERENCED_PARAMETER(device_h);
1190 UNREFERENCED_PARAMETER(swap_chain_h);
1191 UNREFERENCED_PARAMETER(rect);
1195 return PVRSRV_ERROR_NOT_SUPPORTED;
1200 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcRect()
1203 * @param device_h (IN) The handle for this device (an opaque pointer to
1205 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1206 * to a emgddc_swapchain_t).
1207 * @param rect (IN) Unused.
1208 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1210 static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE device_h,
1211 IMG_HANDLE swap_chain_h,
1214 UNREFERENCED_PARAMETER(device_h);
1215 UNREFERENCED_PARAMETER(swap_chain_h);
1216 UNREFERENCED_PARAMETER(rect);
1220 return PVRSRV_ERROR_NOT_SUPPORTED;
1225 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstColourKey()
1228 * @param device_h (IN) The handle for this device (an opaque pointer to
1230 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1231 * to a emgddc_swapchain_t).
1232 * @param color (IN) Unused.
1233 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1235 static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE device_h,
1236 IMG_HANDLE swap_chain_h,
1239 UNREFERENCED_PARAMETER(device_h);
1240 UNREFERENCED_PARAMETER(swap_chain_h);
1241 UNREFERENCED_PARAMETER(color);
1245 return PVRSRV_ERROR_NOT_SUPPORTED;
1250 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcColourKey()
1253 * @param device_h (IN) The handle for this device (an opaque pointer to
1255 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1256 * to a emgddc_swapchain_t).
1257 * @param color (IN) Unused.
1258 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1260 static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE device_h,
1261 IMG_HANDLE swap_chain_h,
1264 UNREFERENCED_PARAMETER(device_h);
1265 UNREFERENCED_PARAMETER(swap_chain_h);
1266 UNREFERENCED_PARAMETER(color);
1270 return PVRSRV_ERROR_NOT_SUPPORTED;
1275 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBuffers()
1278 * @param device_h (IN) The handle for this device (an opaque pointer to
1280 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1281 * to a emgddc_swapchain_t).
1282 * @param buffer_count (OUT) The number of buffers in the specified swap chain.
1283 * @param buffer_h (IN/OUT) An array of buffer handles (an opaque pointer to a
1284 * emgddc_buffer_t) in the specified swap chain (memory must be allocated by
1286 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1288 static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE device_h,
1289 IMG_HANDLE swap_chain_h,
1290 IMG_UINT32 *buffer_count,
1291 IMG_HANDLE *buffer_h)
1293 emgddc_devinfo_t *devinfo;
1294 emgddc_swapchain_t *swap_chain;
1298 EMGD_DEBUG("device_h = 0x%p", device_h);
1301 if (!device_h || !swap_chain_h || !buffer_count || !buffer_h) {
1302 return PVRSRV_ERROR_INVALID_PARAMS;
1305 devinfo = (emgddc_devinfo_t *) device_h;
1306 swap_chain = (emgddc_swapchain_t *) swap_chain_h;
1307 if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
1308 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
1309 "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
1310 return PVRSRV_ERROR_INVALID_PARAMS;
1313 *buffer_count = (IMG_UINT32) swap_chain->buffer_count;
1315 for (i = 0 ; i < swap_chain->buffer_count ; i++) {
1316 buffer_h[i] = (IMG_HANDLE) &swap_chain->buffers[i];
1323 } /* GetDCBuffers() */
1327 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCBuffer()
1328 * function. This function is supposed to cause a flip to the specified
1329 * buffer. However, it is no longer called by PVR services!
1331 * NOTE: As can be seen, this function was never completely implemented
1332 * (i.e. in the DDK used to create this version). This is because the PVR code
1333 * doesn't call this function. Instead, it calls emgddc_process_flip().
1335 * @param device_h (IN) The handle for this device (an opaque pointer to
1337 * @param buffer_h (IN) The handle for this buffer (an opaque pointer to a
1339 * @param swap_interval (IN) Unused.
1340 * @param private_tag_h (IN) Unused.
1341 * @param clip_rect_count (IN) Largely unused.
1342 * @param clip_rect (IN) Unused.
1343 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1345 static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE device_h,
1346 IMG_HANDLE buffer_h,
1347 IMG_UINT32 swap_interval,
1348 IMG_HANDLE private_tag_h,
1349 IMG_UINT32 clip_rect_count,
1350 IMG_RECT *clip_rect)
1352 /* This function is never called by PVR services, and so it is stubbed: */
1353 UNREFERENCED_PARAMETER(device_h);
1354 UNREFERENCED_PARAMETER(buffer_h);
1355 UNREFERENCED_PARAMETER(swap_interval);
1356 UNREFERENCED_PARAMETER(private_tag_h);
1357 UNREFERENCED_PARAMETER(clip_rect_count);
1358 UNREFERENCED_PARAMETER(clip_rect);
1361 return PVRSRV_ERROR_NOT_SUPPORTED;
1363 } /* SwapToDCBuffer() */
1367 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCSystem()
1368 * function. This function causes a flip to the "system buffer" (a.k.a. frame
1371 * @param device_h (IN) The handle for this device (an opaque pointer to
1373 * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
1374 * to a emgddc_swapchain_t).
1375 * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1377 static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE device_h,
1378 IMG_HANDLE swap_chain_h)
1380 emgddc_devinfo_t *devinfo;
1381 emgddc_swapchain_t *swap_chain;
1382 unsigned long lock_flags;
1385 EMGD_DEBUG("device_h = 0x%p", device_h);
1388 if (!device_h || !swap_chain_h) {
1389 return PVRSRV_ERROR_INVALID_PARAMS;
1392 devinfo = (emgddc_devinfo_t *) device_h;
1393 swap_chain = (emgddc_swapchain_t *) swap_chain_h;
1394 if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
1395 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
1396 "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
1397 return PVRSRV_ERROR_INVALID_PARAMS;
1399 /* This must be a flip-able swap chain, or we can't cause a flip for it: */
1400 if (!(swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN)) {
1401 return PVRSRV_ERROR_INVALID_PARAMS;
1404 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1406 flush_flip_queue(swap_chain);
1407 emgddc_flip(swap_chain, &devinfo->system_buffer);
1409 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1415 } /* SwapToDCSystem() */
1419 * Drains the circular queue of buffers to flip for a specified swap chain.
1420 * The queue is processed in order. For every item in the queue, processing is
1423 * - An item that has been "completed" (i.e. PVR services has been told that
1424 * the flip occured), but hasn't reached the end of its swap interval, is
1425 * immediately ended and cleared.
1427 * - An item that has been flipped, but hasn't been "completed" with PVR
1428 * services, is "completed," ended, and cleared.
1430 * - An item that has been queued, but hasn't been flipped, is immediately
1431 * flipped (i.e. given the Poulsbo hardware, this really means that the
1432 * hardware is told to flip them at the start of the next vertical blanking
1433 * period), "completed," ended, and cleared.
1435 * Note: This function assumes that the calling function has already obtained
1438 * @param swap_chain (IN) The swap chain to flush the queue for.
1440 static void flush_flip_queue(emgddc_swapchain_t *swap_chain)
1442 emgddc_flip_queue_item_t *flip_item;
1443 unsigned long max_index;
1449 /* Get the first item to drain in the circular queue: */
1450 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1451 max_index = swap_chain->buffer_count - 1;
1453 for (i = 0 ; i < swap_chain->buffer_count ; i++) {
1454 if (flip_item->valid == EMGD_FALSE) {
1458 EMGD_DEBUG("Flushing buffer offset=0x%lx", flip_item->buffer->offset);
1460 if ((swap_chain->devinfo->flipping_disabled == EMGD_FALSE) &&
1461 (flip_item->flipped == EMGD_FALSE) &&
1462 (swap_chain->valid == EMGD_TRUE)) {
1463 EMGD_DEBUG("Flipping to buffer offset=0x%lx",
1464 flip_item->buffer->offset);
1465 emgddc_flip(swap_chain, flip_item->buffer);
1468 if (flip_item->cmd_completed == EMGD_FALSE) {
1469 PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
1471 EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
1472 flip_item->buffer->offset);
1473 pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete, IMG_TRUE);
1476 /* We're done with this item in the queue. Prepare for processing the
1479 flip_item->flipped = EMGD_FALSE;
1480 flip_item->cmd_completed = EMGD_FALSE;
1481 flip_item->valid = EMGD_FALSE;
1483 /* Point to the next item in the circular queue: */
1484 swap_chain->remove_index++;
1485 if (swap_chain->remove_index > max_index) {
1486 swap_chain->remove_index = 0;
1489 /* Get the next item in the circular queue: */
1490 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1493 /* Reset the circular queue to the start: */
1494 swap_chain->insert_index = 0;
1495 swap_chain->remove_index = 0;
1500 } /* flush_flip_queue() */
1503 static void set_flush_state_internal_nolock(emgddc_devinfo_t* devinfo,
1504 emgd_bool flush_state)
1506 emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
1512 if (devinfo->set_flush_state_ref_count == 0) {
1513 /* Don't actually disable interrupts. Just set a flag so that
1514 * buffer flips won't be queued, then flush the circular buffer of
1515 * all pending flips, for all swap chains:
1517 devinfo->flush_commands = EMGD_TRUE;
1518 while (swap_chain != NULL) {
1519 flush_flip_queue(swap_chain);
1520 swap_chain = swap_chain->next;
1523 devinfo->set_flush_state_ref_count++;
1525 if (devinfo->set_flush_state_ref_count != 0) {
1526 devinfo->set_flush_state_ref_count--;
1527 if (devinfo->set_flush_state_ref_count == 0) {
1528 /* Don't actually enable interrupts. Just set a flag so that
1529 * buffer flips will be queued:
1531 devinfo->flush_commands = EMGD_FALSE;
1541 static void set_flush_state_external(emgddc_devinfo_t* devinfo,
1542 emgd_bool flush_state)
1544 unsigned long lock_flags;
1549 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1551 if (devinfo->flush_commands != flush_state) {
1552 devinfo->flush_commands = flush_state;
1553 set_flush_state_internal_nolock(devinfo, flush_state);
1556 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1564 * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCState() function.
1565 * This function is supposed to set some state flags in the driver, affecting
1566 * interrupt-driven buffer flips.
1568 * Note: The following function used to never be called, but now is called when
1569 * X11 is rotated 90 degrees (it is called as a result of an interrupt handler
1570 * dealing with an SGX hardware reset). As such, the code that this calls
1571 * cannot enable/disable interrupts (which may cause an interrupt handler to be
1572 * registered/unregistered).
1574 * Note: The code that this calls seems overly complicated. If we never enable
1575 * SUPPORT_FB_EVENTS, it can be simplified (e.g. no use of
1576 * set_flush_state_ref_count).
1578 * @param device_h (IN) The handle for this device (an opaque pointer to
1580 * @param state (IN) Either DC_STATE_FLUSH_COMMANDS or
1581 * DC_STATE_NO_FLUSH_COMMANDS.
1583 static IMG_VOID SetDCState(IMG_HANDLE device_h, IMG_UINT32 state)
1585 emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) device_h;
1588 EMGD_DEBUG("device_h = 0x%p", device_h);
1591 if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
1592 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
1593 __FUNCTION__, device_h);
1598 case DC_STATE_FLUSH_COMMANDS:
1599 set_flush_state_external(devinfo, EMGD_TRUE);
1601 case DC_STATE_NO_FLUSH_COMMANDS:
1602 set_flush_state_external(devinfo, EMGD_FALSE);
1610 } /* SetDCState() */
1613 #ifdef SUPPORT_FB_EVENTS
1614 /* NOTE -- The following code is probably not correct. It was inherited from
1615 * an early IMG/UMG DDK, and has never been used. If we ever decide to use
1616 * this code, we should look at the latest DDK and UMG code, to glean what may
1617 * be really needed. At a minimum, the following code needs to affect all swap
1621 static int emgddc_fb_events(struct notifier_block *notif,
1622 unsigned long event, void *data)
1624 emgddc_devinfo_t *devinfo;
1625 emgddc_swapchain_t *swap_chain;
1626 struct fb_event *fb_event = (struct fb_event *) data;
1628 unsigned long lock_flags;
1633 if (event != FB_EVENT_BLANK) {
1637 /* Look up the device (for DIH/Extended mode): */
1638 if (notif == &(global_devinfo[0]->lin_notif_block)) {
1639 devinfo = global_devinfo[0];
1640 } else if (notif == &(global_devinfo[1]->lin_notif_block)) {
1641 devinfo = global_devinfo[1];
1643 printk(KERN_ERR "[EMGD] emgddc_fb_events() cannot find its device\n");
1646 swap_chain = devinfo->flipable_swapchains;
1648 blanked = (*(IMG_INT *) fb_event->data != 0) ? EMGD_TRUE : EMGD_FALSE;
1650 if (blanked != swap_chain->blanked) {
1651 swap_chain->blanked = blanked;
1653 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1656 set_flush_state_internal_nolock(devinfo, EMGD_TRUE);
1658 set_flush_state_internal_nolock(devinfo, EMGD_FALSE);
1661 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1671 static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo)
1674 emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
1679 memset(&devinfo->lin_notif_block, 0, sizeof(devinfo->lin_notif_block));
1681 devinfo->lin_notif_block.notifier_call = emgddc_fb_events;
1682 swap_chain->blanked = EMGD_FALSE;
1683 res = fb_register_client(&devinfo->lin_notif_block);
1685 EMGD_ERROR_EXIT("fb_register_client() failed (%d)", res);
1686 return EMGD_ERROR_GENERIC;
1696 static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo)
1704 res = fb_unregister_client(&devinfo->lin_notif_block);
1706 EMGD_ERROR_EXIT("fb_unregister_client() failed (%d)", res);
1707 return EMGD_ERROR_GENERIC;
1715 #endif /* SUPPORT_FB_EVENTS */
1719 * This function does per-vblank processing of the circular queue of buffers to
1720 * flip. It is called for each flip-able swap chain, during a VBlank
1721 * interrupt. The first item in the queue is processed, and if it is cleared
1722 * (see below), the next item is processed, etc. Items are processed as
1725 * - An item that hasn't been flipped, is flipped. In this case, processing
1726 * stops. It is assumed that the swap interval for this item is at least
1727 * one, and therefore, another vblank is needed for this flip.
1729 * - An item that has been flipped, but hasn't been "completed" (i.e. PVR
1730 * services has been told that the flip occured), is "completed" and has its
1731 * swap interval decremented by 1. If the swap interval is now 0, the item
1732 * is cleared, allowing processing of the next item to start.
1734 * - An item that has been "completed," but hasn't reached the end of its swap
1735 * interval, has its swap interval decremented by 1. If the swap interval is
1736 * now 0, the item is cleared, allowing processing of the next item to start.
1738 * @param swap_chain (IN) The swap chain to process the queue for.
1740 emgd_bool emgddc_process_flip_queue_for_vblank(emgddc_swapchain_t *swap_chain)
1742 PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
1743 IMG_BOOL status = IMG_TRUE;
1744 emgddc_flip_queue_item_t *flip_item;
1745 unsigned long max_index;
1750 if (swap_chain->devinfo->flush_commands) {
1755 /* Get the first item to process in the circular queue: */
1756 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1757 max_index = swap_chain->buffer_count - 1;
1759 while (flip_item->valid) {
1760 if (flip_item->flipped) {
1761 if (!flip_item->cmd_completed) {
1762 EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer "
1763 "offset=0x%lx", flip_item->buffer->offset);
1764 pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete,
1766 flip_item->cmd_completed = EMGD_TRUE;
1769 flip_item->swap_interval--;
1770 EMGD_DEBUG("Swap interval is %lu for buffer offset=0x%lx",
1771 flip_item->swap_interval, flip_item->buffer->offset);
1773 if (flip_item->swap_interval == 0) {
1774 /* We're done with this item in the queue. Prepare for
1775 * processing the next item:
1777 flip_item->cmd_completed = EMGD_FALSE;
1778 flip_item->flipped = EMGD_FALSE;
1779 flip_item->valid = EMGD_FALSE;
1781 /* Point to the next item in the circular queue: */
1782 swap_chain->remove_index++;
1783 if (swap_chain->remove_index > max_index) {
1784 swap_chain->remove_index = 0;
1787 /* Wait for more vblanks before doing more queue processing: */
1791 EMGD_DEBUG("Flipping to buffer offset=0x%lx",
1792 flip_item->buffer->offset);
1793 emgddc_flip(swap_chain, flip_item->buffer);
1794 flip_item->flipped = EMGD_TRUE;
1795 /* Wait for more vblanks before doing more queue processing: */
1799 /* Get the next item in the circular queue: */
1800 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1808 } /* emgddc_process_flip_queue_for_vblank() */
1812 * This is called by a HAL-implemented, Linux interrupt handler. It is called
1813 * when a VBlank interrupt occurs. All device-specific functionality was
1814 * implemented by the HAL, and only 3DD-specific functionality needs to be
1815 * provided by this function.
1817 * @param pdevinfo (IN) Pointer to the devinfo that had a VBlank interrupt.
1818 * @return Non-zero for success, zeron for failure.
1820 static int emgddc_process_vblank(void* pdevinfo)
1822 emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) pdevinfo;
1823 emgddc_swapchain_t *swap_chain;
1824 unsigned long lock_flags;
1829 if ((devinfo != global_devinfo[0]) && (devinfo != global_devinfo[1])) {
1833 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1835 swap_chain = devinfo->flipable_swapchains;
1836 while (swap_chain != NULL) {
1837 (void) emgddc_process_flip_queue_for_vblank(swap_chain);
1838 swap_chain = swap_chain->next;
1841 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1845 } /* emgddc_process_vblank() */
1849 * Called by PVR services to flip a buffer. When interrupts are supported, the
1850 * flip may be queued (in a circular buffer) to happen later. When interrupts
1851 * are not supported, the flip always happens immediately
1853 * @param cmd_cookie_h (IN) An opaque pointer to a PVR service data structure
1854 * that must be handed back when the flip is "completed" (i.e. PVR services
1855 * is told that the flip occured).
1856 * @param data_size (IN) Size of the flip command and all clipping rectangles
1857 * (which isn't supported). This is only used for consistency-checking.
1858 * @param data (IN) A pointer to information about what to flip.
1860 static IMG_BOOL emgddc_process_flip(IMG_HANDLE cmd_cookie_h,
1861 IMG_UINT32 data_size,
1864 DISPLAYCLASS_FLIP_COMMAND *flip_cmd;
1865 emgddc_devinfo_t *devinfo;
1866 emgddc_buffer_t *buffers;
1867 emgddc_swapchain_t *swap_chain;
1868 unsigned long max_index;
1869 emgddc_flip_queue_item_t* flip_item;
1870 unsigned long lock_flags;
1872 int must_complete = 0;
1873 igd_context_t *context;
1879 * Unpack the flip command and look for errors:
1882 if (!cmd_cookie_h || !data) {
1883 EMGD_ERROR_EXIT("NULL parameter(s)");
1887 flip_cmd = (DISPLAYCLASS_FLIP_COMMAND *) data;
1889 /* Note: the data_size actually accounts for both the flip command and
1890 * all of the clipping rectangles. As such, the only error is if
1891 * data_size is smaller than the sizeof the flip command:
1893 if (flip_cmd == IMG_NULL ||
1894 (sizeof(DISPLAYCLASS_FLIP_COMMAND) > data_size)) {
1895 EMGD_ERROR_EXIT("Invalid flip_cmd (0x%p)", flip_cmd);
1899 devinfo = (emgddc_devinfo_t *) flip_cmd->hExtDevice;
1900 buffers = (emgddc_buffer_t *) flip_cmd->hExtBuffer;
1901 swap_chain = (emgddc_swapchain_t *) flip_cmd->hExtSwapChain;
1903 if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
1904 /* Note: Hardware video decode creates pixmap swap chains,
1905 * and when they are being destroyed (at
1906 * the end of video playback), something tries to flip these
1907 * non-flipable swap chains. The only way to avoid a hang is to
1908 * "complete" the flip command.
1910 printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
1911 "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
1912 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
1917 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1919 if ((devinfo->flipping_disabled == EMGD_TRUE) ||
1920 (swap_chain->valid != EMGD_TRUE)) {
1921 /* We won't flip, but must tell PVR services that the flip occured: */
1922 EMGD_DEBUG("Something (e.g. a mode change) has invalidated\n"
1923 "this swap chain. As such buffer flips are not allowed.\n"
1924 "If a mode change caused this problem, this swap chain\n"
1925 "needs to be destroyed, and a new one created.");
1926 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
1927 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1932 context = devinfo->priv->context;
1933 if (context->device_context.power_state != IGD_POWERSTATE_D0) {
1934 /* If device is in a suspended state, but PVR services asks the driver
1935 * to perform a buffer flip, basically ignore it except for telling PVR
1936 * services that we did the flip:
1938 EMGD_DEBUG("Device in suspended state--completing command");
1939 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
1940 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1945 /* Get the first item to add to the circular queue: */
1946 flip_item = &swap_chain->flip_queue[swap_chain->insert_index];
1947 max_index = swap_chain->buffer_count - 1;
1951 * Decide what needs to be done:
1953 if ((flip_cmd->ui32SwapInterval == 0) ||
1954 (devinfo->flush_commands == EMGD_TRUE)) {
1955 /* Perform and complete the flip now: */
1959 /* PVR services only calls emgddc_process_flip() when the 3DD completes
1960 * the previous flip. Thus, the circular flip_item queue should never
1961 * overflow. However, just in case, check whether the flip_item
1962 * already contains a valid/queued flip (i.e. we've overflowed the
1965 if (flip_item->valid == EMGD_FALSE) {
1966 if (swap_chain->insert_index == swap_chain->remove_index) {
1967 /* Perform the flip now, but queue it for completion: */
1970 /* else - queue the flip for later: */
1972 /* Just in case we overflow the circular queue, generate an error */
1973 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
1974 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1975 EMGD_ERROR_EXIT("Overflowed the circular flip_item queue");
1982 * Do what needs to be done:
1985 /* Perform the flip now: */
1986 EMGD_DEBUG("Flipping to buffer offset=0x%lx", buffers->offset);
1987 emgddc_flip(swap_chain, buffers);
1989 if (must_complete) {
1990 /* Tell the PVR services that the flip occured: */
1991 EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
1993 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
1995 /* Queue the flip for later completion: */
1996 EMGD_DEBUG("Queueing buffer offset=0x%lx", buffers->offset);
1998 flip_item->flipped = EMGD_TRUE;
2000 flip_item->cmd_complete = cmd_cookie_h;
2001 flip_item->swap_interval = (unsigned long) flip_cmd->ui32SwapInterval;
2002 flip_item->valid = EMGD_TRUE;
2003 flip_item->buffer = buffers;
2005 swap_chain->insert_index++;
2006 if (swap_chain->insert_index > max_index) {
2007 swap_chain->insert_index = 0;
2011 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
2015 } /* emgddc_process_flip() */
2019 * For a given devinfo, unmap's the frame buffer, and frees the devinfo and
2022 * @param dev (IN) The drm_device for this driver connection.
2024 void emgddc_free_a_devinfo(emgddc_devinfo_t *devinfo)
2026 igd_context_t *context = devinfo->priv->context;
2030 if (devinfo->priv->hal_running) {
2031 /* Un-register (if needed) the interrupt connection with the HAL: */
2032 if (devinfo->interrupt_h) {
2033 context->dispatch.unregister_vblank_callback(devinfo->interrupt_h);
2034 devinfo->interrupt_h = NULL;
2037 if (devinfo->system_buffer.virt_addr) {
2038 context->dispatch.gmm_unmap(devinfo->system_buffer.virt_addr);
2044 } /* emgddc_free_a_devinfo() */
2048 * Frees all devinfo structures and their surfaces. This is called during
2049 * de-init time, or when init fails.
2051 void emgddc_free_all_devinfos(void)
2053 emgddc_devinfo_t *devinfo;
2057 /* Free the primary display's structures: */
2058 devinfo = global_devinfo[0];
2059 emgddc_free_a_devinfo(devinfo);
2060 global_devinfo[0] = NULL;
2062 /* Free the secondary display's structures, if applicable: */
2063 if (NULL == (devinfo = global_devinfo[1])) {
2064 emgddc_free_a_devinfo(devinfo);
2065 global_devinfo[1] = NULL;
2069 } /* emgddc_free_all_devinfos() */
2073 * Initialize the "static" (i.e. doesn't vary with alter_display) portion of
2074 * a devinfo structure.
2076 * @param dev (IN) The drm_device for this driver connection.
2077 * @param devinfo (IN/OUT) The devinfo to initialize.
2078 * @param port_number (IN) Which devinfo (0 for primary, 1 for secondary/DIH).
2079 * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2081 static emgd_error_t emgddc_init_devinfo(struct drm_device *dev,
2082 emgddc_devinfo_t *devinfo, int which_devinfo)
2084 drm_emgd_priv_t *priv = dev->dev_private;
2085 PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable;
2086 PFN_CMD_PROC cmd_proc_list[EMGDDC_COMMAND_COUNT];
2087 IMG_UINT32 sync_count_list[EMGDDC_COMMAND_COUNT][2];
2093 * Initialize the static/display-independent devinfo values:
2095 devinfo->which_devinfo = which_devinfo;
2096 devinfo->priv = priv;
2097 devinfo->drm_device = dev;
2098 devinfo->flipable_swapchains = NULL;
2099 devinfo->swap_chain_id_counter = 0;
2100 devinfo->display_info.ui32MaxSwapChainBuffers = 5;
2101 devinfo->display_info.ui32MaxSwapChains = 1024 * 1024;
2102 /* Note: change from zero if we support interrupts and see the need: */
2103 devinfo->display_info.ui32MaxSwapInterval = 2;
2104 devinfo->display_info.ui32MinSwapInterval = 0;
2105 EMGD_DEBUG("Maximum number of swap chains: %lu",
2106 devinfo->display_info.ui32MaxSwapChains);
2107 EMGD_DEBUG("Maximum number of swap chain buffers: %lu",
2108 devinfo->display_info.ui32MaxSwapChainBuffers);
2109 strncpy(devinfo->display_info.szDisplayName, DISPLAY_DEVICE_NAME,
2110 MAX_DISPLAY_NAME_SIZE);
2111 devinfo->flush_commands = EMGD_FALSE;
2112 spin_lock_init(&devinfo->swap_chain_lock);
2116 * Get the PVR services jump table, which this 3rd-party display driver can
2117 * use to call PVR services:
2119 if (!PVRGetDisplayClassJTable(&devinfo->pvr_jtable)) {
2120 EMGD_ERROR_EXIT("Can not get PVR services jump table");
2121 return EMGD_ERROR_INIT_FAILURE;
2123 pvr_jtable = &devinfo->pvr_jtable;
2127 * Setup the jump table that PVR services uses to call this 3rd-party
2130 devinfo->dc_jtable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
2131 devinfo->dc_jtable.pfnOpenDCDevice = OpenDCDevice;
2132 devinfo->dc_jtable.pfnCloseDCDevice = CloseDCDevice;
2133 devinfo->dc_jtable.pfnEnumDCFormats = EnumDCFormats;
2134 devinfo->dc_jtable.pfnEnumDCDims = EnumDCDims;
2135 devinfo->dc_jtable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
2136 devinfo->dc_jtable.pfnGetDCInfo = GetDCInfo;
2137 devinfo->dc_jtable.pfnGetBufferAddr = GetDCBufferAddr;
2138 devinfo->dc_jtable.pfnCreateDCSwapChain = CreateDCSwapChain;
2139 devinfo->dc_jtable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
2140 devinfo->dc_jtable.pfnSetDCDstRect = SetDCDstRect;
2141 devinfo->dc_jtable.pfnSetDCSrcRect = SetDCSrcRect;
2142 devinfo->dc_jtable.pfnSetDCDstColourKey = SetDCDstColourKey;
2143 devinfo->dc_jtable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
2144 devinfo->dc_jtable.pfnGetDCBuffers = GetDCBuffers;
2145 devinfo->dc_jtable.pfnSwapToDCBuffer = SwapToDCBuffer;
2146 devinfo->dc_jtable.pfnSwapToDCSystem = SwapToDCSystem;
2147 devinfo->dc_jtable.pfnSetDCState = SetDCState;
2151 * Register this device with PVR services:
2153 if (pvr_jtable->pfnPVRSRVRegisterDCDevice(&devinfo->dc_jtable,
2154 &devinfo->device_id ) != PVRSRV_OK) {
2155 EMGD_ERROR_EXIT("Device registration failed");
2156 return EMGD_ERROR_DEVICE_REGISTER_FAILED;
2159 EMGD_DEBUG("Device ID: %d", (int)devinfo->device_id);
2163 * Tell PVR services about the function to process swap-chain buffer
2166 cmd_proc_list[DC_FLIP_COMMAND] = emgddc_process_flip;
2168 /* FIXME: Not sure what these are for: */
2169 sync_count_list[DC_FLIP_COMMAND][0] = 0;
2170 sync_count_list[DC_FLIP_COMMAND][1] = 2;
2172 if (pvr_jtable->pfnPVRSRVRegisterCmdProcList(devinfo->device_id,
2175 EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
2176 EMGD_ERROR_EXIT("Can't register callback\n");
2177 return EMGD_ERROR_CANT_REGISTER_CALLBACK;
2184 } /* emgddc_init_devinfo() */
2188 * Initializes the display/device-specific values of the devinfo structure for
2189 * a specified display (primary or secondary). This function is called during
2190 * initialization time, and whenever the EMGD driver does a potential mode
2191 * change, via alter_displays().
2193 * @param devinfo (IN/OUT) The devinfo to initialize for the display.
2194 * @param display (IN) The specified display (primary or secondary).
2195 * @param port_number (IN) The port number of the specified display.
2196 * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2198 static emgd_error_t init_display(emgddc_devinfo_t *devinfo,
2199 igd_display_h display,
2200 unsigned short port_number)
2202 drm_emgd_priv_t *priv = devinfo->priv;
2203 igd_context_t *context = priv->context;
2204 unsigned long dc = priv->dc;
2205 igd_framebuffer_info_t fb_info;
2206 DISPLAY_FORMAT *display_format_list;
2207 igd_display_info_t pt_info;
2208 unsigned long *fb_list_pfs;
2209 DISPLAY_DIMS *display_dim_list;
2210 igd_display_info_t *mode_list = NULL;
2211 igd_display_info_t *mode;
2212 int mode_flags = IGD_QUERY_LIVE_MODES;
2213 emgddc_buffer_t *buffer = &(devinfo->system_buffer);
2218 EMGD_DEBUG("Parameters:");
2219 EMGD_DEBUG(" devinfo=0x%p", devinfo);
2220 EMGD_DEBUG(" devinfo->which_devinfo=%d", devinfo->which_devinfo);
2221 EMGD_DEBUG(" display=0x%p", display);
2222 EMGD_DEBUG(" port_number=%u", port_number);
2224 /* Clear the following lists, in case we are re-initializing: */
2225 OS_MEMSET(devinfo->display_format_list, 0,
2226 sizeof(devinfo->display_format_list));
2227 OS_MEMSET(devinfo->display_dim_list, 0,
2228 sizeof(devinfo->display_dim_list));
2229 display_format_list = devinfo->display_format_list;
2230 display_dim_list = devinfo->display_dim_list;
2233 /* Call get_display() to get some of the following info: */
2234 ret = context->dispatch.get_display(display, port_number,
2235 &fb_info, &pt_info, 0);
2237 EMGD_ERROR_EXIT("get_display() returned %d", ret);
2238 return EMGD_ERROR_GENERIC;
2243 * Obtain the following addresses:
2245 * - buffer->offset = Framebuffer GTT address
2246 * - virt_addr = gmm_map(framebuffer offset);
2248 buffer->offset = fb_info.fb_base_offset;
2249 if(NULL == buffer->virt_addr){
2250 buffer->virt_addr = context->dispatch.gmm_map(fb_info.fb_base_offset);
2252 EMGD_DEBUG("buffer->virt_addr = 0x%p", buffer->virt_addr);
2253 /* This is the offset of the allocated framebuffer (e.g. the
2254 * 1024x768 surface of gmm-managed memory):
2256 EMGD_DEBUG("fb_info->fb_base_offset = 0x%lx", fb_info.fb_base_offset);
2259 /* Register (if we haven't) with the HAL to be able to use interrupts: */
2260 if (!devinfo->interrupt_h) {
2261 devinfo->interrupt_h =
2262 context->dispatch.register_vblank_callback(emgddc_process_vblank,
2263 devinfo, port_number);
2264 if (!devinfo->interrupt_h) {
2265 /* This should not happen, but just in case, provide an error: */
2266 printk(KERN_ERR "Cannot establish the ability to perform VBlank "
2267 "interrupts for port number %u.", port_number);
2273 * Obtain and translate pixel formats:
2275 /* Note: We always care about the current pixel format: */
2276 devinfo->emgd_pf = fb_info.pixel_format;
2277 devinfo->pvr_pf = emgd2pvr_pf(fb_info.pixel_format);
2278 display_format_list[0].pixelformat = emgd2pvr_pf(fb_info.pixel_format);
2279 EMGD_DEBUG("FB's native EMGD pixel format = 0x%08lx", devinfo->emgd_pf);
2280 EMGD_DEBUG("FB's PVR pixel format = %u",display_format_list[0].pixelformat);
2281 if (!priv->xserver_running) {
2282 /* In addition, provide an entire list of pixel formats: */
2283 ret = context->dispatch.get_pixelformats(display, &fb_list_pfs, NULL,
2286 EMGD_ERROR_EXIT("get_pixelformats() returned %d", ret);
2287 return EMGD_ERROR_GENERIC;
2289 while (*fb_list_pfs) {
2290 if ((devinfo->pvr_pf != emgd2pvr_pf(*fb_list_pfs)) &&
2291 (PVRSRV_PIXEL_FORMAT_UNKNOWN != emgd2pvr_pf(*fb_list_pfs))) {
2292 display_format_list[i].pixelformat = emgd2pvr_pf(*fb_list_pfs);
2293 EMGD_DEBUG(" Add'l (%d) PVR pixel format = "
2294 "%u", i, emgd2pvr_pf(*fb_list_pfs));
2297 if (++i >= EMGDDC_MAXFORMATS) {
2298 /* Don't write past the end of the array */
2299 EMGD_ERROR("Reached end of display_format_list! Consider "
2300 "increasing EMGDDC_MAXFORMATS.");
2305 devinfo->num_formats = i;
2306 EMGD_DEBUG("Total number of translated pixel formats = %d", i);
2310 * Obtain the possible dimensions, from the EMGD modes:
2312 /* Note: we always care about the current dimensions: */
2313 devinfo->width = fb_info.width;
2314 devinfo->height = fb_info.height;
2315 devinfo->byte_stride = fb_info.screen_pitch;
2316 EMGD_DEBUG("FB's width = %ld, height = %ld, stride = %ld",
2317 devinfo->width, devinfo->height, devinfo->byte_stride);
2318 display_dim_list[0].ui32Width = fb_info.width;
2319 display_dim_list[0].ui32Height = fb_info.height;
2320 display_dim_list[0].ui32ByteStride = fb_info.screen_pitch;
2322 if (!priv->xserver_running) {
2323 /* In addition, provide an entire list of dimensions: */
2324 ret = context->dispatch.query_mode_list((igd_driver_h) context, dc,
2325 &mode_list, mode_flags);
2327 EMGD_ERROR_EXIT("query_mode_list() returned %d", ret);
2328 return EMGD_ERROR_GENERIC;
2331 while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
2333 for (j = i - 1 ; j >= 0 ; j--) {
2334 if ((display_dim_list[j].ui32Width == mode->width) &&
2335 (display_dim_list[j].ui32Height == mode->height)) {
2340 display_dim_list[i].ui32Width = mode->width;
2341 display_dim_list[i].ui32Height = mode->height;
2342 display_dim_list[i].ui32ByteStride =
2343 (mode->width * IGD_PF_BPP(devinfo->emgd_pf) + 7) >>3;
2344 EMGD_DEBUG(" Add'l width = %d, height = %d, stride = %ld",
2345 mode->width, mode->height,
2346 display_dim_list[i].ui32ByteStride);
2347 if (++i >= EMGDDC_MAXDIMS) {
2348 /* Don't write past the end of the array */
2349 EMGD_ERROR("Reached end of display_dim_list! Consider "
2350 "increasing EMGDDC_MAXDIMS.");
2357 devinfo->num_dims = i;
2358 EMGD_DEBUG("Total number of dimensions = %d", i);
2362 * Obtain the size of the frame buffer, which will also be the size of any
2363 * swap chain buffers:
2365 devinfo->fb_size = devinfo->height * devinfo->byte_stride;
2366 EMGD_DEBUG("Frame buffer size = %lu = %luMB = 0x%lx", devinfo->fb_size,
2367 devinfo->fb_size / (1024 * 1024), devinfo->fb_size);
2371 * Initialize the igd_surface_t structure for the frame buffer, in order
2372 * allow the buffer flipping code to flip back to the frame buffer:
2374 buffer->priv = priv;
2375 buffer->offset = fb_info.fb_base_offset;
2376 buffer->pitch = devinfo->byte_stride;
2377 buffer->width = devinfo->width;
2378 buffer->height = devinfo->height;
2379 buffer->pixel_format = fb_info.pixel_format;
2380 buffer->size = devinfo->fb_size;
2386 } /* init_display() */
2389 * Loops through the avaiable displays, invalidating the associated flip-chains
2390 * This function is called from igd_alter_displays so as to resolve any race
2391 * conditions that may occur due to performing a flip during a mode-set.
2393 * @param display (IN) The display whose flipchains are to be invalidated.
2395 static int emgddc_invalidate_flip_chains(int display) {
2397 emgddc_devinfo_t * devinfo;
2398 emgddc_swapchain_t *swap_chain;
2399 unsigned long lock_flags;
2401 igd_display_h display_handle;
2402 igd_context_t *context;
2407 EMGD_DEBUG("Parameters:");
2408 EMGD_DEBUG("display=0x%1x",display);
2410 for (i = 0; i < MAX_DISPLAYS; i++) {
2411 if (display & (1 << i)) {
2412 devinfo = global_devinfo[i];
2414 if (devinfo == NULL) {
2415 EMGD_DEBUG("Skipping NULL display at index %d", i);
2420 /* Mode changes invalidate flip-able swap chains. We can't destroy
2421 * them behind the back of PVR services, but we can and should
2422 * ignore all pending and future buffer flips for existing swap
2424 * Note: new swap chains will be valid, and be able to perform flips.
2426 /* Obtain the lock, to hold-off future interrupt handling for a bit */
2427 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
2428 swap_chain = devinfo->flipable_swapchains;
2429 while (swap_chain != NULL) {
2430 swap_chain->valid = EMGD_FALSE;
2432 flush_flip_queue(swap_chain);
2433 swap_chain = swap_chain->next;
2435 /* Now that we've invalidated pending flips, release the lock */
2436 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
2438 /* Reset the frame-buffer information to point to the system
2440 context = devinfo->priv->context;
2441 display_handle = (devinfo->which_devinfo == 1)?
2442 devinfo->priv->secondary:devinfo->priv->primary;
2444 surf.offset = devinfo->system_buffer.offset;
2445 surf.pitch = devinfo->system_buffer.pitch;
2446 surf.width = devinfo->system_buffer.width;
2447 surf.height = devinfo->system_buffer.height;
2448 surf.pixel_format = devinfo->system_buffer.pixel_format;
2449 surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
2451 ret = context->dispatch.set_surface(display_handle,
2452 IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
2455 EMGD_ERROR("set_surface() returned %d for display at index %d",
2468 * [Re-]Initializes the 3DD's display/device-specific values for both devinfo
2469 * structures. This function is called during initializatio time, and whenever
2470 * the EMGD driver does a potential mode change, via alter_displays().
2472 * @param dev (IN) The drm_device associated with this driver.
2473 * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2475 static int emgddc_reinit_3dd(struct drm_device *dev)
2477 emgddc_devinfo_t *devinfo;
2478 drm_emgd_priv_t *priv = dev->dev_private;
2483 if (0 == priv->dc) {
2484 EMGD_DEBUG("not ready to re-init, because no dc has been set");
2485 if (!priv->hal_running) {
2486 /* Ensure that devinfo->interrupt_h is NULL: */
2487 if (NULL != (devinfo = global_devinfo[0])) {
2488 devinfo->interrupt_h = NULL;
2490 if (NULL != (devinfo = global_devinfo[1])) {
2491 devinfo->interrupt_h = NULL;
2497 EMGD_DEBUG("The DC is 0x%08lx", priv->dc);
2498 EMGD_DEBUG("IGD_DC_CLONE(priv->dc) is %d", IGD_DC_CLONE(priv->dc));
2499 EMGD_DEBUG("IGD_DC_EXTENDED(priv->dc) is %d", IGD_DC_EXTENDED(priv->dc));
2501 /* Always initialize the primary devinfo: */
2502 ret = init_display(global_devinfo[0], priv->primary,
2503 priv->primary_port_number);
2504 if (ret != EMGD_OK) {
2508 /* Initialize the secondary devinfo if we're in DIH/extended mode: */
2509 if (IGD_DC_EXTENDED(priv->dc)) {
2510 EMGD_DEBUG("Detected that we're in DIH/EXTENDED mode");
2512 /* Allocate the devinfo if it hasn't already been allocated: */
2513 if (NULL == (devinfo = global_devinfo[1])) {
2514 EMGD_DEBUG("Allocating devinfo structure for DIH/EXTENDED mode");
2515 devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
2517 EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
2518 return EMGD_ERROR_OUT_OF_MEMORY;
2520 OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
2522 /* Perform static/display-independent initialization: */
2523 ret = emgddc_init_devinfo(dev, devinfo, 1);
2524 if (ret != EMGD_OK) {
2525 EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
2526 emgddc_free_a_devinfo(devinfo);
2531 /* Perform dynamic/display-dependent initialization: */
2532 ret = init_display(devinfo, priv->secondary,
2533 priv->secondary_port_number);
2534 if (ret != EMGD_OK) {
2535 EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
2536 emgddc_free_a_devinfo(devinfo);
2537 global_devinfo[1] = NULL;
2541 /* Remember the devinfo, for other functions that aren't passed it: */
2542 global_devinfo[1] = devinfo;
2549 } /* emgddc_reinit_3dd() */
2553 * Master initialization function. This is called when the EMGD DRM module
2554 * tells PVR services to start, which calls this function.
2556 * @param dev (IN) The drm_device for this driver connection.
2557 * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2559 emgd_error_t emgddc_init(struct drm_device *dev)
2561 emgddc_devinfo_t *devinfo;
2562 drm_emgd_priv_t *priv = dev->dev_private;
2568 /* Exit early if trying to initialize again: */
2569 devinfo = global_devinfo[0];
2570 if (devinfo != NULL) {
2575 /* Always allocate the primary display's devinfo structure: */
2576 devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
2578 EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
2579 return EMGD_ERROR_OUT_OF_MEMORY;
2581 OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
2582 global_devinfo[0] = devinfo;
2584 /* Perform static/display-independent initialization: */
2585 ret = emgddc_init_devinfo(dev, devinfo, 0);
2586 if (ret != EMGD_OK) {
2587 emgddc_free_all_devinfos();
2591 /* Perform dynamic/display-dependent initialization (if we're in
2592 * DIH/Extended mode, the secondary devinfo will also be allocated and
2595 priv->reinit_3dd = emgddc_reinit_3dd;
2597 /* Used inside igd_alter_displays */
2598 priv->invalidate_flip_chains = emgddc_invalidate_flip_chains;
2600 ret = emgddc_reinit_3dd(dev);
2601 if (ret != EMGD_OK) {
2602 emgddc_free_all_devinfos();
2606 /* Remember the devinfo, for other functions that aren't passed it: */
2607 global_devinfo[0] = devinfo;
2613 } /* emgddc_init() */
2617 * Master de-initialization function. This is called when the EMGD DRM module
2618 * is being unloaded (it tells PVR services to exit, which calls this
2621 * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2623 emgd_error_t emgddc_deinit(void)
2625 emgddc_devinfo_t *devinfo;
2627 emgd_error_t ret = EMGD_OK;
2632 for (i = 0 ; i < 2 ; i++) {
2633 devinfo = global_devinfo[i];
2634 if (devinfo == NULL) {
2639 /* Unhook and unregister from PVR services: */
2640 if (devinfo->pvr_jtable.pfnPVRSRVRemoveCmdProcList(devinfo->device_id,
2641 EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
2642 ret = EMGD_ERROR_GENERIC;
2644 if (devinfo->pvr_jtable.pfnPVRSRVRemoveDCDevice(devinfo->device_id) !=
2646 ret = EMGD_ERROR_GENERIC;
2650 /* Delete any/all swap chains now: */
2651 /* Note: If we ever support interrupts, there may be a race condition
2652 * of pending flips. This was placed here, after the PVR services
2653 * thinks the driver has gone away, so that no flips should come by
2656 while (devinfo->flipable_swapchains) {
2657 if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
2658 devinfo->flipable_swapchains)) {
2659 ret = EMGD_ERROR_GENERIC;
2662 while (devinfo->pixmap_swapchains) {
2663 if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
2664 devinfo->pixmap_swapchains)) {
2665 ret = EMGD_ERROR_GENERIC;
2670 emgddc_free_a_devinfo(devinfo);
2671 global_devinfo[i] = NULL;
2678 } /* emgddc_deinit() */
2682 * Potentially perform a mode change.
2684 * If the X server is running, PVR services (including this function) can't
2685 * do mode changes. To avoid having to switch modes, ensure that the
2686 * current pixel format and dimension is specified:
2688 * If the X server is NOT running, PVR services (including this function)
2689 * can do mode changes. In this case, if the pixel format and/or
2690 * dimensions don't match the current mode, perform a mode change (as long
2691 * as valid values are provided):
2693 static PVRSRV_ERROR do_mode_change(igd_context_t *context,
2694 emgddc_devinfo_t *devinfo,
2695 drm_emgd_priv_t *priv,
2696 DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib)
2698 struct drm_device* drm_dev;
2699 int err = PVRSRV_OK;
2701 drm_dev = devinfo->drm_device;
2703 if (priv->xserver_running) {
2704 if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
2705 (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride) ||
2706 (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
2707 (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
2708 return PVRSRV_ERROR_INVALID_PARAMS;
2710 } else if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
2711 (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride)||
2712 (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
2713 (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
2714 unsigned long emgd_pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
2715 igd_display_info_t *mode_list = NULL;
2716 igd_display_info_t *mode = NULL;
2717 igd_display_info_t *desired_mode = NULL;
2718 int mode_flags = IGD_QUERY_LIVE_MODES;
2719 unsigned long byte_stride;
2720 igd_framebuffer_info_t primary_fb_info;
2721 igd_framebuffer_info_t secondary_fb_info;
2722 igd_display_h primary;
2723 igd_display_h secondary;
2725 printk("[EMGD] A mode change is requested. The following new values\n"
2726 "[EMGD] will be checked, and if good, take effect:\n");
2727 printk("[EMGD] pixel format = %u (PVR) = 0x%08lx (EMGD)\n",
2728 dst_surf_attrib->pixelformat, emgd_pf);
2729 printk("[EMGD] width = %lu, height = %lu\n",
2730 dst_surf_attrib->sDims.ui32Width,
2731 dst_surf_attrib->sDims.ui32Height);
2732 printk("[EMGD] stride = %lu\n",dst_surf_attrib->sDims.ui32ByteStride);
2735 /* Check the pixel format: */
2736 if (IGD_PF_UNKNOWN == emgd_pf) {
2737 printk(KERN_ERR "Unknown pixel format %u\n",
2738 dst_surf_attrib->pixelformat);
2739 return PVRSRV_ERROR_INVALID_PARAMS;
2743 /* Check the width, height, and stride: */
2744 EMGD_DEBUG("Calling query_mode_list()");
2745 err = context->dispatch.query_mode_list(context, priv->dc,
2746 &mode_list, mode_flags);
2748 printk(KERN_ERR "The query_mode_list() function returned %d.", err);
2749 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2751 EMGD_DEBUG("Comparing the mode list with the desired width, height, "
2754 while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
2755 byte_stride = IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
2756 EMGD_DEBUG(" ... Found a mode with width=%d, height=%d, "
2757 "refresh=%d;", mode->width, mode->height, mode->refresh);
2758 if ((mode->width == dst_surf_attrib->sDims.ui32Width) &&
2759 (mode->height == dst_surf_attrib->sDims.ui32Height) &&
2760 (byte_stride == dst_surf_attrib->sDims.ui32ByteStride)) {
2761 EMGD_DEBUG(" ... This mode is a match!");
2762 desired_mode = mode;
2767 if (NULL == desired_mode) {
2768 printk(KERN_ERR "No mode matching the desired width (%lu), height "
2769 "(%lu), and stride (%lu) was found.",
2770 dst_surf_attrib->sDims.ui32Width,
2771 dst_surf_attrib->sDims.ui32Height,
2772 dst_surf_attrib->sDims.ui32ByteStride);
2773 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2775 /* Must set this in order to get the timings setup: */
2776 desired_mode->flags |= IGD_DISPLAY_ENABLE;
2780 /* Make the mode change by calling alter_displays(): */
2781 primary_fb_info.width = desired_mode->width;
2782 primary_fb_info.height = desired_mode->height;
2783 primary_fb_info.pixel_format = emgd_pf;
2784 primary_fb_info.flags = 0;
2785 primary_fb_info.allocated = 0;
2786 memcpy(&secondary_fb_info, &primary_fb_info,
2787 sizeof(igd_framebuffer_info_t));
2789 EMGD_DEBUG("Calling alter_displays()");
2790 err = context->dispatch.alter_displays(context,
2791 &primary, desired_mode, &primary_fb_info,
2792 &secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
2794 printk(KERN_ERR "The alter_displays() function returned %d.", err);
2795 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2799 /* Update the private copy, like emgd_alter_displays() would do: */
2800 priv->primary = primary;
2801 priv->secondary = secondary;
2802 priv->primary_port_number = (priv->dc & 0xf0) >> 4;
2803 priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
2806 /* Re-initialize the display values: */
2807 err = priv->reinit_3dd(drm_dev);
2808 if (err != EMGD_OK) {
2809 printk(KERN_ERR "The reinit_3dd() function returned %d.", err);
2810 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2812 } /* end of mode-change code */
2815 } /* do_mode_change() */