Move the drivers to a separate sub-directory
[profile/ivi/intel-emgd-kmod.git] / drivers / pvr / services4 / 3rdparty / emgd_displayclass / emgd_dc.c
1 /**********************************************************************
2  * Copyright (c) 2002-2010, Intel Corporation.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
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
20  * THE SOFTWARE.
21  ******************************************************************************/
22 #define MODULE_NAME hal.pvr3dd
23
24 #include <linux/spinlock.h>
25
26 #include "drm_emgd_private.h"
27
28 #include "img_defs.h"
29 #include "servicesext.h"
30 #include "kerneldisplay.h"
31 #include "emgd_dc.h"
32 #include "emgd_drm.h"
33
34
35 #if !defined(SUPPORT_DRI_DRM)
36 #error "SUPPORT_DRI_DRM must be set"
37 #endif
38
39
40 /* Function to get the PVR services jump table */
41 extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *jtable);
42
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);
52
53
54 /* Special value used to register with the PVR services command queue: */
55 #define EMGDDC_COMMAND_COUNT            1
56
57
58 /**
59  * This is a pointer to the global emgddc_devinfo_t structure, used in various
60  * parts of this file.
61  */
62 static emgddc_devinfo_t *global_devinfo[] = {NULL, NULL};
63
64
65 /**
66  * Pairs of equivalent pixel formats, in EMGD and PVR formats:
67  */
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 */
72
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 */
78
79         /* 3 Byte-per-pixel [A]RGB Pixel Formats: */
80         {IGD_PF_RGB24, PVRSRV_PIXEL_FORMAT_RGB888},         /* IMG numbered */
81
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 */
88
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},
94         /* UNKNOWN to IMG
95         {IGD_PF_YUV411_PACKED_Y41P, PVRSRV_PIXEL_FORMAT_UNKNOWN},
96         */
97
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 */
102         /* UNKNOWN to IMG
103         {IGD_PF_YUV410_PLANAR_YVU9, PVRSRV_PIXEL_FORMAT_UNKNOWN},
104         */
105         {IGD_PF_YUV420_PLANAR_NV12, PVRSRV_PIXEL_FORMAT_NV12},
106 };
107 unsigned int num_known_pfs =
108         sizeof(known_pfs) / sizeof(emgddc_pixelformat_translator_t);
109
110
111 /**
112  * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
113  *
114  * @param emgd_pf (IN) EMGD-specific pixel format.
115  * @return Translated PVR-specific pixel format.
116  */
117 static unsigned long pvr2emgd_pf(PVRSRV_PIXEL_FORMAT pvr_pf)
118 {
119         int i;
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;
123                 }
124         }
125
126         /* If we get to here, we didn't find a known PVR pixel format: */
127         return IGD_PF_UNKNOWN;
128 }
129
130
131 /**
132  * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
133  *
134  * @param emgd_pf (IN) EMGD-specific pixel format.
135  * @return Translated PVR-specific pixel format.
136  */
137 static PVRSRV_PIXEL_FORMAT emgd2pvr_pf(unsigned long emgd_pf)
138 {
139         int i;
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;
143                 }
144         }
145
146         /* If we get to here, we didn't find a known PVR pixel format: */
147         return IGD_PF_UNKNOWN;
148 }
149
150
151 /**
152  * Determines if the user-space-provided pointer (to a devinfo) is valid.
153  *
154  * @param devinfo (IN) The user-space-provided pointer to a devinfo.
155  */
156 static int is_valid_devinfo(emgddc_devinfo_t *devinfo)
157 {
158         if ((devinfo == global_devinfo[0]) || (devinfo == global_devinfo[1])) {
159                 return 1;
160         } else {
161                 return 0;
162         }
163 } /* is_valid_devinfo() */
164
165
166 /**
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.
170  *
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
175  * devinfo).
176  * @param system_buffer_sync_data (IN) Sync data for this device's system
177  * buffer.
178  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
179  */
180 static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 device_id,
181         IMG_HANDLE *device_h,
182         PVRSRV_SYNC_DATA* system_buffer_sync_data)
183 {
184         emgddc_devinfo_t *devinfo;
185
186         EMGD_TRACE_ENTER;
187
188
189         UNREFERENCED_PARAMETER(device_id);
190
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);
198         } else {
199                 printk(KERN_ERR "[EMGD] OpenDCDevice() called with unknown device ID "
200                         "%lu\n", device_id);
201                 return PVRSRV_ERROR_INVALID_DEVICE;
202         }
203         devinfo->system_buffer.sync_data = system_buffer_sync_data;
204         *device_h = (IMG_HANDLE) devinfo;
205
206
207         EMGD_TRACE_EXIT;
208
209         return PVRSRV_OK;
210 } /* OpenDCDevice() */
211
212
213 /**
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.
217  *
218  * @param device_h (IN) The handle for this device (an opaque pointer to
219  * devinfo).
220  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
221  */
222 static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE device_h)
223 {
224         EMGD_TRACE_STUB;
225
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;
231         }
232
233         return PVRSRV_OK;
234 } /* CloseDCDevice() */
235
236
237 /**
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.
243  *
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.
250  *
251  * @param device_h (IN) The handle for this device (an opaque pointer to
252  * devinfo).
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
255  * if NULL).
256  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
257  */
258 static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE device_h,
259         IMG_UINT32 *num_formats,
260         DISPLAY_FORMAT *format)
261 {
262         emgddc_devinfo_t        *devinfo;
263
264         EMGD_TRACE_ENTER;
265         EMGD_DEBUG("device_h = 0x%p", device_h);
266
267
268         if (!device_h || !num_formats) {
269                 return PVRSRV_ERROR_INVALID_PARAMS;
270         }
271
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;
277         }
278
279         *num_formats = devinfo->num_formats;
280
281         if (format) {
282                 unsigned long i;
283
284                 for (i = 0 ; i < devinfo->num_formats ; i++) {
285                         format[i] = devinfo->display_format_list[i];
286                 }
287         }
288
289
290         EMGD_TRACE_EXIT;
291         return PVRSRV_OK;
292
293 } /* EnumDCFormats() */
294
295
296 /**
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.
302  *
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.
309  *
310  * @param device_h (IN) The handle for this device (an opaque pointer to
311  * devinfo).
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
315  * if NULL).
316  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
317  */
318 static PVRSRV_ERROR EnumDCDims(IMG_HANDLE device_h,
319         DISPLAY_FORMAT *format,
320         IMG_UINT32 *num_dims,
321         DISPLAY_DIMS *dims)
322 {
323         emgddc_devinfo_t        *devinfo;
324
325         EMGD_TRACE_ENTER;
326         EMGD_DEBUG("device_h = 0x%p", device_h);
327
328
329         if (!device_h || !format || !num_dims) {
330                 return PVRSRV_ERROR_INVALID_PARAMS;
331         }
332
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;
338         }
339
340         *num_dims = devinfo->num_dims;
341
342         if (dims) {
343                 unsigned long i;
344
345                 for (i = 0 ; i < devinfo->num_dims ; i++) {
346                         dims[i] = devinfo->display_dim_list[i];
347                 }
348         }
349
350
351         EMGD_TRACE_EXIT;
352         return PVRSRV_OK;
353
354 } /* EnumDCDims() */
355
356
357 /**
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.
362  *
363  * @param device_h (IN) The handle for this device (an opaque pointer to
364  * devinfo).
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.
368  */
369 static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE device_h, IMG_HANDLE *buffer_h)
370 {
371         emgddc_devinfo_t        *devinfo;
372
373         EMGD_TRACE_ENTER;
374         EMGD_DEBUG("device_h = 0x%p", device_h);
375
376
377         if (!device_h || !buffer_h) {
378                 return PVRSRV_ERROR_INVALID_PARAMS;
379         }
380
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;
386         }
387
388         *buffer_h = (IMG_HANDLE) &devinfo->system_buffer;
389
390
391         EMGD_TRACE_EXIT;
392         return PVRSRV_OK;
393
394 } /* GetDCSystemBuffer() */
395
396
397 /**
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).
402  *
403  * @param device_h (IN) The handle for this device (an opaque pointer to
404  * devinfo).
405  * @param dc_info (OUT) The DISPLAY_INFO structure associated with this device.
406  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
407  */
408 static PVRSRV_ERROR GetDCInfo(IMG_HANDLE device_h, DISPLAY_INFO *dc_info)
409 {
410         emgddc_devinfo_t        *devinfo;
411
412         EMGD_TRACE_ENTER;
413         EMGD_DEBUG("device_h = 0x%p", device_h);
414
415
416         if (!device_h || !dc_info) {
417                 return PVRSRV_ERROR_INVALID_PARAMS;
418         }
419
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;
425         }
426
427         *dc_info = devinfo->display_info;
428
429
430         EMGD_TRACE_EXIT;
431         return PVRSRV_OK;
432
433 } /* GetDCInfo() */
434
435
436 /**
437  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBufferAddr()
438  * function.
439  *
440  * @param device_h (IN) The handle for this device (an opaque pointer to
441  * devinfo).
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
448  * addresses.
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
451  * the buffer.
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.
456  */
457 static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE device_h,
458         IMG_HANDLE buffer_h,
459         IMG_SYS_PHYADDR **phys_addr,
460         IMG_UINT32 *fb_size,
461         IMG_VOID **virt_addr,
462         IMG_HANDLE *os_map_info_h,
463         IMG_BOOL *is_contiguous)
464 {
465         emgddc_devinfo_t *devinfo;
466         igd_context_t *context;
467         emgddc_buffer_t *system_buffer;
468         unsigned long page_count = 0;
469         int ret;
470
471         EMGD_TRACE_ENTER;
472         EMGD_DEBUG("device_h = 0x%p", device_h);
473
474
475         if (!device_h) {
476                 printk(KERN_ERR "[EMGD] %s() Null device handle.\n", __FUNCTION__);
477                 return PVRSRV_ERROR_INVALID_PARAMS;
478         }
479
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;
485         }
486
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;
491         }
492
493         if (!buffer_h) {
494                 printk(KERN_ERR "[EMGD] %s() Null buffer handle.\n", __FUNCTION__);
495                 return PVRSRV_ERROR_INVALID_PARAMS;
496         }
497
498         system_buffer = (emgddc_buffer_t *) buffer_h;
499
500         if (!phys_addr) {
501                 return PVRSRV_ERROR_INVALID_PARAMS;
502         }
503
504         EMGD_DEBUG("  phys_addr = 0x%p", phys_addr);
505         EMGD_DEBUG("  *phys_addr = 0x%p", (*phys_addr));
506
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);
511                 EMGD_TRACE_EXIT;
512                 return PVRSRV_ERROR_OUT_OF_MEMORY;
513         }
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);
517
518         if (!fb_size) {
519                 return PVRSRV_ERROR_INVALID_PARAMS;
520         }
521
522         if (fb_size) {
523                 *fb_size = (IMG_UINT32) system_buffer->size;
524                 EMGD_DEBUG("  fb_size = 0x%lx", *fb_size);
525         }
526
527         if (virt_addr) {
528                 *virt_addr = system_buffer->virt_addr;
529                 EMGD_DEBUG("  virt_addr = 0x%p", *virt_addr);
530         }
531
532         /* Note: this value is ignored by the PVR services code: */
533         if (os_map_info_h) {
534                 *os_map_info_h = (IMG_HANDLE)system_buffer->offset;
535                 EMGD_DEBUG("  os_map_info_h = 0x%p", *os_map_info_h);
536         }
537
538         /*
539          * Other than cursor, memory allocations are not contiguous pages
540          */
541         if (is_contiguous) {
542                 if(system_buffer->is_contiguous == IMG_TRUE)
543                 {       *is_contiguous = IMG_TRUE;
544
545                 }
546                 else{
547                         *is_contiguous = IMG_FALSE;
548
549                 }
550         }
551
552         EMGD_TRACE_EXIT;
553         return PVRSRV_OK;
554
555 } /* GetDCBufferAddr() */
556
557
558 /**
559  * Determines if the user-space-provided pointers (to a devinfo and swap chain)
560  * are valid.
561  *
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.
566  */
567 static int is_valid_swap_chain(emgddc_devinfo_t *devinfo,
568         emgddc_swapchain_t *swap_chain, int must_be_flipable)
569 {
570         if (!is_valid_devinfo(devinfo)) {
571                 return 0;
572         } else {
573                 /* Search both lists for this swap chain: */
574                 emgddc_swapchain_t *swap = devinfo->flipable_swapchains;
575                 while (swap) {
576                         if (swap == swap_chain) {
577                                 return 1;
578                         }
579                         swap = swap->next;
580                 }
581                 if (!must_be_flipable) {
582                         swap = devinfo->pixmap_swapchains;
583                         while (swap) {
584                                 if (swap == swap_chain) {
585                                         return 1;
586                                 }
587                                 swap = swap->next;
588                         }
589                 }
590         }
591         /* We didn't find this swap chain pointer, so it's not valid: */
592         return 0;
593 } /* is_valid_swap_chain() */
594
595
596 /**
597  * Called by CreateDCSwapChain() to add a new swap chain to one of the lists of
598  * swap chains.
599  *
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.
602  */
603 static void add_swap_chain_to_list(emgddc_swapchain_t **list,
604         emgddc_swapchain_t *swap_chain)
605 {
606         /* It's simplest to add to the front of the list: */
607         if (*list == NULL) {
608                 *list = swap_chain;
609         } else {
610                 swap_chain->next = *list;
611                 *list = swap_chain;
612         }
613 } /* add_swap_chain_to_list() */
614
615
616 /**
617  * Called by DestroyDCSwapChain() to remove an about-to-be-deleted swap chain
618  * from one of the lists of swap chains.
619  *
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.
622  */
623 static void remove_swap_chain_from_list(emgddc_swapchain_t **list,
624         emgddc_swapchain_t *swap_chain)
625 {
626         emgddc_swapchain_t *swap, *prev;
627
628         swap = *list;
629         prev = *list;
630         while (swap) {
631                 if (swap == swap_chain) {
632                         /* Found match */
633                         if (swap == *list) {
634                                 *list = swap->next;
635                         } else {
636                                 prev->next = swap->next;
637                         }
638                         break;
639                 }
640                 prev = swap;
641                 swap = swap->next;
642         }
643 } /* remove_swap_chain_from_list() */
644
645
646 /**
647  * Called by either CreateDCSwapChain() or DestroyDCSwapChain() to free all GMM
648  * and kernel space memory memory of the specified swap chain.
649  *
650  * @param swap_chain (IN) The swap chain to free.
651  * @param context (IN) The EMGD context to use to call gmm_free().
652  */
653 static void free_swap_chain(emgddc_swapchain_t *swap_chain,
654         igd_context_t *context)
655 {
656         emgddc_buffer_t *buffers;
657         int i=0;
658
659         /*
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.
663          */
664         if (swap_chain->devinfo->priv->hal_running) {
665                 buffers = swap_chain->buffers;
666
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);
672                                         }
673                                         if (buffers[i].offset) {
674                                                 context->dispatch.gmm_free(buffers[i].offset);
675                                         }
676                                 }
677                         }
678                         else{
679                                 context->dispatch.gmm_unmap_ci((unsigned long)buffers[i].virt_addr);
680                         }
681
682                 }
683         }
684
685         if (swap_chain->flip_queue) {
686                 OS_FREE(swap_chain->flip_queue);
687         }
688         OS_FREE(swap_chain->buffers);
689         OS_FREE(swap_chain);
690
691         EMGD_TRACE_EXIT;
692 } /* free_swap_chain() */
693
694
695 /**
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).
703  *
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.
708  *
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.
715  *
716  * @param device_h (IN) The handle for this device (an opaque pointer to
717  * devinfo).
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
721  * front buffer.
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.
732  */
733 static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE device_h,
734         IMG_UINT32 flags,
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)
742 {
743         emgddc_devinfo_t        *devinfo;
744         emgddc_swapchain_t *swap_chain;
745         emgddc_buffer_t *buffers;
746         IMG_UINT32 i;
747         emgddc_flip_queue_item_t *flip_queue = NULL;
748         unsigned long lock_flags;
749
750         struct drm_device* drm_dev;
751         drm_emgd_priv_t *priv;
752         igd_context_t *context;
753         igd_dispatch_t *dispatch;
754         int flipable;
755
756         IMG_UINT32 ci_offset=0;
757
758
759         EMGD_TRACE_ENTER;
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);
762
763         if(flags & PVR2D_CREATE_FLIPCHAIN_CI)
764         {
765                 ci_offset = src_surf_attrib->ui32Reseved;
766
767         }
768
769         /*
770          * Check the parameters and dependencies:
771          */
772         if (!device_h || !dst_surf_attrib || !src_surf_attrib || !sync_data ||
773                 !swap_chain_h) {
774                 return PVRSRV_ERROR_INVALID_PARAMS;
775         }
776
777         /*
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):
780          *
781          *  PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY - General purpose displayable
782          *  PVR2D_CREATE_FLIPCHAIN_OEMGENERAL - General purpose non-displayable
783          *  PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY - Overlay
784          *
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:
787          *
788          *  PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN - Flip-able buffers
789          */
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))) {
795                 flipable = 0;
796
797         } else {
798                 /*
799                  * If this is suppose to be an actual flip-able swap chain, then
800                  * make sure there are at least 2 buffers.
801                  */
802                 if (buffer_count < 2) {
803                         return PVRSRV_ERROR_TOO_FEW_BUFFERS;
804                 }
805                 flipable = 1;
806
807         }
808
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;
814         }
815         drm_dev = devinfo->drm_device;
816         priv = drm_dev->dev_private;
817         context = priv->context;
818         dispatch = &(context->dispatch);
819
820
821         if (buffer_count > devinfo->display_info.ui32MaxSwapChainBuffers) {
822                 return PVRSRV_ERROR_TOOMANYBUFFERS;
823         }
824
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;
833         }
834
835         if (flipable) {
836                 PVRSRV_ERROR err =
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()");
840                         EMGD_TRACE_EXIT;
841                         return err;
842                 }
843         }
844
845         /*
846          * Allocate data structures:
847          */
848         swap_chain = (emgddc_swapchain_t *) OS_ALLOC(sizeof(emgddc_swapchain_t));
849         if (!swap_chain) {
850                 EMGD_ERROR_EXIT("Can not allocate memory for a swap chain");
851                 return PVRSRV_ERROR_OUT_OF_MEMORY;
852         }
853         OS_MEMSET(swap_chain, 0, sizeof(emgddc_swapchain_t));
854
855         buffers = (emgddc_buffer_t *) OS_ALLOC(sizeof(emgddc_buffer_t) *
856                 buffer_count);
857         if (!buffers) {
858                 OS_FREE(swap_chain);
859                 EMGD_ERROR_EXIT("Can not allocate memory for swap chain buffers");
860                 return PVRSRV_ERROR_OUT_OF_MEMORY;
861         }
862         OS_MEMSET(buffers, 0, sizeof(emgddc_buffer_t) * buffer_count);
863
864         if (flipable) {
865                 flip_queue = (emgddc_flip_queue_item_t *)
866                         OS_ALLOC(sizeof(emgddc_flip_queue_item_t) * buffer_count);
867                 if (!flip_queue) {
868                         OS_FREE(buffers);
869                         OS_FREE(swap_chain);
870                         EMGD_ERROR_EXIT("Can not allocate memory for flip queue");
871                         return PVRSRV_ERROR_OUT_OF_MEMORY;
872                 }
873                 OS_MEMSET(flip_queue, 0,
874                         sizeof(emgddc_flip_queue_item_t) * buffer_count);
875         }
876
877         /*
878          * Initialize data structures:
879          */
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;
886         if (flipable) {
887                 swap_chain->flip_queue = flip_queue;
888                 swap_chain->insert_index = 0;
889                 swap_chain->remove_index = 0;
890         }
891         swap_chain->pvr_jtable = &devinfo->pvr_jtable;
892
893         /* Link the buffers of the swap chain: */
894         for (i = 0 ; i < buffer_count-1 ; i++) {
895                 buffers[i].next = &buffers[i+1];
896         }
897         buffers[i].next = &buffers[0];
898
899         i = 0;
900         if (flipable) {
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;
913                 i++;
914         }
915
916         /*
917          * Allocate memory for the buffers
918          */
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;
926                 unsigned long pf;
927                 unsigned long flags = IGD_SURFACE_RENDER;
928                 int ret;
929                 unsigned int map_method=1;      /*1: gtt map by va driver*/
930
931                 if (!(oem_flags & PVR2D_CREATE_FLIPCHAIN_OEMGENERAL)) {
932                         flags |= IGD_SURFACE_DISPLAY;
933                 }
934
935                 buffers[i].priv = priv;
936
937                 /*
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?
941                  */
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;
947
948                 if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
949                         if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI_V4L2_MAP)
950                                 map_method = 0;
951
952
953                         size=height*pitch;
954                         ret = dispatch->gmm_map_ci(&offset,
955                                 ci_offset,
956                                 &virt_addr,
957                                 map_method,
958                                 size);
959
960
961                         if (0 != ret) {
962                                 free_swap_chain(swap_chain, context);
963                                 EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
964                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
965                         }
966                         buffers[i].is_contiguous = IMG_TRUE;
967
968                 }
969                 else{
970
971                         ret = dispatch->gmm_alloc_surface(&offset,
972                                 pf,
973                                 &width, &height,
974                                 &pitch, &size,
975                                 IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
976                         if (0 != ret) {
977                                 free_swap_chain(swap_chain, context);
978                                 EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
979                                 return PVRSRV_ERROR_OUT_OF_MEMORY;
980                         }
981                         buffers[i].is_contiguous = IMG_FALSE;
982                 }
983
984                 dst_surf_attrib->sDims.ui32ByteStride = pitch;
985                 src_surf_attrib->sDims.ui32ByteStride = pitch;
986
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;
992
993                 buffers[i].offset = offset;
994
995                 if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
996
997                                 buffers[i].virt_addr = (IMG_CPU_VIRTADDR)virt_addr;
998                 }
999                 else
1000                         buffers[i].virt_addr = dispatch->gmm_map(offset);
1001                 buffers[i].sync_data = sync_data[i];
1002                 buffers[i].is_fb = 0;
1003         } /* for */
1004
1005
1006         if (flipable) {
1007                 /* Initialize what's needed for flip-able swap chains: */
1008                 int must_enable;
1009
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;
1014                 }
1015
1016                 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1017
1018                 must_enable = (devinfo->flipable_swapchains == NULL) ? 1 : 0;
1019
1020                 /* Add this swap chain to the list of flip-able swap chains: */
1021                 add_swap_chain_to_list(&devinfo->flipable_swapchains, swap_chain);
1022
1023                 /* Unlock here (before enabling interrupts), to prevent deadlock: */
1024                 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1025
1026                 if (!devinfo->flush_commands) {
1027                         if (must_enable) {
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,
1036                                                                                                 swap_chain);
1037                                         free_swap_chain(swap_chain, context);
1038                                         return PVRSRV_ERROR_BAD_MAPPING;
1039                                 } else {
1040                                         devinfo->flipping_disabled = EMGD_FALSE;
1041                                 }
1042                         }
1043                 }
1044
1045 #ifdef SUPPORT_FB_EVENTS
1046                 if (must_enable) {
1047                         /* Enable fb events: */
1048                         if (enable_event_notification(devinfo)!= EMGD_OK) {
1049                                 EMGD_ERROR_EXIT("Can not enable framebuffer event "
1050                                         "notification");
1051                                 /* Properly clean up: */
1052                                 if (devinfo->interrupt_h) {
1053                                         dispatch->disable_vblank_callback(
1054                                                 devinfo->interrupt_h);
1055                                 }
1056                                 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1057                                 remove_swap_chain_from_list(&devinfo->flipable_swapchains,
1058                                         swap_chain);
1059                                 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1060                                 free_swap_chain(swap_chain, context);
1061                                 return PVRSRV_ERROR_BAD_MAPPING;
1062                         }
1063                 }
1064 #endif /* SUPPORT_FB_EVENTS */
1065         } else {
1066                 /* Add this swap chain to the list of pixmap swap chains: */
1067                 add_swap_chain_to_list(&devinfo->pixmap_swapchains, swap_chain);
1068         }
1069
1070
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);
1075
1076         EMGD_TRACE_EXIT;
1077         return PVRSRV_OK;
1078
1079 } /* CreateDCSwapChain() */
1080
1081
1082 /**
1083  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnDestroyDCSwapChain()
1084  * function.
1085  *
1086  * @param device_h (IN) The handle for this device (an opaque pointer to
1087  * devinfo).
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.
1091  */
1092 static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE device_h,
1093         IMG_HANDLE swap_chain_h)
1094 {
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
1102         emgd_error_t error;
1103 #endif /* SUPPORT_FB_EVENTS */
1104
1105         EMGD_TRACE_ENTER;
1106         EMGD_DEBUG("device_h = 0x%p", device_h);
1107
1108
1109         if (!device_h || !swap_chain_h) {
1110                 return PVRSRV_ERROR_INVALID_PARAMS;
1111         }
1112
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;
1122         }
1123
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: */
1127                 int must_disable;
1128                 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1129                 must_disable =
1130                         ((devinfo->flipable_swapchains == swap_chain) &&
1131                          (devinfo->flipable_swapchains->next == NULL)) ? 1 : 0;
1132
1133                 /* Remove this swap chain from the list of flip-able swap chains: */
1134                 remove_swap_chain_from_list(&devinfo->flipable_swapchains, swap_chain);
1135
1136                 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1137
1138 #ifdef SUPPORT_FB_EVENTS
1139                 if (must_disable) {
1140                         /* Disable fb events: */
1141                         error = disable_event_notification(devinfo);
1142                         if (error != EMGD_OK) {
1143                                 EMGD_ERROR("Could not disable framebuffer event notification");
1144                         }
1145                 }
1146 #endif /* SUPPORT_FB_EVENTS */
1147
1148                 /* Disable interrupts for vblanks: */
1149                 if (must_disable) {
1150                         if (devinfo->interrupt_h) {
1151                                 dispatch->disable_vblank_callback(devinfo->interrupt_h);
1152                         }
1153                 }
1154
1155                 /* Flush any pending flips: */
1156                 flush_flip_queue(swap_chain);
1157
1158                 /* Flip back to the system buffer: */
1159                 emgddc_flip(swap_chain, &devinfo->system_buffer);
1160         } else {
1161                 /* Remove this swap chain from the list of pixmap swap chains: */
1162                 remove_swap_chain_from_list(&devinfo->pixmap_swapchains, swap_chain);
1163         }
1164
1165         /* Free all GMM and kernel space memory for this swap chain: */
1166         free_swap_chain(swap_chain, context);
1167
1168         EMGD_TRACE_EXIT;
1169         return PVRSRV_OK;
1170
1171 } /* DestroyDCSwapChain() */
1172
1173
1174 /**
1175  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstRect()
1176  * function.
1177  *
1178  * @param device_h (IN) The handle for this device (an opaque pointer to
1179  * devinfo).
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.
1184  */
1185 static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE device_h,
1186         IMG_HANDLE swap_chain_h,
1187         IMG_RECT *rect)
1188 {
1189         UNREFERENCED_PARAMETER(device_h);
1190         UNREFERENCED_PARAMETER(swap_chain_h);
1191         UNREFERENCED_PARAMETER(rect);
1192
1193         EMGD_TRACE_STUB;
1194
1195         return PVRSRV_ERROR_NOT_SUPPORTED;
1196 }
1197
1198
1199 /**
1200  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcRect()
1201  * function.
1202  *
1203  * @param device_h (IN) The handle for this device (an opaque pointer to
1204  * devinfo).
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.
1209  */
1210 static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE device_h,
1211         IMG_HANDLE swap_chain_h,
1212         IMG_RECT *rect)
1213 {
1214         UNREFERENCED_PARAMETER(device_h);
1215         UNREFERENCED_PARAMETER(swap_chain_h);
1216         UNREFERENCED_PARAMETER(rect);
1217
1218         EMGD_TRACE_STUB;
1219
1220         return PVRSRV_ERROR_NOT_SUPPORTED;
1221 }
1222
1223
1224 /**
1225  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstColourKey()
1226  * function.
1227  *
1228  * @param device_h (IN) The handle for this device (an opaque pointer to
1229  * devinfo).
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.
1234  */
1235 static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE device_h,
1236         IMG_HANDLE swap_chain_h,
1237         IMG_UINT32 color)
1238 {
1239         UNREFERENCED_PARAMETER(device_h);
1240         UNREFERENCED_PARAMETER(swap_chain_h);
1241         UNREFERENCED_PARAMETER(color);
1242
1243         EMGD_TRACE_STUB;
1244
1245         return PVRSRV_ERROR_NOT_SUPPORTED;
1246 }
1247
1248
1249 /**
1250  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcColourKey()
1251  * function.
1252  *
1253  * @param device_h (IN) The handle for this device (an opaque pointer to
1254  * devinfo).
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.
1259  */
1260 static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE device_h,
1261         IMG_HANDLE swap_chain_h,
1262         IMG_UINT32 color)
1263 {
1264         UNREFERENCED_PARAMETER(device_h);
1265         UNREFERENCED_PARAMETER(swap_chain_h);
1266         UNREFERENCED_PARAMETER(color);
1267
1268         EMGD_TRACE_STUB;
1269
1270         return PVRSRV_ERROR_NOT_SUPPORTED;
1271 }
1272
1273
1274 /**
1275  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBuffers()
1276  * function.
1277  *
1278  * @param device_h (IN) The handle for this device (an opaque pointer to
1279  * devinfo).
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
1285  * the caller).
1286  * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
1287  */
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)
1292 {
1293         emgddc_devinfo_t *devinfo;
1294         emgddc_swapchain_t *swap_chain;
1295         unsigned long i;
1296
1297         EMGD_TRACE_ENTER;
1298         EMGD_DEBUG("device_h = 0x%p", device_h);
1299
1300
1301         if (!device_h || !swap_chain_h || !buffer_count || !buffer_h) {
1302                 return PVRSRV_ERROR_INVALID_PARAMS;
1303         }
1304
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;
1311         }
1312
1313         *buffer_count = (IMG_UINT32) swap_chain->buffer_count;
1314
1315         for (i = 0 ; i < swap_chain->buffer_count ; i++) {
1316                 buffer_h[i] = (IMG_HANDLE) &swap_chain->buffers[i];
1317         }
1318
1319
1320         EMGD_TRACE_EXIT;
1321         return PVRSRV_OK;
1322
1323 } /* GetDCBuffers() */
1324
1325
1326 /**
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!
1330  *
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().
1334  *
1335  * @param device_h (IN) The handle for this device (an opaque pointer to
1336  * devinfo).
1337  * @param buffer_h (IN) The handle for this buffer (an opaque pointer to a
1338  * emgddc_buffer_t).
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.
1344  */
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)
1351 {
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);
1359
1360         EMGD_TRACE_STUB;
1361         return PVRSRV_ERROR_NOT_SUPPORTED;
1362
1363 } /* SwapToDCBuffer() */
1364
1365
1366 /**
1367  * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCSystem()
1368  * function.  This function causes a flip to the "system buffer" (a.k.a. frame
1369  * buffer).
1370  *
1371  * @param device_h (IN) The handle for this device (an opaque pointer to
1372  * devinfo).
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.
1376  */
1377 static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE device_h,
1378         IMG_HANDLE swap_chain_h)
1379 {
1380         emgddc_devinfo_t   *devinfo;
1381         emgddc_swapchain_t *swap_chain;
1382         unsigned long      lock_flags;
1383
1384         EMGD_TRACE_ENTER;
1385         EMGD_DEBUG("device_h = 0x%p", device_h);
1386
1387
1388         if (!device_h || !swap_chain_h) {
1389                 return PVRSRV_ERROR_INVALID_PARAMS;
1390         }
1391
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;
1398         }
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;
1402         }
1403
1404         spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1405
1406         flush_flip_queue(swap_chain);
1407         emgddc_flip(swap_chain, &devinfo->system_buffer);
1408
1409         spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1410
1411
1412         EMGD_TRACE_EXIT;
1413         return PVRSRV_OK;
1414
1415 } /* SwapToDCSystem() */
1416
1417
1418 /**
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
1421  * as follows:
1422  *
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.
1426  *
1427  * - An item that has been flipped, but hasn't been "completed" with PVR
1428  *   services, is "completed," ended, and cleared.
1429  *
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.
1434  *
1435  * Note: This function assumes that the calling function has already obtained
1436  * the spin lock.
1437  *
1438  * @param swap_chain (IN) The swap chain to flush the queue for.
1439  */
1440 static void flush_flip_queue(emgddc_swapchain_t *swap_chain)
1441 {
1442         emgddc_flip_queue_item_t *flip_item;
1443         unsigned long max_index;
1444         unsigned long i;
1445
1446         EMGD_TRACE_ENTER;
1447
1448
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;
1452
1453         for (i = 0 ; i < swap_chain->buffer_count ; i++) {
1454                 if (flip_item->valid == EMGD_FALSE) {
1455                         continue;
1456                 }
1457
1458                 EMGD_DEBUG("Flushing buffer offset=0x%lx", flip_item->buffer->offset);
1459
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);
1466                 }
1467
1468                 if (flip_item->cmd_completed == EMGD_FALSE) {
1469                         PVRSRV_DC_DISP2SRV_KMJTABLE     *pvr_jtable = swap_chain->pvr_jtable;
1470
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);
1474                 }
1475
1476                 /* We're done with this item in the queue.  Prepare for processing the
1477                  * next item:
1478                  */
1479                 flip_item->flipped = EMGD_FALSE;
1480                 flip_item->cmd_completed = EMGD_FALSE;
1481                 flip_item->valid = EMGD_FALSE;
1482
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;
1487                 }
1488
1489                 /* Get the next item in the circular queue: */
1490                 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1491         }
1492
1493         /* Reset the circular queue to the start: */
1494         swap_chain->insert_index = 0;
1495         swap_chain->remove_index = 0;
1496
1497
1498         EMGD_TRACE_EXIT;
1499
1500 } /* flush_flip_queue() */
1501
1502
1503 static void set_flush_state_internal_nolock(emgddc_devinfo_t* devinfo,
1504         emgd_bool flush_state)
1505 {
1506         emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
1507
1508         EMGD_TRACE_ENTER;
1509
1510
1511         if (flush_state) {
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:
1516                          */
1517                         devinfo->flush_commands = EMGD_TRUE;
1518                         while (swap_chain != NULL) {
1519                                 flush_flip_queue(swap_chain);
1520                                 swap_chain = swap_chain->next;
1521                         }
1522                 }
1523                 devinfo->set_flush_state_ref_count++;
1524         } else {
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:
1530                                  */
1531                                 devinfo->flush_commands = EMGD_FALSE;
1532                         }
1533                 }
1534         }
1535
1536
1537         EMGD_TRACE_EXIT;
1538 }
1539
1540
1541 static void set_flush_state_external(emgddc_devinfo_t* devinfo,
1542         emgd_bool flush_state)
1543 {
1544         unsigned long lock_flags;
1545
1546         EMGD_TRACE_ENTER;
1547
1548
1549         spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1550
1551         if (devinfo->flush_commands != flush_state) {
1552                 devinfo->flush_commands = flush_state;
1553                 set_flush_state_internal_nolock(devinfo, flush_state);
1554         }
1555
1556         spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1557
1558
1559         EMGD_TRACE_EXIT;
1560 }
1561
1562
1563 /**
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.
1567  *
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).
1573  *
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).
1577  *
1578  * @param device_h (IN) The handle for this device (an opaque pointer to
1579  * devinfo).
1580  * @param state (IN) Either DC_STATE_FLUSH_COMMANDS or
1581  * DC_STATE_NO_FLUSH_COMMANDS.
1582  */
1583 static IMG_VOID SetDCState(IMG_HANDLE device_h, IMG_UINT32 state)
1584 {
1585         emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) device_h;
1586
1587         EMGD_TRACE_ENTER;
1588         EMGD_DEBUG("device_h = 0x%p", device_h);
1589
1590
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);
1594                 return;
1595         }
1596
1597         switch (state) {
1598         case DC_STATE_FLUSH_COMMANDS:
1599                 set_flush_state_external(devinfo, EMGD_TRUE);
1600                 break;
1601         case DC_STATE_NO_FLUSH_COMMANDS:
1602                 set_flush_state_external(devinfo, EMGD_FALSE);
1603                 break;
1604         default:
1605                 break;
1606         }
1607
1608
1609         EMGD_TRACE_EXIT;
1610 } /* SetDCState() */
1611
1612
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
1618  * chains.
1619  */
1620
1621 static int emgddc_fb_events(struct notifier_block *notif,
1622         unsigned long event, void *data)
1623 {
1624         emgddc_devinfo_t *devinfo;
1625         emgddc_swapchain_t *swap_chain;
1626         struct fb_event *fb_event = (struct fb_event *) data;
1627         emgd_bool blanked;
1628         unsigned long lock_flags;
1629
1630         EMGD_TRACE_ENTER;
1631
1632
1633         if (event != FB_EVENT_BLANK) {
1634                 return 0;
1635         }
1636
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];
1642         } else {
1643                 printk(KERN_ERR "[EMGD] emgddc_fb_events() cannot find its device\n");
1644                 return -ENODEV;
1645         }
1646         swap_chain = devinfo->flipable_swapchains;
1647
1648         blanked = (*(IMG_INT *) fb_event->data != 0) ? EMGD_TRUE : EMGD_FALSE;
1649
1650         if (blanked != swap_chain->blanked) {
1651                 swap_chain->blanked = blanked;
1652
1653                 spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1654
1655                 if (blanked) {
1656                         set_flush_state_internal_nolock(devinfo, EMGD_TRUE);
1657                 } else {
1658                         set_flush_state_internal_nolock(devinfo, EMGD_FALSE);
1659                 }
1660
1661                 spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1662         }
1663
1664
1665         EMGD_TRACE_EXIT;
1666
1667         return 0;
1668 }
1669
1670
1671 static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo)
1672 {
1673         int res;
1674         emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
1675
1676         EMGD_TRACE_ENTER;
1677
1678
1679         memset(&devinfo->lin_notif_block, 0, sizeof(devinfo->lin_notif_block));
1680
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);
1684         if (res != 0) {
1685                 EMGD_ERROR_EXIT("fb_register_client() failed (%d)", res);
1686                 return EMGD_ERROR_GENERIC;
1687         }
1688
1689
1690         EMGD_TRACE_EXIT;
1691
1692         return EMGD_OK;
1693 }
1694
1695
1696 static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo)
1697 {
1698         int res;
1699
1700
1701         EMGD_TRACE_ENTER;
1702
1703
1704         res = fb_unregister_client(&devinfo->lin_notif_block);
1705         if (res != 0) {
1706                 EMGD_ERROR_EXIT("fb_unregister_client() failed (%d)", res);
1707                 return EMGD_ERROR_GENERIC;
1708         }
1709
1710
1711         EMGD_TRACE_EXIT;
1712
1713         return EMGD_OK;
1714 }
1715 #endif /* SUPPORT_FB_EVENTS */
1716
1717
1718 /**
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
1723  * follows:
1724  *
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.
1728  *
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.
1733  *
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.
1737  *
1738  * @param swap_chain (IN) The swap chain to process the queue for.
1739  */
1740 emgd_bool emgddc_process_flip_queue_for_vblank(emgddc_swapchain_t *swap_chain)
1741 {
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;
1746
1747         EMGD_TRACE_ENTER;
1748
1749
1750         if (swap_chain->devinfo->flush_commands) {
1751                 EMGD_TRACE_EXIT;
1752                 return status;
1753         }
1754
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;
1758
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,
1765                                         IMG_TRUE);
1766                                 flip_item->cmd_completed = EMGD_TRUE;
1767                         }
1768
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);
1772
1773                         if (flip_item->swap_interval == 0) {
1774                                 /* We're done with this item in the queue.  Prepare for
1775                                  * processing the next item:
1776                                  */
1777                                 flip_item->cmd_completed = EMGD_FALSE;
1778                                 flip_item->flipped = EMGD_FALSE;
1779                                 flip_item->valid = EMGD_FALSE;
1780
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;
1785                                 }
1786                         } else {
1787                                 /* Wait for more vblanks before doing more queue processing: */
1788                                 break;
1789                         }
1790                 } else {
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: */
1796                         break;
1797                 }
1798
1799                 /* Get the next item in the circular queue: */
1800                 flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
1801         }
1802
1803
1804         EMGD_TRACE_EXIT;
1805
1806         return status;
1807
1808 } /* emgddc_process_flip_queue_for_vblank() */
1809
1810
1811 /**
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.
1816  *
1817  * @param pdevinfo (IN) Pointer to the devinfo that had a VBlank interrupt.
1818  * @return Non-zero for success, zeron for failure.
1819  */
1820 static int emgddc_process_vblank(void* pdevinfo)
1821 {
1822         emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) pdevinfo;
1823         emgddc_swapchain_t *swap_chain;
1824         unsigned long lock_flags;
1825
1826         EMGD_TRACE_ENTER;
1827
1828
1829         if ((devinfo != global_devinfo[0]) && (devinfo != global_devinfo[1])) {
1830                 return 0;
1831         }
1832
1833         spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1834
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;
1839         }
1840
1841         spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
1842
1843         return 1;
1844
1845 } /* emgddc_process_vblank() */
1846
1847
1848 /**
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
1852  *
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.
1859  */
1860 static IMG_BOOL emgddc_process_flip(IMG_HANDLE cmd_cookie_h,
1861         IMG_UINT32 data_size,
1862         IMG_VOID *data)
1863 {
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;
1871         int must_flip = 0;
1872         int must_complete = 0;
1873         igd_context_t *context;
1874
1875         EMGD_TRACE_ENTER;
1876
1877
1878         /*
1879          * Unpack the flip command and look for errors:
1880          */
1881
1882         if (!cmd_cookie_h || !data) {
1883                 EMGD_ERROR_EXIT("NULL parameter(s)");
1884                 return IMG_FALSE;
1885         }
1886
1887         flip_cmd = (DISPLAYCLASS_FLIP_COMMAND *) data;
1888
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:
1892          */
1893         if (flip_cmd == IMG_NULL ||
1894                 (sizeof(DISPLAYCLASS_FLIP_COMMAND) > data_size)) {
1895                 EMGD_ERROR_EXIT("Invalid flip_cmd (0x%p)", flip_cmd);
1896                 return IMG_FALSE;
1897         }
1898
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;
1902
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.
1909                  */
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);
1913                 EMGD_TRACE_EXIT;
1914                 return IMG_TRUE;
1915         }
1916
1917         spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
1918
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);
1928                 EMGD_TRACE_EXIT;
1929                 return IMG_TRUE;
1930         }
1931
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:
1937                  */
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);
1941                 EMGD_TRACE_EXIT;
1942                 return IMG_TRUE;
1943         }
1944
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;
1948
1949
1950         /*
1951          * Decide what needs to be done:
1952          */
1953         if ((flip_cmd->ui32SwapInterval == 0) ||
1954                 (devinfo->flush_commands == EMGD_TRUE)) {
1955                 /* Perform and complete the flip now: */
1956                 must_flip = 1;
1957                 must_complete = 1;
1958         } else {
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
1963                  * circular queue).
1964                  */
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: */
1968                                 must_flip = 1;
1969                         }
1970                         /* else - queue the flip for later: */
1971                 } else {
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");
1976                         return IMG_FALSE;
1977                 }
1978         }
1979
1980
1981         /*
1982          * Do what needs to be done:
1983          */
1984         if (must_flip) {
1985                 /* Perform the flip now: */
1986                 EMGD_DEBUG("Flipping to buffer offset=0x%lx", buffers->offset);
1987                 emgddc_flip(swap_chain, buffers);
1988         }
1989         if (must_complete) {
1990                 /* Tell the PVR services that the flip occured: */
1991                 EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
1992                         buffers->offset);
1993                 swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
1994         } else {
1995                 /* Queue the flip for later completion: */
1996                 EMGD_DEBUG("Queueing buffer offset=0x%lx", buffers->offset);
1997                 if (must_flip) {
1998                         flip_item->flipped = EMGD_TRUE;
1999                 }
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;
2004
2005                 swap_chain->insert_index++;
2006                 if (swap_chain->insert_index > max_index) {
2007                         swap_chain->insert_index = 0;
2008                 }
2009         }
2010
2011         spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
2012
2013         EMGD_TRACE_EXIT;
2014         return IMG_TRUE;
2015 } /* emgddc_process_flip() */
2016
2017
2018 /**
2019  * For a given devinfo, unmap's the frame buffer, and frees the devinfo and
2020  * it's surfaces.
2021  *
2022  * @param dev (IN) The drm_device for this driver connection.
2023  */
2024 void emgddc_free_a_devinfo(emgddc_devinfo_t *devinfo)
2025 {
2026         igd_context_t *context = devinfo->priv->context;
2027
2028         EMGD_TRACE_ENTER;
2029
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;
2035                 }
2036
2037                 if (devinfo->system_buffer.virt_addr) {
2038                         context->dispatch.gmm_unmap(devinfo->system_buffer.virt_addr);
2039                 }
2040         }
2041         OS_FREE(devinfo);
2042
2043         EMGD_TRACE_EXIT;
2044 } /* emgddc_free_a_devinfo() */
2045
2046
2047 /**
2048  * Frees all devinfo structures and their surfaces.  This is called during
2049  * de-init time, or when init fails.
2050  */
2051 void emgddc_free_all_devinfos(void)
2052 {
2053         emgddc_devinfo_t *devinfo;
2054
2055         EMGD_TRACE_ENTER;
2056
2057         /* Free the primary display's structures: */
2058         devinfo = global_devinfo[0];
2059         emgddc_free_a_devinfo(devinfo);
2060         global_devinfo[0] = NULL;
2061
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;
2066         }
2067
2068         EMGD_TRACE_EXIT;
2069 } /* emgddc_free_all_devinfos() */
2070
2071
2072 /**
2073  * Initialize the "static" (i.e. doesn't vary with alter_display) portion of
2074  * a devinfo structure.
2075  *
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).
2080  */
2081 static emgd_error_t emgddc_init_devinfo(struct drm_device *dev,
2082         emgddc_devinfo_t *devinfo, int which_devinfo)
2083 {
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];
2088
2089         EMGD_TRACE_ENTER;
2090
2091
2092         /*
2093          * Initialize the static/display-independent devinfo values:
2094          */
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);
2113
2114
2115         /*
2116          * Get the PVR services jump table, which this 3rd-party display driver can
2117          * use to call PVR services:
2118          */
2119         if (!PVRGetDisplayClassJTable(&devinfo->pvr_jtable)) {
2120                 EMGD_ERROR_EXIT("Can not get PVR services jump table");
2121                 return EMGD_ERROR_INIT_FAILURE;
2122         }
2123         pvr_jtable = &devinfo->pvr_jtable;
2124
2125
2126         /*
2127          * Setup the jump table that PVR services uses to call this 3rd-party
2128          * display driver:
2129          */
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;
2148
2149
2150         /*
2151          * Register this device with PVR services:
2152          */
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;
2157         }
2158
2159         EMGD_DEBUG("Device ID: %d", (int)devinfo->device_id);
2160
2161
2162         /*
2163          * Tell PVR services about the function to process swap-chain buffer
2164          * flips:
2165          */
2166         cmd_proc_list[DC_FLIP_COMMAND] = emgddc_process_flip;
2167
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;
2171
2172         if (pvr_jtable->pfnPVRSRVRegisterCmdProcList(devinfo->device_id,
2173                 &cmd_proc_list[0],
2174                 sync_count_list,
2175                 EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
2176                 EMGD_ERROR_EXIT("Can't register callback\n");
2177                 return EMGD_ERROR_CANT_REGISTER_CALLBACK;
2178         }
2179
2180
2181         EMGD_TRACE_EXIT;
2182         return EMGD_OK;
2183
2184 } /* emgddc_init_devinfo() */
2185
2186
2187 /**
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().
2192  *
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).
2197  */
2198 static emgd_error_t init_display(emgddc_devinfo_t *devinfo,
2199         igd_display_h display,
2200         unsigned short port_number)
2201 {
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);
2214         int i = 1, j, ret;
2215
2216         EMGD_TRACE_ENTER;
2217
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);
2223
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;
2231
2232
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);
2236         if (0 != ret) {
2237                 EMGD_ERROR_EXIT("get_display() returned %d", ret);
2238                 return EMGD_ERROR_GENERIC;
2239         }
2240
2241
2242         /*
2243          * Obtain the following addresses:
2244          *
2245          * - buffer->offset = Framebuffer GTT address
2246          * - virt_addr = gmm_map(framebuffer offset);
2247          */
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);
2251         }
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):
2255          */
2256         EMGD_DEBUG("fb_info->fb_base_offset = 0x%lx", fb_info.fb_base_offset);
2257
2258
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);
2268                 }
2269         }
2270
2271
2272         /*
2273          * Obtain and translate pixel formats:
2274          */
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,
2284                         NULL, NULL, NULL);
2285                 if (0 != ret) {
2286                         EMGD_ERROR_EXIT("get_pixelformats() returned %d", ret);
2287                         return EMGD_ERROR_GENERIC;
2288                 }
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));
2295                         }
2296                         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.");
2301                                 break;
2302                         }
2303                 }
2304         }
2305         devinfo->num_formats = i;
2306         EMGD_DEBUG("Total number of translated pixel formats = %d", i);
2307
2308
2309         /*
2310          * Obtain the possible dimensions, from the EMGD modes:
2311          */
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;
2321         i = 1;
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);
2326                 if (0 != ret) {
2327                         EMGD_ERROR_EXIT("query_mode_list() returned %d", ret);
2328                         return EMGD_ERROR_GENERIC;
2329                 }
2330                 mode = mode_list;
2331                 while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
2332                         int seen = 0;
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)) {
2336                                         seen = 1;
2337                                 }
2338                         }
2339                         if (!seen) {
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.");
2351                                         break;
2352                                 }
2353                         }
2354                         mode++;
2355                 }
2356         }
2357         devinfo->num_dims = i;
2358         EMGD_DEBUG("Total number of dimensions = %d", i);
2359
2360
2361         /*
2362          * Obtain the size of the frame buffer, which will also be the size of any
2363          * swap chain buffers:
2364          */
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);
2368
2369
2370         /*
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:
2373          */
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;
2381
2382
2383         EMGD_TRACE_EXIT;
2384         return EMGD_OK;
2385
2386 } /* init_display() */
2387
2388 /**
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.
2392  *
2393  * @param display     (IN) The display whose flipchains are to be invalidated.
2394  */
2395 static int emgddc_invalidate_flip_chains(int display) {
2396
2397         emgddc_devinfo_t * devinfo;
2398         emgddc_swapchain_t *swap_chain;
2399         unsigned long lock_flags;
2400         igd_surface_t surf;
2401         igd_display_h display_handle;
2402         igd_context_t *context;
2403         int i;
2404         int ret;
2405
2406         EMGD_TRACE_ENTER;
2407         EMGD_DEBUG("Parameters:");
2408         EMGD_DEBUG("display=0x%1x",display);
2409
2410         for (i = 0; i < MAX_DISPLAYS; i++) {
2411                 if (display & (1 << i)) {
2412                         devinfo = global_devinfo[i];
2413
2414                         if (devinfo == NULL) {
2415                                 EMGD_DEBUG("Skipping NULL display at index %d", i);
2416                                 continue;
2417                         }
2418
2419
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
2423                          * chains.
2424                          * Note: new swap chains will be valid, and be able to perform flips.
2425                          */
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;
2431
2432                                 flush_flip_queue(swap_chain);
2433                                 swap_chain = swap_chain->next;
2434                         }
2435                         /* Now that we've invalidated pending flips, release the lock */
2436                         spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
2437
2438                         /* Reset the frame-buffer information to point to the system
2439                          * buffer */
2440                         context = devinfo->priv->context;
2441                         display_handle = (devinfo->which_devinfo == 1)?
2442                                                                 devinfo->priv->secondary:devinfo->priv->primary;
2443
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;
2450
2451                         ret = context->dispatch.set_surface(display_handle,
2452                                         IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
2453
2454                         if (ret) {
2455                                 EMGD_ERROR("set_surface() returned %d for display at index %d",
2456                                                 ret, i);
2457                         }
2458                 }
2459         }
2460
2461         EMGD_TRACE_EXIT;
2462
2463         return 0;
2464 }
2465
2466
2467 /**
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().
2471  *
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).
2474  */
2475 static int emgddc_reinit_3dd(struct drm_device *dev)
2476 {
2477         emgddc_devinfo_t *devinfo;
2478         drm_emgd_priv_t *priv = dev->dev_private;
2479         int ret;
2480
2481         EMGD_TRACE_ENTER;
2482
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;
2489                         }
2490                         if (NULL != (devinfo = global_devinfo[1])) {
2491                                 devinfo->interrupt_h = NULL;
2492                         }
2493                 }
2494                 return EMGD_OK;
2495         }
2496
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));
2500
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) {
2505                 return ret;
2506         }
2507
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");
2511
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));
2516                         if (!devinfo) {
2517                                 EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
2518                                 return EMGD_ERROR_OUT_OF_MEMORY;
2519                         }
2520                         OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
2521
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);
2527                                 return ret;
2528                         }
2529                 }
2530
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;
2538                         return ret;
2539                 }
2540
2541                 /* Remember the devinfo, for other functions that aren't passed it: */
2542                 global_devinfo[1] = devinfo;
2543         }
2544
2545
2546         EMGD_TRACE_EXIT;
2547         return EMGD_OK;
2548
2549 } /* emgddc_reinit_3dd() */
2550
2551
2552 /**
2553  * Master initialization function.  This is called when the EMGD DRM module
2554  * tells PVR services to start, which calls this function.
2555  *
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).
2558  */
2559 emgd_error_t emgddc_init(struct drm_device *dev)
2560 {
2561         emgddc_devinfo_t *devinfo;
2562         drm_emgd_priv_t *priv = dev->dev_private;
2563         int ret;
2564
2565         EMGD_TRACE_ENTER;
2566
2567
2568         /* Exit early if trying to initialize again: */
2569         devinfo = global_devinfo[0];
2570         if (devinfo != NULL) {
2571                 EMGD_TRACE_EXIT;
2572                 return EMGD_OK;
2573         }
2574
2575         /* Always allocate the primary display's devinfo structure: */
2576         devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
2577         if (!devinfo) {
2578                 EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
2579                 return EMGD_ERROR_OUT_OF_MEMORY;
2580         }
2581         OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
2582         global_devinfo[0] = devinfo;
2583
2584         /* Perform static/display-independent initialization: */
2585         ret = emgddc_init_devinfo(dev, devinfo, 0);
2586         if (ret != EMGD_OK) {
2587                 emgddc_free_all_devinfos();
2588                 return ret;
2589         }
2590
2591         /* Perform dynamic/display-dependent initialization (if we're in
2592          * DIH/Extended mode, the secondary devinfo will also be allocated and
2593          * initialized):
2594          */
2595         priv->reinit_3dd = emgddc_reinit_3dd;
2596
2597         /* Used inside igd_alter_displays */
2598         priv->invalidate_flip_chains = emgddc_invalidate_flip_chains;
2599
2600         ret = emgddc_reinit_3dd(dev);
2601         if (ret != EMGD_OK) {
2602                 emgddc_free_all_devinfos();
2603                 return ret;
2604         }
2605
2606         /* Remember the devinfo, for other functions that aren't passed it: */
2607         global_devinfo[0] = devinfo;
2608
2609
2610         EMGD_TRACE_EXIT;
2611         return EMGD_OK;
2612
2613 } /* emgddc_init() */
2614
2615
2616 /**
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
2619  * function).
2620  *
2621  * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
2622  */
2623 emgd_error_t emgddc_deinit(void)
2624 {
2625         emgddc_devinfo_t *devinfo;
2626         int i;
2627         emgd_error_t ret = EMGD_OK;
2628
2629         EMGD_TRACE_ENTER;
2630
2631
2632         for (i = 0 ; i < 2 ; i++) {
2633                 devinfo = global_devinfo[i];
2634                 if (devinfo == NULL) {
2635                         continue;
2636                 }
2637
2638
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;
2643                 }
2644                 if (devinfo->pvr_jtable.pfnPVRSRVRemoveDCDevice(devinfo->device_id) !=
2645                         PVRSRV_OK) {
2646                         ret = EMGD_ERROR_GENERIC;
2647                 }
2648
2649
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
2654                  * this time.
2655                  */
2656                 while (devinfo->flipable_swapchains) {
2657                         if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
2658                                 devinfo->flipable_swapchains)) {
2659                                 ret = EMGD_ERROR_GENERIC;
2660                         }
2661                 }
2662                 while (devinfo->pixmap_swapchains) {
2663                         if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
2664                                 devinfo->pixmap_swapchains)) {
2665                                 ret = EMGD_ERROR_GENERIC;
2666                         }
2667                 }
2668
2669
2670                 emgddc_free_a_devinfo(devinfo);
2671                 global_devinfo[i] = NULL;
2672         }
2673
2674
2675         EMGD_TRACE_EXIT;
2676         return ret;
2677
2678 } /* emgddc_deinit() */
2679
2680
2681 /*
2682  * Potentially perform a mode change.
2683  *
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:
2687  *
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):
2692  */
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)
2697 {
2698         struct drm_device* drm_dev;
2699         int err = PVRSRV_OK;
2700
2701         drm_dev = devinfo->drm_device;
2702
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;
2709                 }
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;
2724
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);
2733
2734
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;
2740                 }
2741
2742
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);
2747                 if (err) {
2748                         printk(KERN_ERR "The query_mode_list() function returned %d.", err);
2749                         return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2750                 }
2751                 EMGD_DEBUG("Comparing the mode list with the desired width, height, "
2752                                 "and stride...");
2753                 mode = mode_list;
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;
2763                                 break;
2764                         }
2765                         mode++;
2766                 }
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;
2774                 } else {
2775                         /* Must set this in order to get the timings setup: */
2776                         desired_mode->flags |= IGD_DISPLAY_ENABLE;
2777                 }
2778
2779
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));
2788
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);
2793                 if (err) {
2794                         printk(KERN_ERR "The alter_displays() function returned %d.", err);
2795                         return PVRSRV_ERROR_FAILED_DEPENDENCIES;
2796                 }
2797
2798
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;
2804
2805
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;
2811                 }
2812         } /* end of mode-change code */
2813
2814         return err;
2815 } /* do_mode_change() */