4fb5c244fb5280b4b56eadc6709e1f3442c7c7fc
[profile/ivi/intel-emgd-kmod.git] / emgd / drm / emgd_interface.c
1 /*-----------------------------------------------------------------------------
2  * Filename: emgd_interface.c
3  * $Revision: 1.191 $
4  *-----------------------------------------------------------------------------
5  * Copyright (c) 2002-2010, Intel Corporation.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  *-----------------------------------------------------------------------------
26  * Description:
27  *  This file implements the kernel-space bridge between the IAL and the HAL.
28  *  Each of the igd_dispatch_t functions are called by an ioctl's handling
29  *  function, that's implemented in this file.  All parameters coming from user
30  *  space are copied and sent to the HAL.  All return parameters and the
31  *  overall return value is copied back to the user-space bridge code.
32  *  See the description in the file "emgd_hal2drm.c" for more details.
33  *-----------------------------------------------------------------------------
34  */
35
36 #define MODULE_NAME hal.oal
37
38 #include "drmP.h"
39 #include "drm.h"
40
41 #include "drm_emgd_private.h"
42 #include "emgd_drm.h"
43 #include "emgd_drv.h"
44 #include "memory.h"
45
46 #include "module_init.h"
47 #include "mode_dispatch.h"
48 #include "ovl_dispatch.h"
49 #include "ovl_virt.h"
50 #include "msvdx.h"
51 #include "topaz.h"
52
53 #include "memmap.h"
54 #include "sched.h"
55
56 #include "services.h"
57 #include "perproc.h"
58 #include "pvr_bridge_km.h"
59 #include "syscommon.h"
60 #include "pvr_drm.h"
61
62 #include <linkage.h>
63
64 #include "pvrversion.h"
65
66 /* Turn on tracing for this file only */
67 /*
68 #undef EMGD_TRACE_ENTER
69 #define EMGD_TRACE_ENTER printk( KERN_ERR "%s Entry. ",__FUNCTION__)
70 */
71
72 /* The compile-time configuration found in "user_config.c": */
73 extern emgd_drm_config_t config_drm;
74 /* Module parameters from "emgd_drv.c": */
75 extern int drm_emgd_dc;
76 extern unsigned x_started;
77
78 extern void emgd_init_display(int merge_mod_params, drm_emgd_priv_t *priv);
79
80 /**
81  * The driver handle for talking with the HAL, within the DRM/kernel code.
82  * This is a "real handle" as opposed to the "fake handle" in user-space.
83  * Notice that there's only one handle, as the secondary device shares this
84  * handle, and so it is cached here to simplify the ioctl-handling procedures.
85  */
86 static igd_driver_h handle = NULL;
87 /** This is the dispatch table for the HAL.  It is cached for quick access. */
88 static igd_dispatch_t *dispatch = NULL;
89
90
91 /*!
92  * This is called by emgd_driver_load() once it has a "real" driver handle, to
93  * allow the values to be cached in this file.
94  *
95  * @param drm_handle (IN) the kernel-space HAL's "real" driver handle
96  */
97 void emgd_set_real_handle(igd_driver_h drm_handle)
98 {
99         handle = drm_handle;
100 } /* emgd_set_real_handle() */
101
102 /*!
103  * This is called by emgd_driver_load() once it has a "real" dispatch table, to
104  * allow the values to be cached in this file.
105  *
106  * @param drm_dispatch (OUT) the kernel-space HAL's dispatch table
107  */
108 void emgd_set_real_dispatch(igd_dispatch_t *drm_dispatch)
109 {
110         dispatch = drm_dispatch;
111 } /* emgd_set_real_dispatch() */
112
113
114 /*
115  * Externally-accessible global variables and functions, for PreInit()-time
116  * configuration:
117  */
118 extern mode_context_t mode_context[1];
119 extern void dsp_shutdown(igd_context_t *context);
120 extern int pi_pd_init(igd_display_port_t *port, unsigned long port_feature,
121         unsigned long second_port_feature, int drm_load_time);
122 #ifdef DEBUG_BUILD_TYPE
123 extern void emgd_print_params(igd_param_t *params);
124 #endif
125 extern void emgd_modeset_destroy(struct drm_device *dev);
126
127
128 /*
129  * NOTE: The rest of this file contains implementations of the HAL-to-DRM
130  * ioctl-handling procedures.
131  *
132  * The naming convention is:  emgd_<HAL-procedure-pointer-name>()
133  */
134
135
136 /*!
137  * IOCTL to get chipset information from DRM.
138  */
139 int emgd_get_chipset_info(struct drm_device *dev, void *arg,
140                 struct drm_file *file_priv)
141 {
142         emgd_drm_driver_get_chipset_info_t *drm_data = arg;
143         drm_emgd_priv_t *priv = dev->dev_private;
144
145         drm_data->device_id = priv->init_info->device_id;
146         drm_data->revision_id = priv->init_info->vendor_id;
147
148         /*
149          * Copy over the name and description fields.  Currently these
150          * are hard coded to a maximum of 40 and 20 characters respectively.
151          */
152         if (strlen(priv->init_info->name) > 39) {
153                 strncpy(drm_data->name, priv->init_info->name, 39);
154                 drm_data->name[39] = '\0';
155         } else {
156                 strcpy(drm_data->name, priv->init_info->name);
157         }
158
159         if (strlen(priv->init_info->chipset) > 19) {
160                 strncpy(drm_data->description, priv->init_info->chipset, 19);
161                 drm_data->description[19] = '\0';
162         } else {
163                 strcpy(drm_data->description, priv->init_info->chipset);
164         }
165
166         return 0;
167 }
168
169
170 int do_wait_vblank(void *display, int headline, int footline)
171 {
172         int rtn;
173         int scnlne;
174         os_alarm_t timeout;
175         int ext = -99999;
176         unsigned long height = PIPE((igd_display_context_t *)display)->timing->height;
177
178         /*EMGD_TRACE_ENTER;*/
179
180         if (footline + 50 > height)
181                 ext = IGD_IN_VBLANK;
182
183         timeout = OS_SET_ALARM(50);
184         do {
185                 /* Call the HAL: */
186                 rtn = dispatch->get_scanline((igd_display_context_t *)display, &scnlne);
187                 if (rtn || (scnlne >= footline && scnlne <= footline + 50) || ext == scnlne) {
188                         break;
189                 }
190                 OS_SCHEDULE();
191         } while (!OS_TEST_ALARM(timeout));
192
193         /*EMGD_DEBUG("rtn = %d", rtn);*/
194         /*EMGD_TRACE_EXIT;*/
195         return 0;
196 }
197
198 /*!
199  * IOCTL to bridge the IAL to the HAL's wait_vblank() procedure.
200  */
201 int emgd_wait_vblank(struct drm_device *dev, void *arg,
202         struct drm_file *file_priv)
203 {
204         int rtn;
205         emgd_drm_driver_set_sync_refresh_t *refresh = arg;
206         igd_display_h *display_handle = &(refresh->display_handle);
207
208         /*EMGD_TRACE_ENTER;*/
209         rtn = do_wait_vblank((igd_display_context_t *)(*display_handle), refresh->start_line, refresh->bottom_line);
210
211         /*EMGD_DEBUG("rtn = %d", rtn);*/
212         /*EMGD_TRACE_EXIT;*/
213         return 0;
214 } /* emgd_wait_vblank() */
215
216 /*!
217  * IOCTL to bridge the IAL to the HAL's alter_cursor() procedure.
218  */
219 int emgd_alter_cursor(struct drm_device *dev, void *arg,
220         struct drm_file *file_priv)
221 {
222         emgd_drm_alter_cursor_t *drm_data = arg;
223
224         /*EMGD_TRACE_ENTER;*/
225
226
227         /* Call the HAL: */
228         drm_data->rtn = dispatch->alter_cursor(drm_data->display_handle,
229                 &(drm_data->cursor_info),
230                 drm_data->image);
231
232
233         /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
234         /*EMGD_TRACE_EXIT;*/
235         return 0;
236 } /* emgd_alter_cursor() */
237
238
239 /*!
240  * IOCTL to bridge the IAL to the HAL's alter_cursor_pos() procedure.
241  */
242 int emgd_alter_cursor_pos(struct drm_device *dev, void *arg,
243         struct drm_file *file_priv)
244 {
245         emgd_drm_alter_cursor_pos_t *drm_data = arg;
246
247         /*EMGD_TRACE_ENTER;*/
248
249
250         /* Call the HAL: */
251         drm_data->rtn = dispatch->alter_cursor_pos(drm_data->display_handle,
252                 &(drm_data->cursor_info));
253
254
255         /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
256         /*EMGD_TRACE_EXIT;*/
257         return 0;
258 } /* emgd_alter_cursor_pos() */
259
260 /*!
261  * IOCTL to bridge the IAL to the HAL's emgd_get_display_info() procedure.
262  */
263 int emgd_get_display_info(struct drm_device *dev, void *arg,
264         struct drm_file *file_priv)
265 {
266   /*
267         emgd_drm_get_display_info_t *drm_data = arg;
268
269         igd_context_t *context = (igd_context_t *) handle;
270         drm_emgd_priv_t *priv = (drm_emgd_priv_t *)dev->dev_private;
271 */
272         EMGD_TRACE_ENTER;
273 /*
274         EMGD_DEBUG("drm_data->primary = 0x%lx",  (unsigned long) drm_data->primary);
275         EMGD_DEBUG("drm_data->secondary = 0x%lx",(unsigned long) drm_data->secondary);
276
277         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn); */
278         EMGD_TRACE_EXIT;
279         return 0;
280 } /* emgd_get_display_info() */
281
282 /*!
283  * IOCTL to bridge the IAL to the HAL's alter_displays() procedure.
284  */
285 int emgd_alter_displays(struct drm_device *dev, void *arg,
286         struct drm_file *file_priv)
287 {
288         emgd_drm_alter_displays_t *drm_data = arg;
289         drm_emgd_priv_t *priv = dev->dev_private;
290         int temp_dc = drm_data->dc;
291
292         EMGD_TRACE_ENTER;
293
294         /*
295          * If we are in Vertical Extended mode and the caller's dc is also
296          * Vertical Extended, then set it to Clone instead as our HAL doesn't
297          * know anything about Vertical Extended mode.
298          */
299         if(IGD_DC_VEXT(drm_data->dc)) {
300                 temp_dc = (drm_data->dc & ~IGD_DISPLAY_CONFIG_MASK) |
301                                 IGD_DISPLAY_CONFIG_CLONE;
302                 if (drm_data->primary_fb_info.height ==
303                         drm_data->secondary_fb_info.height) {
304                         if(drm_data->primary_pt_info.height ==
305                                         drm_data->primary_fb_info.height) {
306                                 drm_data->primary_fb_info.height *= 2;
307                         }
308
309                         if(drm_data->secondary_pt_info.height ==
310                                         drm_data->secondary_fb_info.height) {
311                                 drm_data->secondary_fb_info.height *= 2;
312                         }
313                 }
314         }
315
316         /* Call the HAL: */
317         drm_data->rtn = dispatch->alter_displays(handle,
318                 /* Note: Since a pointer is passed to drm_data->primary/secondary,
319                  * there's no need to copy anything back into drm_data, except
320                  * for the return value.
321                  */
322                 &(drm_data->primary),
323                 &(drm_data->primary_pt_info),
324                 &(drm_data->primary_fb_info),
325                 &(drm_data->secondary),
326                 &(drm_data->secondary_pt_info),
327                 &(drm_data->secondary_fb_info),
328                 temp_dc,
329                 drm_data->flags);
330
331         if (!drm_data->rtn) {
332                 /*
333                  * Special for Vertical Extended, pan the second display
334                  */
335                 if(IGD_DC_VEXT(drm_emgd_dc) && IGD_DC_VEXT(drm_data->dc)) {
336                         dispatch->pan_display(drm_data->secondary, 0,
337                                         drm_data->secondary_fb_info.height / 2);
338                 }
339                 /* Communicate the new info to the IMG 3rd-party display driver: */
340                 priv->dc = drm_data->dc;
341                 priv->primary = drm_data->primary;
342                 priv->secondary = drm_data->secondary;
343                 priv->primary_port_number = (drm_data->dc & 0xf0) >> 4;
344                 priv->secondary_port_number = (drm_data->dc & 0xf00000) >> 20;
345
346                 if (priv->must_power_on_ports) {
347                         /* The HAL was re-initialized during emgd_driver_pre_init()
348                          * (i.e. because the X server was restarted).  At that time, it
349                          * turned off the port drivers' hardware (so that it could poke new
350                          * values into the port drivers).  It couldn't turn the hardware
351                          * back on then.  Do so now.
352                          */
353                         igd_context_t *context = (igd_context_t *) handle;
354                         igd_display_port_t *port = NULL;
355
356                         while ((port = context->mod_dispatch.dsp_get_next_port(context,
357                                                 port, 0)) != NULL) {
358                                 /* only LVDS was turned off, so turn it back on */
359                                 if (port->pd_driver &&  (port->port_number == IGD_PORT_TYPE_LVDS)) {
360                                         EMGD_DEBUG("Turning on power for port %lu\n", port->port_number);
361
362                                         dispatch->power_display(context, port->port_number,
363                                                 IGD_POWERSTATE_D0);
364                                 }
365                         }
366                         priv->must_power_on_ports = 0;
367                 }
368
369                 if (priv->reinit_3dd) {
370                         priv->reinit_3dd(dev);
371                 }
372         }
373
374         EMGD_DEBUG("drm_data->primary = 0x%lx", (unsigned long) drm_data->primary);
375         EMGD_DEBUG("drm_data->secondary = 0x%lx",(unsigned long) drm_data->secondary);
376         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
377         EMGD_TRACE_EXIT;
378         return 0;
379 } /* emgd_alter_displays() */
380
381
382 /*!
383  * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
384  */
385 int emgd_alter_ovl(struct drm_device *dev, void *arg,
386         struct drm_file *file_priv)
387 {
388         emgd_drm_alter_ovl_t *drm_data = arg;
389
390         EMGD_TRACE_ENTER;
391         EMGD_DEBUG("Deprecated version of alter_ovl. FIX ME.");
392
393         /* Call the HAL: */
394         drm_data->rtn = dispatch->alter_ovl2(drm_data->display_handle,
395                 (igd_surface_t *) &(drm_data->src_surf),
396                 (igd_rect_t *) &(drm_data->src_rect),
397                 (igd_rect_t *) &(drm_data->dst_rect),
398                 (igd_ovl_info_t *) &(drm_data->ovl_info),
399                 drm_data->flags);
400
401         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
402         EMGD_TRACE_EXIT;
403         return 0;
404 } /* emgd_alter_ovl() */
405
406
407 /*!
408  * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
409  */
410 int emgd_alter_ovl2(struct drm_device *dev, void *arg,
411         struct drm_file *file_priv)
412 {
413         emgd_drm_alter_ovl2_t *drm_data = arg;
414
415         EMGD_TRACE_ENTER;
416         /* Dump the overlay parameters for debugging */
417         /*
418         printk (KERN_ERR "emgd_alter_ovl2 Entry."
419                 "offset=0x%X "
420                 "pitch=0x%X "
421                 "width=0x%X "
422                 "height=0x%X "
423                 "pixel_format=0x%X "
424                 "flags=0x%X "
425                 "virt_addr=0x%X "
426                 "pvr2d_mem_info=0x%X "
427                 "pvr2d_context_h=0x%X "
428                 "hPVR2DFlipChain=0x%X "
429                 "src_x1=0x%X "
430                 "src_x2=0x%X "
431                 "src_y1=0x%X "
432                 "src_y2=0x%X "
433                 "dest_x1=0x%X "
434                 "dest_x2=0x%X "
435                 "dest_y1=0x%X "
436                 "dest_y2=0x%X "
437                 "color_key.src_lo=0x%X "
438                 "color_key.src_hi=0x%X "
439                 "color_key.dest=0x%X "
440                 "color_key.flags=0x%X "
441                 "flags=0x%X "
442                 ,
443                 (unsigned int)drm_data->src_surf.offset ,
444                 (unsigned int)drm_data->src_surf.pitch ,
445                 (unsigned int)drm_data->src_surf.width ,
446                 (unsigned int)drm_data->src_surf.height ,
447                 (unsigned int)drm_data->src_surf.pixel_format ,
448                 (unsigned int)drm_data->src_surf.flags ,
449                 (unsigned int)drm_data->src_surf.virt_addr ,
450                 (unsigned int)drm_data->src_surf.pvr2d_mem_info ,
451                 (unsigned int)drm_data->src_surf.pvr2d_context_h ,
452                 (unsigned int)drm_data->src_surf.hPVR2DFlipChain ,
453                 (unsigned int)drm_data->src_rect.x1,
454                 (unsigned int)drm_data->src_rect.x2,
455                 (unsigned int)drm_data->src_rect.y1,
456                 (unsigned int)drm_data->src_rect.y2,
457                 (unsigned int)drm_data->dst_rect.x1,
458                 (unsigned int)drm_data->dst_rect.x2,
459                 (unsigned int)drm_data->dst_rect.y1,
460                 (unsigned int)drm_data->dst_rect.y2,
461                 (unsigned int)drm_data->ovl_info.color_key.src_lo,
462                 (unsigned int)drm_data->ovl_info.color_key.src_hi,
463                 (unsigned int)drm_data->ovl_info.color_key.dest,
464                 (unsigned int)drm_data->ovl_info.color_key.flags,
465                 (unsigned int)drm_data->flags
466                 );
467         */
468         switch (drm_data->cmd) {
469         case CMD_ALTER_OVL2:
470                 drm_data->rtn = dispatch->alter_ovl2(drm_data->display_handle,
471                                                                                          &(drm_data->src_surf),
472                                                                                          &(drm_data->src_rect),
473                                                                                          &(drm_data->dst_rect),
474                                                                  &(drm_data->ovl_info),
475                                                                      drm_data->flags);
476                 break;
477         case CMD_ALTER_OVL2_OSD:
478                 drm_data->rtn = dispatch->alter_ovl2_osd(drm_data->display_handle,
479                                              &(drm_data->src_surf),
480                                              &(drm_data->src_rect),
481                                              &(drm_data->dst_rect),
482                                              &(drm_data->ovl_info),
483                                              drm_data->flags);
484                 break;
485         default:
486                 break;
487         }
488
489         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
490         EMGD_TRACE_EXIT;
491
492         return 0;
493 } /* emgd_alter_ovl2() */
494
495
496 /*!
497  * IOCTL to bridge the IAL to the HAL's get_ovl_init_params() procedure.
498  */
499 int emgd_get_ovl_init_params(struct drm_device *dev, void *arg,
500         struct drm_file *file_priv)
501 {
502         emgd_drm_get_ovl_init_params_t *drm_data = arg;
503         ovl_um_context_t *ovl_um_context;
504
505         EMGD_TRACE_ENTER;
506
507         /* Call the HAL: */
508         /* there may not be a need to call the hal for this, since we have
509          * access to the overlay context.  We can probably just copy what we need
510          * from the context to the drm_data
511          */
512
513         if (!drm_data) {
514                 EMGD_DEBUG("Invalid drm_data in emgd_get_ovl_init_params.\n");
515                 return 0;
516         }
517
518         ovl_um_context = drm_data->ovl_um_context;
519
520         if (!ovl_um_context) {
521                 drm_data->rtn = -1;
522                 return 0;
523         }
524
525         drm_data->rtn = dispatch->get_ovl_init_params(handle, ovl_um_context);
526
527         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
528         EMGD_TRACE_EXIT;
529         return 0;
530 } /* emgd_get_ovl_init_params() */
531
532
533 /*!
534  * IOCTL to bridge the IAL to the HAL's appcontext_alloc() procedure.
535  */
536 int emgd_appcontext_alloc(struct drm_device *dev, void *arg,
537         struct drm_file *file_priv)
538 {
539         emgd_drm_appcontext_alloc_t *drm_data = arg;
540
541         EMGD_TRACE_ENTER;
542
543
544         /* Call the HAL: */
545         /* NOTE: the return value is different than normal: */
546         drm_data->appcontext_h =
547                 dispatch->appcontext_alloc(drm_data->display_handle,
548                         drm_data->priority,
549                         drm_data->flags);
550
551
552         EMGD_DEBUG("drm_data->appcontext_h = %p", drm_data->appcontext_h);
553         EMGD_TRACE_EXIT;
554         return 0;
555 } /* emgd_appcontext_alloc() */
556
557
558 /*!
559  * IOCTL to bridge the IAL to the HAL's appcontext_free() procedure.
560  */
561 int emgd_appcontext_free(struct drm_device *dev, void *arg,
562         struct drm_file *file_priv)
563 {
564         emgd_drm_appcontext_free_t *drm_data = arg;
565
566         EMGD_TRACE_ENTER;
567
568
569         /* Call the HAL: */
570         /* NOTE: no return value is desired: */
571         dispatch->appcontext_free(drm_data->display_handle,
572                 drm_data->priority,
573                 drm_data->appcontext_h);
574
575
576         EMGD_DEBUG("This function has no drm_data->rtn value");
577         EMGD_TRACE_EXIT;
578         return 0;
579 } /* emgd_appcontext_free() */
580
581
582 /*!
583  * IOCTL to bridge the IAL to the HAL's driver_save_restore() procedure.
584  */
585 int emgd_driver_save_restore(struct drm_device *dev, void *arg,
586         struct drm_file *file_priv)
587 {
588         drm_emgd_priv_t *priv = dev->dev_private;
589         emgd_drm_driver_save_restore_t *drm_data = arg;
590         unsigned long save_flags  = 0;
591
592         EMGD_TRACE_ENTER;
593
594         if (config_drm.init) {
595                 save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
596         }
597         else {
598                 save_flags = IGD_REG_SAVE_ALL;
599         }
600
601         /* Call the HAL: */
602         drm_data->rtn = dispatch->driver_save_restore(handle, save_flags);
603
604         /* Change the state of what's saved: */
605         if (priv->saved_registers == CONSOLE_STATE_SAVED) {
606                 priv->saved_registers = X_SERVER_STATE_SAVED;
607                 EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
608         } else {
609                 priv->saved_registers = CONSOLE_STATE_SAVED;
610                 EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
611         }
612
613         if (priv->saved_registers == X_SERVER_STATE_SAVED &&
614                 !priv->qb_seamless && !config_drm.kms && config_drm.init) {
615                 emgd_init_display(FALSE, priv);
616         }
617
618         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
619
620         EMGD_TRACE_EXIT;
621         return 0;
622 } /* emgd_driver_save_restore() */
623
624
625 /*!
626  * IOCTL to bridge the IAL to the HAL's enable_port() procedure.
627  */
628 int emgd_enable_port(struct drm_device *dev, void *arg,
629         struct drm_file *file_priv)
630 {
631         emgd_drm_enable_port_t *drm_data = arg;
632
633         EMGD_TRACE_ENTER;
634
635
636         /* Call the HAL: */
637         drm_data->rtn = dispatch->enable_port(drm_data->display_handle,
638                 drm_data->port_number,
639                 drm_data->flag,
640                 drm_data->test);
641
642
643         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
644         EMGD_TRACE_EXIT;
645         return 0;
646 } /* emgd_enable_port() */
647
648
649 /*!
650  * IOCTL to bridge the IAL to the HAL's get_attrs() procedure.
651  */
652 int emgd_get_attrs(struct drm_device *dev, void *arg,
653         struct drm_file *file_priv)
654 {
655         emgd_drm_get_attrs_t *drm_data = arg;
656         igd_attr_t *attr_list = NULL;
657         igd_attr_t *ext_list = NULL;
658         igd_extension_attr_t *tmp = NULL;
659         int i = 0;
660         int extended = 0;
661         int core_cnt = 0;
662         int ext_cnt = 0;
663
664         EMGD_TRACE_ENTER;
665
666
667         /* Call the HAL: */
668         drm_data->rtn = dispatch->get_attrs(handle,
669                 drm_data->port_number,
670                 &(drm_data->list_size),
671                 /* Note: get_attrs() returns a pointer to live data, that the caller
672                  * (i.e. this procedure) is not supposed to free/alter.  Therefore,
673                  * this data must be copied into the space pointed to by
674                  * drm_data->attr_list (assuming enough memory was allocated for it--if
675                  * not, the hal2drm code will allocate drm_data->list_size and call
676                  * this ioctl again).
677                  */
678                 &(attr_list));
679
680         /*
681          * The attribute list may have an extension list in addition to
682          * the core attributes.  The caller may want the core list or
683          * the extenstion list. Use the extended flag in drm_data to
684          * determine this.  If the caller is looking for the count, then
685          * return either core or extended size.
686          */
687
688         while ((i < drm_data->list_size) && (attr_list[i].id != PD_ATTR_LIST_END)){
689                 if (attr_list[i].id == PD_ATTR_ID_EXTENSION) {
690                         extended = 1;
691                         tmp = (igd_extension_attr_t *)&attr_list[i];
692                         ext_list = tmp->extension;
693
694                         /* Count extension attributes */
695                         while ((ext_cnt < drm_data->list_size) &&
696                                         (ext_list[ext_cnt].id != PD_ATTR_LIST_END)){
697                                 ext_cnt++;
698                         }
699                 }
700                 core_cnt++;
701                 i++;
702         }
703
704         if(drm_data->port_number == IGD_PORT_TYPE_LVDS) {
705                 /* LVDS port driver returns +1 is to include the end attribute */
706                 ext_cnt++;
707         }
708         if (drm_data->extended) {
709                 drm_data->list_size = ext_cnt; /* size of extension list */
710
711                 /* Copy the attribute array back to user-space, if enough room: */
712                 if ((drm_data->allocated_size > 0) &&
713                         (drm_data->list_size <= drm_data->allocated_size)) {
714                         OS_MEMCPY(drm_data->attr_list, ext_list,
715                                 (drm_data->list_size * sizeof(igd_attr_t)));
716                 }
717         } else {
718                 drm_data->list_size = core_cnt;
719
720                 /* Copy the attribute array back to user-space, if enough room: */
721                 if ((drm_data->allocated_size > 0) &&
722                         (drm_data->list_size <= drm_data->allocated_size)) {
723                         OS_MEMCPY(drm_data->attr_list, attr_list,
724                                 (drm_data->list_size * sizeof(igd_attr_t)));
725                 }
726         }
727
728
729         drm_data->extended = extended;
730
731         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
732         EMGD_TRACE_EXIT;
733         return 0;
734 } /* emgd_get_attrs() */
735
736
737 /*!
738  * IOCTL to bridge the IAL to the HAL's get_display() procedure.
739  */
740 int emgd_get_display(struct drm_device *dev, void *arg,
741         struct drm_file *file_priv)
742 {
743         igd_context_t *context = (igd_context_t *) handle;
744         emgd_drm_get_display_t *drm_data = arg;
745         igd_display_context_t *display =
746                 (igd_display_context_t *) drm_data->display_handle;
747         drm_emgd_priv_t *priv = dev->dev_private;
748         int dc, port_num;
749         int do_reinit_3dd = 1;
750
751         EMGD_TRACE_ENTER;
752
753         /* Can we overload this to get the display handle if it's null? */
754         if (display == NULL) {
755                 display = context->mod_dispatch.dsp_display_list[drm_data->port_number];
756                 drm_data->display_handle = display;
757         }
758
759         /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
760         if ((display == NULL) || (PORT(display, drm_data->port_number) == NULL)) {
761                 EMGD_ERROR_EXIT("emgd_get_display() given invalid display "
762                         "handle (0x%x) or port number (%d)", (unsigned int) display,
763                         drm_data->port_number);
764                 return -IGD_ERROR_INVAL;
765         }
766
767         dc = *(context->mod_dispatch.dsp_current_dc);
768         port_num = drm_data->port_number;
769
770         if (drm_data->flags & IGD_GET_DISPLAY_NO_3DD_REINIT){
771                 do_reinit_3dd = 0;
772                 drm_data->flags &= (~IGD_GET_DISPLAY_NO_3DD_REINIT);
773         }
774
775         /* Call the HAL: */
776         drm_data->rtn = dispatch->get_display(drm_data->display_handle,
777                 drm_data->port_number,
778                 /* Note: Since a pointer is passed to drm_data->fb_info/pt_info,
779                  * there's no need to copy anything back into drm_data, except
780                  * for the return value.
781                  */
782                 &(drm_data->fb_info),
783                 &(drm_data->pt_info),
784                 drm_data->flags);
785
786         /* In seamless mode this gets called instead of alter_displays */
787         /* The reason why we do not want to call reinit_3dd() if the clone mode is
788          * set and if this function was called to get the secondary handle is because
789          * reinit_3dd() calls init_display() which in turn calls get_display() and passes
790          * the handle for secondary, and primary port number hence leading to an incorrect
791          * combination. Also, we may not have to call reinit_3dd() as this is already done
792          * as a part of configuring the primary.
793          */
794         if (do_reinit_3dd) {
795                 if(mode_context->seamless && !(IGD_DC_CLONE(dc) && port_num == priv->secondary_port_number)) {
796                         if (priv->reinit_3dd) {
797                                 if(IGD_DC_VEXT(drm_emgd_dc)) {
798                                         priv->dc = drm_emgd_dc;
799                                 } else {
800                                         priv->dc = *(context->mod_dispatch.dsp_current_dc);
801                                 }
802                                 EMGD_DEBUG("priv->dc = 0x%lX", priv->dc);
803                                 priv->primary = drm_data->display_handle;
804                                 priv->secondary = NULL;
805                                 priv->primary_port_number = (priv->dc & 0xf0) >> 4;
806                                 priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
807                                 priv->reinit_3dd(dev);
808                         }
809                 }
810         }
811
812
813         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
814         EMGD_TRACE_EXIT;
815         return 0;
816 } /* emgd_get_display() */
817
818
819 /*!
820  * IOCTL to support emgd_hal2drm_drm_config(), which returns to the X driver
821  * the igd_param_t that was used at load time, as well as the "config ID" that
822  * was either specified by the "configid" module parameter of stored in the
823  * VBOIS (by calling igd_get_param(...,IGD_PARAM_PANEL_ID,...)).
824  */
825 int emgd_get_drm_config(struct drm_device *dev, void *arg,
826         struct drm_file *file_priv)
827 {
828         emgd_drm_get_drm_config_t *drm_data = arg;
829         igd_param_t *params;
830         int i;
831
832
833         EMGD_TRACE_ENTER;
834
835
836         /*
837          * Return the igd_param_t parameter values used at module load time:
838          */
839         if (drm_emgd_configid < 0) {
840                 params = config_drm.hal_params[0];
841         } else {
842                 params = config_drm.hal_params[drm_emgd_configid-1];
843         }
844         if (config_drm.init) {
845                 drm_data->display_config = drm_emgd_dc;
846         } else {
847                 drm_data->display_config = config_drm.dc;
848         }
849         drm_data->params.page_request = params->page_request;
850         drm_data->params.max_fb_size = params->max_fb_size;
851         drm_data->params.preserve_regs = params->preserve_regs;
852         drm_data->params.display_flags = params->display_flags;
853         drm_data->params.display_color = params->display_color;
854         drm_data->params.quickboot = params->quickboot;
855         drm_data->params.qb_seamless = params->qb_seamless;
856         drm_data->params.qb_video_input = params->qb_video_input;
857         drm_data->params.qb_splash = params->qb_splash;
858         drm_data->params.polling = params->polling;
859         drm_data->params.ref_freq = params->ref_freq;
860         drm_data->params.tuning_wa = params->tuning_wa;
861         drm_data->params.clip_hw_fix = params->clip_hw_fix;
862         drm_data->params.async_flip_wa = params->async_flip_wa;
863         drm_data->params.en_reg_override = params->en_reg_override;
864         drm_data->params.disp_arb = params->disp_arb;
865         drm_data->params.fifo_watermark1 = params->fifo_watermark1;
866         drm_data->params.fifo_watermark2 = params->fifo_watermark2;
867         drm_data->params.fifo_watermark3 = params->fifo_watermark3;
868         drm_data->params.fifo_watermark4 = params->fifo_watermark4;
869         drm_data->params.fifo_watermark5 = params->fifo_watermark5;
870         drm_data->params.fifo_watermark6 = params->fifo_watermark6;
871         drm_data->params.gvd_hp_control = params->gvd_hp_control;
872         drm_data->params.bunit_chicken_bits = params->bunit_chicken_bits;
873         drm_data->params.bunit_write_flush = params->bunit_write_flush;
874         drm_data->params.disp_chicken_bits = params->disp_chicken_bits;
875         drm_data->params.punt_to_3dblit = params->punt_to_3dblit;
876
877         for (i = 0 ; i < IGD_MAX_PORTS ; i++) {
878                 drm_data->params.port_order[i] = params->port_order[i];
879                 drm_data->params.display_params[i].port_number =
880                         params->display_params[i].port_number;
881                 drm_data->params.display_params[i].present_params =
882                         (params->display_params[i].present_params &
883                                 ~(IGD_PARAM_DTD_LIST | IGD_PARAM_ATTR_LIST));
884                 drm_data->params.display_params[i].flags =
885                         params->display_params[i].flags;
886                 drm_data->params.display_params[i].edid_avail =
887                         params->display_params[i].edid_avail;
888                 drm_data->params.display_params[i].edid_not_avail =
889                         params->display_params[i].edid_not_avail;
890                 drm_data->params.display_params[i].ddc_gpio =
891                         params->display_params[i].ddc_gpio;
892                 drm_data->params.display_params[i].ddc_speed =
893                         params->display_params[i].ddc_speed;
894                 drm_data->params.display_params[i].ddc_dab =
895                         params->display_params[i].ddc_dab;
896                 drm_data->params.display_params[i].i2c_gpio =
897                         params->display_params[i].i2c_gpio;
898                 drm_data->params.display_params[i].i2c_speed =
899                         params->display_params[i].i2c_speed;
900                 drm_data->params.display_params[i].i2c_dab =
901                         params->display_params[i].i2c_dab;
902                 drm_data->params.display_params[i].fp_info =
903                         params->display_params[i].fp_info;
904                 /* No DTDs nor attrs are sent up.  If "xorg.conf" lists none, the
905                  * defaults (in "user_config.c") are still in force.  If anything
906                  * is listed in "xorg.conf", it overrides the defaults.  Thus,
907                  * there's no need to send them up.
908                  */
909         }
910
911         /*
912          * Return the "ConfigID" to return (either the module parameter or the
913          * value stored in VBIOS:
914          */
915         if (drm_emgd_configid > 0) {
916                 drm_data->config_id = drm_emgd_configid;
917         } else {
918                 /* Call the HAL: */
919                 int err = igd_get_param(handle, IGD_PARAM_PANEL_ID,
920                         /* Note: Since a pointer is passed to drm_data->value,
921                          * there's no need to copy anything back into drm_data, except
922                          * for the return value.
923                          */
924                         &drm_data->config_id);
925                 if (err) {
926                         /* Either the vBIOS doesn't exist, or there was a problem reading
927                          * it.  Either way, don't error; just set the config_id to an
928                          * invalid value:
929                          */
930                         drm_data->config_id = -1;
931                 }
932         }
933
934         /* Fill in DDK & EMGD version numbers and debug status */
935         drm_data->build_config.ddk_version = PVRVERSION_BUILD;
936         drm_data->build_config.emgd_version = IGD_BUILD_NUM;
937 #ifdef DEBUG
938         drm_data->build_config.debug = 1;
939 #else
940         drm_data->build_config.debug = 0;
941 #endif
942
943         drm_data->rtn = 0;
944         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
945         EMGD_TRACE_EXIT;
946         return 0;
947 } /* emgd_get_drm_config() */
948
949
950 /*!
951  * IOCTL to bridge the IAL to the HAL's get_EDID_block() procedure.
952  */
953 int emgd_get_EDID_block(struct drm_device *dev, void *arg,
954         struct drm_file *file_priv)
955 {
956         emgd_drm_get_EDID_block_t *drm_data = arg;
957
958         EMGD_TRACE_ENTER;
959
960
961         /* Call the HAL: */
962         drm_data->rtn = dispatch->get_EDID_block(handle,
963                 drm_data->port_number,
964                 /* Note: Since a pointer is passed to drm_data->edid_block,
965                  * there's no need to copy anything back into drm_data, except
966                  * for the return value.
967                  */
968                 drm_data->edid_block,
969                 drm_data->block_number);
970
971
972         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
973         EMGD_TRACE_EXIT;
974         return 0;
975 } /* emgd_get_EDID_block() */
976
977
978 /*!
979  * IOCTL to bridge the IAL to the HAL's get_EDID_info() procedure.
980  */
981 int emgd_get_EDID_info(struct drm_device *dev, void *arg,
982         struct drm_file *file_priv)
983 {
984         emgd_drm_get_EDID_info_t *drm_data = arg;
985
986         EMGD_TRACE_ENTER;
987
988
989         /* Call the HAL: */
990         drm_data->rtn = dispatch->get_EDID_info(handle,
991                 drm_data->port_number,
992                 /* Note: Since a pointer is passed to drm_data->edid_*,
993                  * there's no need to copy anything back into drm_data, except
994                  * for the return value.
995                  */
996                 &(drm_data->edid_version),
997                 &(drm_data->edid_revision),
998                 &(drm_data->edid_size));
999
1000
1001         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1002         EMGD_TRACE_EXIT;
1003         return 0;
1004 } /* emgd_get_EDID_info() */
1005
1006
1007 /*!
1008  * IOCTL to bridge the IAL to the HAL's get_pixelformats() procedure.
1009  */
1010 int emgd_get_pixelformats(struct drm_device *dev, void *arg,
1011         struct drm_file *file_priv)
1012 {
1013         emgd_drm_get_pixelformats_t *drm_data = arg;
1014         unsigned long *format_list = NULL;
1015         unsigned long *fb_list_pfs = NULL;
1016         unsigned long *cu_list_pfs = NULL;
1017         unsigned long *overlay_pfs = NULL;
1018         unsigned long *render_pfs = NULL;
1019         unsigned long *texture_pfs = NULL;
1020         unsigned long *pf;
1021         int count = 1;
1022
1023         EMGD_TRACE_ENTER;
1024
1025
1026         /* The HAL's get_pixelformats() procedure determines which formats are
1027          * wanted based on whether a pointer is NULL or not, and so we need to make
1028          * the desired-format's pointer non-NULL (setting it to 1 works, though it
1029          * is kinda cheating:-):
1030          */
1031         if (drm_data->format == PIXEL_FORMAT_FRAMEBUFFER) {
1032                 fb_list_pfs = (unsigned long *) 1;
1033         } else if (drm_data->format == PIXEL_FORMAT_CURSOR) {
1034                 cu_list_pfs = (unsigned long *) 1;
1035         } else if (drm_data->format == PIXEL_FORMAT_OVERLAY) {
1036                 overlay_pfs = (unsigned long *) 1;
1037         } else if (drm_data->format == PIXEL_FORMAT_RENDER) {
1038                 render_pfs = (unsigned long *) 1;
1039         } else if (drm_data->format == PIXEL_FORMAT_TEXTURE) {
1040                 texture_pfs = (unsigned long *) 1;
1041         }
1042
1043
1044         /* Call the HAL: */
1045         drm_data->rtn = dispatch->get_pixelformats(drm_data->display_handle,
1046                 &fb_list_pfs, &cu_list_pfs, &overlay_pfs, &render_pfs, &texture_pfs);
1047
1048
1049         /* Next, point format_list at the correct list: */
1050         if (drm_data->format == PIXEL_FORMAT_FRAMEBUFFER) {
1051                 format_list = fb_list_pfs;
1052         } else if (drm_data->format == PIXEL_FORMAT_CURSOR) {
1053                 format_list = cu_list_pfs;
1054         } else if (drm_data->format == PIXEL_FORMAT_OVERLAY) {
1055                 format_list = overlay_pfs;
1056         } else if (drm_data->format == PIXEL_FORMAT_RENDER) {
1057                 format_list = render_pfs;
1058         } else if (drm_data->format == PIXEL_FORMAT_TEXTURE) {
1059                 format_list = texture_pfs;
1060         }
1061
1062
1063         /* Count how many pixelformats were returned: */
1064         pf = format_list;
1065         while (*pf) {
1066                 pf++;
1067                 count++;
1068         }
1069         drm_data->list_size = count;
1070
1071
1072         /* Copy the pixel format list/array back to user-space, if enough room.  If
1073          * there isn't enough memory allocated, the hal2drm code will allocate
1074          * drm_data->list_size and call this ioctl again).
1075          */
1076         if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
1077                 OS_MEMCPY(drm_data->format_list, format_list,
1078                         (count * sizeof(unsigned long)));
1079         }
1080
1081         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1082         EMGD_TRACE_EXIT;
1083         return 0;
1084 } /* emgd_get_pixelformats() */
1085
1086
1087 /*!
1088  * IOCTL to bridge the IAL to the HAL's get_port_info() procedure.
1089  */
1090 int emgd_get_port_info(struct drm_device *dev, void *arg,
1091         struct drm_file *file_priv)
1092 {
1093         emgd_drm_get_port_info_t *drm_data = arg;
1094
1095         EMGD_TRACE_ENTER;
1096
1097
1098         /* Call the HAL: */
1099         drm_data->rtn = dispatch->get_port_info(handle,
1100                 drm_data->port_number,
1101                 /* Note: Since a pointer is passed to drm_data->port_info,
1102                  * there's no need to copy anything back into drm_data, except
1103                  * for the return value.
1104                  */
1105                 &(drm_data->port_info));
1106
1107
1108         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1109         EMGD_TRACE_EXIT;
1110         return 0;
1111 } /* emgd_get_port_info() */
1112
1113
1114 /*!
1115  * IOCTL to bridge the IAL to the HAL's gmm_alloc_region() procedure.
1116  */
1117 int emgd_gmm_alloc_region(struct drm_device *dev, void *arg,
1118         struct drm_file *file_priv)
1119 {
1120         emgd_drm_gmm_alloc_region_t *drm_data = arg;
1121
1122         EMGD_TRACE_ENTER;
1123
1124
1125         /* Call the HAL: */
1126         drm_data->rtn = dispatch->gmm_alloc_region(
1127                 /* Note: Since a pointer is passed to drm_data->offset/size,
1128                  * there's no need to copy anything back into drm_data, except
1129                  * for the return value.
1130                  */
1131                 &(drm_data->offset),
1132                 &(drm_data->size),
1133                 drm_data->type,
1134                 drm_data->flags);
1135
1136
1137         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1138         EMGD_TRACE_EXIT;
1139         return 0;
1140 } /* emgd_gmm_alloc_region() */
1141
1142
1143 /*!
1144  * IOCTL to bridge the IAL to the HAL's gmm_alloc_surface() procedure.
1145  */
1146 int emgd_gmm_alloc_surface(struct drm_device *dev, void *arg,
1147         struct drm_file *file_priv)
1148 {
1149         emgd_drm_gmm_alloc_surface_t *drm_data = arg;
1150
1151         EMGD_TRACE_ENTER;
1152
1153
1154         /* Call the HAL: */
1155         drm_data->rtn = dispatch->gmm_alloc_surface(
1156                 /* Note: Since a pointer is passed to drm_data->*,
1157                  * there's no need to copy anything back into drm_data, except
1158                  * for the return value.
1159                  */
1160                 &(drm_data->offset),
1161                 drm_data->pixel_format,
1162                 &(drm_data->width),
1163                 &(drm_data->height),
1164                 &(drm_data->pitch),
1165                 &(drm_data->size),
1166                 drm_data->type,
1167                 &(drm_data->flags));
1168
1169
1170         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1171         EMGD_TRACE_EXIT;
1172         return 0;
1173 } /* emgd_gmm_alloc_surface() */
1174
1175 int emgd_gmm_get_num_surface(struct drm_device *dev, void *arg,
1176         struct drm_file *file_priv)
1177 {
1178         emgd_drm_gmm_get_num_surface_t *drm_data = arg;
1179         EMGD_TRACE_ENTER;
1180
1181         drm_data->rtn = dispatch->gmm_get_num_surface(
1182                 &(drm_data->count));
1183
1184         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1185         EMGD_TRACE_EXIT;
1186         return 0;
1187 }
1188
1189 int emgd_gmm_get_surface_list(struct drm_device *dev, void *arg,
1190         struct drm_file *file_priv)
1191 {
1192         emgd_drm_gmm_get_surface_list_t *drm_data = arg;
1193         igd_surface_list_t *surface_list = NULL;
1194         EMGD_TRACE_ENTER;
1195
1196         drm_data->rtn = dispatch->gmm_get_surface_list(
1197                 drm_data->allocated_size,
1198                 &(drm_data->list_size),
1199                 &(surface_list));
1200
1201         /* Copy the surface array back to user-space, if enough room */
1202         if ((drm_data->allocated_size > 0) &&
1203                 (drm_data->list_size <= drm_data->allocated_size)) {
1204                 OS_MEMCPY(*(drm_data->surface_list), surface_list,
1205                         (drm_data->list_size * sizeof(igd_surface_list_t)));
1206         }
1207
1208         vfree(surface_list);
1209
1210         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1211         EMGD_TRACE_EXIT;
1212         return 0;
1213 }
1214
1215 /*!
1216  * IOCTL to bridge the IAL to the HAL's gmm_free() procedure.
1217  */
1218 int emgd_gmm_free(struct drm_device *dev, void *arg,
1219         struct drm_file *file_priv)
1220 {
1221         emgd_drm_gmm_free_t *drm_data = arg;
1222
1223         EMGD_TRACE_ENTER;
1224
1225
1226         /* Call the HAL: */
1227         /* NOTE: no return value is desired: */
1228         dispatch->gmm_free(drm_data->offset);
1229
1230
1231         EMGD_DEBUG("This function has no drm_data->rtn value");
1232         EMGD_TRACE_EXIT;
1233         return 0;
1234 } /* emgd_gmm_free() */
1235
1236
1237 /*!
1238  * IOCTL to bridge the IAL to the HAL's gmm_flush_cache() procedure.
1239  */
1240 int emgd_gmm_flush_cache(struct drm_device *dev, void *arg,
1241         struct drm_file *file_priv)
1242 {
1243         emgd_drm_gmm_flush_cache_t *drm_data = arg;
1244
1245         EMGD_TRACE_ENTER;
1246
1247
1248         /* Call the HAL: */
1249         drm_data->rtn = dispatch->gmm_flush_cache();
1250
1251
1252         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1253         EMGD_TRACE_EXIT;
1254         return 0;
1255 } /* emgd_gmm_flush_cache() */
1256
1257
1258 /*!
1259  * IOCTL to bridge the IAL to the HAL's pan_display() procedure.
1260  */
1261 int emgd_pan_display(struct drm_device *dev, void *arg,
1262         struct drm_file *file_priv)
1263 {
1264         emgd_drm_pan_display_t *drm_data = arg;
1265
1266         EMGD_TRACE_ENTER;
1267
1268
1269         /* Call the HAL: */
1270         /* NOTE: the return value is different than normal: */
1271         drm_data->rtn = dispatch->pan_display(drm_data->display_handle,
1272                 drm_data->x_offset,
1273                 drm_data->y_offset);
1274
1275
1276         EMGD_DEBUG("drm_data->rtn = %ld", drm_data->rtn);
1277         EMGD_TRACE_EXIT;
1278         return 0;
1279 } /* emgd_pan_display() */
1280
1281
1282 /*!
1283  * IOCTL to bridge the IAL to the HAL's power_display() procedure.
1284  */
1285 int emgd_power_display(struct drm_device *dev, void *arg,
1286         struct drm_file *file_priv)
1287 {
1288         emgd_drm_power_display_t *drm_data = arg;
1289         igd_context_t *context = (igd_context_t *) handle;
1290         igd_display_context_t *display;
1291
1292         EMGD_TRACE_ENTER;
1293
1294
1295         /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
1296         display = context->mod_dispatch.dsp_display_list[drm_data->port_number];
1297         if ((display == NULL) || (PORT(display, drm_data->port_number) == NULL)) {
1298                 EMGD_ERROR_EXIT("emgd_power_display() given an invalid port "
1299                         "number (%d)\n", drm_data->port_number);
1300                 return -IGD_ERROR_INVAL;
1301         }
1302
1303
1304         /* Call the HAL: */
1305         drm_data->rtn = dispatch->power_display(handle,
1306                 drm_data->port_number,
1307                 drm_data->power_state);
1308
1309
1310         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1311         EMGD_TRACE_EXIT;
1312         return 0;
1313 } /* emgd_power_display() */
1314
1315
1316 /*!
1317  * IOCTL to bridge the IAL to the HAL's pwr_alter() procedure.
1318  */
1319 int emgd_pwr_alter(struct drm_device *dev, void *arg,
1320         struct drm_file *file_priv)
1321 {
1322         emgd_drm_pwr_alter_t *drm_data = arg;
1323
1324         EMGD_TRACE_ENTER;
1325
1326
1327         /* Call the HAL: */
1328         drm_data->rtn = dispatch->pwr_alter(handle, drm_data->power_state);
1329
1330
1331         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1332         EMGD_TRACE_EXIT;
1333         return 0;
1334 } /* emgd_pwr_alter() */
1335
1336
1337 /*!
1338  * IOCTL to bridge the IAL to the HAL's query_dc() procedure.
1339  */
1340 int emgd_query_dc(struct drm_device *dev, void *arg,
1341         struct drm_file *file_priv)
1342 {
1343         emgd_drm_query_dc_t *drm_data = arg;
1344         unsigned long *dc_list = NULL;
1345         unsigned long *dc;
1346         int count = 1;
1347
1348         EMGD_TRACE_ENTER;
1349
1350
1351         /* Next, We don't need to copy the DC list from user-space, since
1352          * the HAL is going to point us to its internal list.
1353          */
1354
1355
1356         /* Call the HAL: */
1357         drm_data->rtn = dispatch->query_dc(handle,
1358                 drm_data->request,
1359                 /* Note: query_dc() returns a pointer to its live internal list, that
1360                  * the caller (i.e. this procedure) is not supposed to free/alter.
1361                  * Therefore, this data must be copied into the space pointed to by
1362                  * drm_data->dc_list (assuming enough memory was allocated for it--if
1363                  * not, the hal2drm code will allocate drm_data->list_size and call
1364                  * this ioctl again).
1365                  */
1366                 &dc_list,
1367                 drm_data->flags);
1368
1369
1370         /* Count how many DCs were returned: */
1371         if(dc_list == NULL){
1372                 EMGD_ERROR("query_dc() returned NULL !");
1373                 return 1;
1374         }
1375         dc = dc_list;
1376         while (*dc) {
1377                 dc++;
1378                 count++;
1379         }
1380
1381         drm_data->list_size = count;
1382         EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
1383
1384
1385         /* Copy the DC list back to user-space, if enough room: */
1386         if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
1387                 EMGD_DEBUG("Copying list");
1388                 OS_MEMCPY(drm_data->dc_list, dc_list, (count * sizeof(unsigned long)));
1389                 EMGD_DEBUG("Copied list");
1390         }
1391
1392
1393         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1394         EMGD_TRACE_EXIT;
1395         return 0;
1396 } /* emgd_query_dc() */
1397
1398
1399 /*!
1400  * IOCTL to bridge the IAL to the HAL's query_max_size_ovl() procedure.
1401  */
1402 int emgd_query_max_size_ovl(struct drm_device *dev, void *arg,
1403         struct drm_file *file_priv)
1404 {
1405         emgd_drm_query_max_size_ovl_t *drm_data = arg;
1406
1407         EMGD_TRACE_ENTER;
1408
1409
1410         /* Call the HAL: */
1411         drm_data->rtn = dispatch->query_max_size_ovl(drm_data->display_handle,
1412                 drm_data->pf,
1413                 /* Note: Since a pointer is passed to drm_data->*,
1414                  * there's no need to copy anything back into drm_data, except
1415                  * for the return value.
1416                  */
1417                 &(drm_data->max_width),
1418                 &(drm_data->max_height));
1419
1420
1421         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1422         EMGD_TRACE_EXIT;
1423         return 0;
1424 } /* emgd_query_max_size_ovl() */
1425
1426
1427 /*!
1428  * IOCTL to bridge the IAL to the HAL's query_ovl() procedure.
1429  */
1430 int emgd_query_ovl(struct drm_device *dev, void *arg,
1431         struct drm_file *file_priv)
1432 {
1433         emgd_drm_query_ovl_t *drm_data = arg;
1434
1435         EMGD_TRACE_ENTER;
1436
1437
1438         /* Call the HAL: */
1439         drm_data->rtn = dispatch->query_ovl(drm_data->display_handle,
1440                 drm_data->flags);
1441
1442         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1443         EMGD_TRACE_EXIT;
1444         return 0;
1445 } /* emgd_query_ovl() */
1446
1447
1448 /*!
1449  * IOCTL to bridge the IAL to the HAL's query_mode_list() procedure.
1450  */
1451 int emgd_query_mode_list(struct drm_device *dev, void *arg,
1452         struct drm_file *file_priv)
1453 {
1454         emgd_drm_query_mode_list_t *drm_data = arg;
1455         igd_display_info_t *mode_list = NULL;
1456         igd_display_info_t *mode;
1457         int count = 1;
1458
1459         EMGD_TRACE_ENTER;
1460
1461
1462         /* Call the HAL: */
1463         drm_data->rtn = dispatch->query_mode_list(handle,
1464                 drm_data->dc,
1465                 /* Note: query_mode_list() **MAY** return a pointer to live data, that
1466                  * the caller (i.e. this procedure) is not supposed to free/alter.
1467                  * Therefore, this data is copied into the space pointed to by
1468                  * drm_data->mode_list (assuming enough memory was allocated for it--if
1469                  * not, the hal2drm code will allocate drm_data->list_size and call
1470                  * this ioctl again).
1471                  */
1472                 &mode_list,
1473                 drm_data->flags);
1474
1475
1476         /* Count how many modes were returned: */
1477         mode = mode_list;
1478         while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
1479                 mode++;
1480                 count++;
1481         }
1482         drm_data->list_size = count;
1483         EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
1484
1485
1486         /* Next, copy the mode list back to user-space: */
1487         if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
1488                 EMGD_DEBUG("Copying list");
1489                 OS_MEMCPY(drm_data->mode_list, mode_list,
1490                         (count * sizeof(igd_display_info_t)));
1491                 EMGD_DEBUG("Copied list");
1492         }
1493
1494         /* Finally, if a non-live list was requested, free the kernel memory: */
1495         if (!(drm_data->flags & IGD_QUERY_LIVE_MODES)) {
1496                 dispatch->free_mode_list(mode_list);
1497         }
1498
1499         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1500         EMGD_TRACE_EXIT;
1501         return 0;
1502 } /* emgd_query_mode_list() */
1503
1504
1505 /*!
1506  * IOCTL to bridge the IAL to the HAL's set_attrs() procedure.
1507  */
1508 int emgd_set_attrs(struct drm_device *dev, void *arg,
1509         struct drm_file *file_priv)
1510 {
1511         emgd_drm_set_attrs_t *drm_data = arg;
1512         igd_attr_t *attr_list = drm_data->attr_list;
1513
1514         EMGD_TRACE_ENTER;
1515
1516
1517         /* Call the HAL: */
1518         drm_data->rtn = dispatch->set_attrs(handle,
1519                 drm_data->port_number,
1520                 /* Note: Since a pointer is passed to drm_data->num_attrs and
1521                  * drm_data->attr_list, there's no need to copy anything back into
1522                  * drm_data, except for the return value.
1523                  */
1524                 drm_data->list_size,
1525                 attr_list);
1526
1527
1528         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1529         EMGD_TRACE_EXIT;
1530         return 0;
1531 } /* emgd_set_attrs() */
1532
1533
1534 /*!
1535  * IOCTL to bridge the IAL to the HAL's set_palette_entry() procedure.
1536  */
1537 int emgd_set_palette_entry(struct drm_device *dev, void *arg,
1538         struct drm_file *file_priv)
1539 {
1540         emgd_drm_set_palette_entry_t *drm_data = arg;
1541
1542         /*EMGD_TRACE_ENTER;*/
1543
1544
1545         /* Call the HAL: */
1546         drm_data->rtn = dispatch->set_palette_entry(drm_data->display_handle,
1547                 drm_data->palette_entry,
1548                 drm_data->palette_color);
1549
1550
1551         /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
1552         /*EMGD_TRACE_EXIT;*/
1553         return 0;
1554 } /* emgd_set_palette_entry() */
1555
1556
1557 /*!
1558  * IOCTL to bridge the IAL to the HAL's set_surface() procedure.
1559  */
1560 int emgd_set_surface(struct drm_device *dev, void *arg,
1561         struct drm_file *file_priv)
1562 {
1563         emgd_drm_set_surface_t *drm_data = arg;
1564
1565         EMGD_TRACE_ENTER;
1566
1567
1568         /* Call the HAL: */
1569         drm_data->rtn = dispatch->set_surface(drm_data->display_handle,
1570                 drm_data->priority,
1571                 drm_data->type,
1572                 &(drm_data->surface),
1573                 drm_data->appcontext,
1574                 drm_data->flags);
1575
1576
1577         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1578         EMGD_TRACE_EXIT;
1579         return 0;
1580 } /* emgd_set_surface() */
1581
1582
1583
1584 /*!
1585  * IOCTL to set surface to dih_clone or back to dih.
1586  * drm_data->mode = CLONE - sets fake clone clone
1587  * drm_data->mode = DIH - reverts back to DIH
1588  * drm_data->dih_clone_display = CLONE_PRIMARY, primary cloned
1589  * drm_data->dih_clone_display = CLONE_SECONDARY, secondary cloned
1590  *
1591  */
1592 int emgd_dihclone_set_surface(struct drm_device *dev, void *arg,
1593         struct drm_file *file_priv)
1594 {
1595         emgd_drm_dihclone_set_surface_t *drm_data = arg;
1596         igd_context_t *context = (igd_context_t *) handle;
1597         igd_plane_t *display_plane1, *display_plane2;
1598         igd_display_pipe_t *pipe1, *pipe2;
1599         igd_display_context_t *display;
1600         igd_surface_t surf;
1601         unsigned long dc ;
1602         unsigned long x_offset, y_offset;
1603
1604         EMGD_TRACE_ENTER;
1605
1606         memset(&surf, 0, sizeof(igd_surface_t));
1607         dc = *(context->mod_dispatch.dsp_current_dc);
1608
1609         context->mod_dispatch.dsp_get_planes_pipes(
1610                         &display_plane1, &display_plane2,
1611                         &pipe1, &pipe2);
1612
1613         /* check if the resolutions match */
1614         if((pipe1->plane->fb_info->width != pipe2->plane->fb_info->width) ||
1615                 (pipe1->plane->fb_info->height != pipe2->plane->fb_info->height)){
1616                         EMGD_ERROR(" emgd_dihclone_set_surface: resolutions don't match");
1617                 return -IGD_ERROR_INVAL;
1618         }
1619
1620
1621         if( drm_data->dih_clone_display != CLONE_PRIMARY && drm_data->dih_clone_display != CLONE_SECONDARY){
1622
1623                 EMGD_ERROR(" emgd_dihclone_set_surface: Invalid Clone Display number");
1624                 return -IGD_ERROR_INVAL;
1625         }
1626
1627         surf.pitch = pipe1->plane->fb_info->screen_pitch;
1628         surf.width =  pipe1->plane->fb_info->width;
1629         surf.height =  pipe1->plane->fb_info->height;
1630         surf.pixel_format =  pipe1->plane->fb_info->pixel_format;
1631         surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
1632
1633         display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1634
1635         /*reverting back to DIH from fake clone */
1636         if( drm_data->mode == DIH){
1637                 if (IGD_DC_VEXT(drm_emgd_dc)) {
1638                         /* Clone to VEXT */
1639                         x_offset = 0;
1640
1641                         y_offset = 0;
1642                         display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1643                         /* Call pan display to revert Primary to VEXT */
1644                         drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
1645
1646                         y_offset = (pipe1->plane->fb_info->height / 2);
1647                         display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1648                         /* Call pan_display to revert Secondary to VEXT */
1649                         drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
1650                 }else {/* in DIH mode */
1651
1652                         if(context->mod_dispatch.dih_clone_display == CLONE_PRIMARY) {
1653
1654                                 EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH1");
1655                                 surf.offset = pipe1->plane->fb_info->fb_base_offset;
1656                                 /* Call the HAL: */
1657                                 drm_data->rtn = dispatch->set_surface(display,
1658                                                 IGD_PRIORITY_NORMAL,
1659                                                 IGD_BUFFER_DISPLAY,
1660                                                 &surf,
1661                                                 NULL,
1662                                                 0);
1663
1664                                 if(drm_data->rtn) {
1665                                         EMGD_ERROR(" emgd_dihclone_set_surface1: failed");
1666                                         return -IGD_ERROR_INVAL;
1667                                 }
1668                                 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1669                                 surf.offset = pipe2->plane->fb_info->saved_offset;
1670                                 /* Call the HAL: */
1671                                 drm_data->rtn = dispatch->set_surface(display,
1672                                                 IGD_PRIORITY_NORMAL,
1673                                                 IGD_BUFFER_DISPLAY,
1674                                                 &surf,
1675                                                 NULL,
1676                                                 0);
1677                                 if(drm_data->rtn) {
1678                                         EMGD_ERROR(" emgd_dihclone_set_surface2: failed");
1679                                         return -IGD_ERROR_INVAL;
1680                                 }
1681
1682
1683                         } else { // if secondary clone
1684
1685                                 EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH2");
1686                                 surf.offset = pipe1->plane->fb_info->saved_offset;
1687                                 /* Call the HAL: */
1688                                 drm_data->rtn = dispatch->set_surface(display,
1689                                                 IGD_PRIORITY_NORMAL,
1690                                                 IGD_BUFFER_DISPLAY,
1691                                                 &surf,
1692                                                 NULL,
1693                                                 0);
1694                                 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1695                                 surf.offset = pipe2->plane->fb_info->fb_base_offset;
1696                                 /* Call the HAL: */
1697                                 drm_data->rtn = dispatch->set_surface(display,
1698                                                 IGD_PRIORITY_NORMAL,
1699                                                 IGD_BUFFER_DISPLAY,
1700                                                 &surf,
1701                                                 NULL,
1702                                                 0);
1703
1704                         }
1705                 }
1706                 if (drm_data->rtn == 0) {
1707                         context->mod_dispatch.in_dih_clone_mode = false;
1708                 }
1709         }
1710         /* setting fake clone (dih clone) mode */
1711         if (drm_data->mode == CLONE) {
1712                 if (IGD_DC_VEXT(drm_emgd_dc)) {
1713                         x_offset = 0;
1714
1715                         if( drm_data->dih_clone_display == CLONE_PRIMARY){
1716                                 y_offset = 0;
1717                                 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1718                         } else {
1719                                 y_offset = (pipe1->plane->fb_info->height / 2);
1720                                 display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1721                         }
1722
1723                         /* Call Pan display to affect pt_info offsets */
1724                         drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
1725                 } else { /* in DIH mode */
1726
1727                         /*first save the display's original offset  */
1728                         surf.offset = pipe1->plane->fb_info->fb_base_offset;
1729                         drm_data->rtn = dispatch->set_surface(display,
1730                                         IGD_PRIORITY_NORMAL,
1731                                         IGD_BUFFER_SAVE,
1732                                         &surf,
1733                                         NULL,
1734                                         0);
1735
1736                         display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1737                         surf.offset = pipe2->plane->fb_info->fb_base_offset;
1738                         drm_data->rtn = dispatch->set_surface(display,
1739                                         IGD_PRIORITY_NORMAL,
1740                                         IGD_BUFFER_SAVE,
1741                                         &surf,
1742                                         NULL,
1743                                         0);
1744
1745
1746                         /* primary display */
1747                         if( drm_data->dih_clone_display == CLONE_PRIMARY){
1748                                 surf.offset = pipe1->plane->fb_info->fb_base_offset;
1749                         } else {
1750                                 surf.offset = pipe2->plane->fb_info->fb_base_offset;
1751                         }
1752
1753                         display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1754
1755                         /* Call the HAL: */
1756                         drm_data->rtn = dispatch->set_surface(display,
1757                                         IGD_PRIORITY_NORMAL,
1758                                         IGD_BUFFER_DISPLAY,
1759                                         &surf,
1760                                         NULL,
1761                                         0);
1762
1763                         /* secondary display */
1764                         display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1765
1766                         drm_data->rtn = dispatch->set_surface(display,
1767                                         IGD_PRIORITY_NORMAL,
1768                                         IGD_BUFFER_DISPLAY,
1769                                         &surf,
1770                                         NULL,
1771                                         0);
1772
1773                 }
1774                 if(drm_data->rtn == 0){
1775                         context->mod_dispatch.in_dih_clone_mode = true;
1776                         context->mod_dispatch.dih_clone_display = drm_data->dih_clone_display;
1777                 }
1778         }
1779
1780         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1781
1782         EMGD_DEBUG("Returning 0");
1783         EMGD_TRACE_EXIT;
1784         return 0;
1785 } /* emgd_dihclone_set_surface() */
1786
1787
1788
1789 /*!
1790  * IOCTL to bridge the IAL to the HAL's sync() procedure.
1791  */
1792 int emgd_sync(struct drm_device *dev, void *arg,
1793         struct drm_file *file_priv)
1794 {
1795         emgd_drm_sync_t *drm_data = arg;
1796
1797         EMGD_TRACE_ENTER;
1798
1799
1800         /* Call the HAL: */
1801         drm_data->rtn = dispatch->sync(drm_data->display_handle,
1802                 drm_data->priority,
1803                 /* Note: Since a pointer is passed to drm_data->in_sync,
1804                  * there's no need to copy anything back into drm_data, except
1805                  * for the return value.
1806                  */
1807                 &(drm_data->in_sync),
1808                 drm_data->flags);
1809
1810
1811         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1812         EMGD_TRACE_EXIT;
1813         return 0;
1814 } /* emgd_sync() */
1815
1816
1817 /*!
1818  * IOCTL to bridge the IAL to the HAL's driver_pre_init() procedure.
1819  */
1820 int emgd_driver_pre_init(struct drm_device *dev, void *arg,
1821         struct drm_file *file_priv)
1822 {
1823         drm_emgd_priv_t *priv = dev->dev_private;
1824         igd_context_t *context = NULL;
1825         emgd_drm_driver_pre_init_t *drm_data = (emgd_drm_driver_pre_init_t *) arg;
1826         igd_param_t *x_params = NULL;
1827         igd_param_t *uc_params = NULL;
1828         igd_fb_caps_t *pf_caps;
1829         igd_display_port_t *port = NULL;
1830         int i, err = 0, need_to_startup_hal = (!priv->hal_running) ? 1 : 0;
1831         unsigned long save_flags;
1832
1833         EMGD_TRACE_ENTER;
1834
1835         /* This flag will cause a call to emgd_init_display() in
1836          * emgd_driver_lastclose() if config_drm.init is true */
1837         x_started = true;
1838
1839         /*
1840          * Need to apply the "x_params" (e.g. "xorg.conf" values, from user-space)
1841          * in the same order as igd_module_init():
1842          * - Nothing to do for REG_INIT(), gmm_init(), nor CMD_INIT().
1843          * - mode_init() has several steps (see below).
1844          * - Nothing to do for APPCONTEXT_INIT().
1845          * - OVERLAY_INIT() is simple (see below).
1846          * - Nothing to do for PWR_INIT(), RESET_INIT(), OS_INIT_INTERRUPT(),
1847          *   BLEND_INIT(), nor INIT_2D().
1848          */
1849         x_params = &(drm_data->params);
1850
1851
1852         /* Before applying them, first see if the X driver sent any DTD or attr
1853          * list(s) for the given ports (i.e. from "xorg.conf").  If not, the values
1854          * from "user_config.c" are supposed to be used (and so they need to be
1855          * looked up and copied).
1856          */
1857         if (drm_emgd_configid < 0) {
1858                 uc_params = config_drm.hal_params[0];
1859         } else {
1860                 uc_params = config_drm.hal_params[drm_emgd_configid-1];
1861         }
1862         for (i = 0 ; i < IGD_MAX_PORTS ; i++) {
1863                 igd_display_params_t *x_dp = &x_params->display_params[i];
1864                 igd_display_params_t *uc_dp = NULL;
1865                 int j;
1866
1867                 if ((x_dp->port_number > 0) && (x_dp->dtd_list.num_dtds == 0)) {
1868                         /* X didn't have any DTDs for this port.  Look up the corresponding
1869                          * display params from "user_config.c"
1870                          */
1871                         for (j = 0 ; j < IGD_MAX_PORTS ; j++) {
1872                                 uc_dp = &uc_params->display_params[j];
1873                                 if (uc_dp->port_number == x_dp->port_number) {
1874                                         break;
1875                                 }
1876                         }
1877                         if ((x_dp->port_number == uc_dp->port_number) ||
1878                                 (uc_dp->dtd_list.num_dtds > 0)) {
1879                                 /* Have X's DTD list point to "user_config.c"'s DTD list */
1880                                 x_dp->dtd_list.num_dtds = uc_dp->dtd_list.num_dtds;
1881                                 x_dp->dtd_list.dtd = uc_dp->dtd_list.dtd;
1882                                 x_dp->present_params |= IGD_PARAM_DTD_LIST;
1883                         }
1884                 }
1885
1886                 if ((x_dp->port_number > 0) && (x_dp->attr_list.num_attrs == 0)) {
1887                         /* X didn't have any ATTRs for this port.  Look up the corresponding
1888                          * display params from "user_config.c"
1889                          */
1890                         for (j = 0 ; j < IGD_MAX_PORTS ; j++) {
1891                                 uc_dp = &uc_params->display_params[j];
1892                                 if (uc_dp->port_number == x_dp->port_number) {
1893                                         break;
1894                                 }
1895                         }
1896                         if ((x_dp->port_number == uc_dp->port_number) ||
1897                                 (uc_dp->attr_list.num_attrs > 0)) {
1898                                 /* Have X's ATTR list point to "user_config.c"'s attr list */
1899                                 x_dp->attr_list.num_attrs = uc_dp->attr_list.num_attrs;
1900                                 x_dp->attr_list.attr = uc_dp->attr_list.attr;
1901                                 x_dp->present_params |= IGD_PARAM_ATTR_LIST;
1902                         }
1903                 }
1904         }
1905 #ifdef DEBUG_BUILD_TYPE
1906         if(emgd_debug && emgd_debug->MODULE_NAME)
1907                 emgd_print_params(x_params);
1908 #endif
1909
1910
1911         if (need_to_startup_hal) {
1912                 /* emgd_driver_load() deferred driver initialization and configuration.
1913                  * Therefore, do it now.
1914                  *
1915                  * Before doing so, ensure both ports are turned on, even if the user
1916                  * only requested one port.
1917                  *
1918                  * TODO/FIXME - This assumes only two ports; is that wise long-term?
1919                  */
1920                 if (x_params->port_order[1] == 0) {
1921                         if (x_params->port_order[0] == 2) {
1922                                 x_params->port_order[1] = 4;
1923                         } else {
1924                                 x_params->port_order[1] = 2;
1925                         }
1926                 }
1927
1928                 EMGD_DEBUG("Starting the HAL");
1929                 err = emgd_startup_hal(dev, x_params);
1930                 if (err != 0) {
1931                         mutex_unlock(&dev->struct_mutex);
1932                         return err;
1933                 } else {
1934                         priv = dev->dev_private;
1935                         priv->hal_running = 1;
1936                 }
1937         }
1938         /* Now that we know the driver is initialized, we can do the following: */
1939         context = (igd_context_t *) handle;
1940         context->mod_dispatch.init_params = x_params;
1941
1942         if (config_drm.init) {
1943                 if (config_drm.kms) {
1944                         save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT)| IGD_REG_SAVE_TYPE_REG;
1945                 } else {
1946                         save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT &
1947                                 ~IGD_REG_SAVE_RB) | IGD_REG_SAVE_TYPE_REG;
1948                 }
1949                 dispatch->driver_save(handle, save_flags);
1950                 EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
1951                 priv->saved_registers = CONSOLE_STATE_SAVED;
1952         }
1953
1954         if (!need_to_startup_hal) {
1955                 /* emgd_driver_load() initialized and configured the driver.
1956                  * Therefore, we must now re-initialize and poke x_params values into
1957                  * various parts of the driver.
1958                  */
1959                 EMGD_DEBUG("Re-initializing the HAL with X driver values");
1960
1961                 /* mode_init() (in "micro_mode.c") only sets the following value, which
1962                  * affects future alter_displays() calls.  Note that no code seems to
1963                  * set x_params->display_color in the X driver.
1964                  */
1965                 mode_context->display_color = x_params->display_color;
1966
1967                 /* mode_init() calls full_mode_init() (in "igd_mode.c"), which set the
1968                  * following values, of which, only seamless is used in the HAL.
1969                  *
1970                  * If seamless is TRUE, full_mode_init() will call the static procedure
1971                  * get_fw_info(), which will get firmware-programmed info before the
1972                  * driver starts re-programming it.  get_fw_info will set seamless to
1973                  * FALSE if there's any errors.  The get_fw_info() procedure can't be
1974                  * called here because it's static.  It may also be too late to call it
1975                  * at this point (i.e. if the HAL has already touched anything, and
1976                  * that may have something to do with how many times the X server
1977                  * process starts).
1978                  */
1979                 mode_context->quickboot = x_params->quickboot;
1980                 mode_context->seamless = x_params->qb_seamless;
1981                 mode_context->video_input = x_params->qb_video_input;
1982                 mode_context->splash = x_params->qb_splash;
1983                 mode_context->first_alter = TRUE;
1984
1985                 if (config_drm.init) {
1986                         for (i=0; i < IGD_MAX_PORTS; i++) {
1987                                 mode_context->batch_blits[x_params->display_params[i].port_number - 1]
1988                                         = x_params->display_params[i].flags & IGD_DISPLAY_BATCH_BLITS;
1989                         }
1990                         toggle_vblank_interrupts(TRUE);
1991                 }
1992
1993                 /* In case the X server ran, exited, and is starting again, we may need
1994                  * to put the X server's state back:
1995                  */
1996                 if (priv->saved_registers == X_SERVER_STATE_SAVED) {
1997                         EMGD_DEBUG("Need to restore the X server's saved register state");
1998
1999                         if (config_drm.init) {
2000                                 save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
2001                         }
2002                         else {
2003                                 save_flags = IGD_REG_SAVE_ALL;
2004                         }
2005                         err = dispatch->driver_save_restore(handle, save_flags);
2006                         EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
2007                         priv->saved_registers = CONSOLE_STATE_SAVED;
2008                 }
2009
2010                 if(!mode_context->seamless) {
2011                         /* NOTE: In order for some new values to be poked into the port
2012                          * drivers' hardware (e.g. the LVDS panel depth), the power must be
2013                          * turned off on those devices.  This used to be done during the
2014                          * emgd_driver_lastclose() function, but that prevents the console from
2015                          * being seen after X quits.
2016                          */
2017                         while ((port = context->mod_dispatch.dsp_get_next_port(context,
2018                                                 port, 0)) != NULL) {
2019                                 /* power off LVDS only */
2020                                 if (port->pd_driver &&  (port->port_number == IGD_PORT_TYPE_LVDS) &&
2021                                         !mode_context->seamless) {
2022                                         EMGD_DEBUG("Turning off power for port %lu\n", port->port_number);
2023                                         dispatch->power_display(context, port->port_number,
2024                                                 IGD_POWERSTATE_D3);
2025                                 }
2026                         }
2027
2028                         /* mode_init() calls dsp_init() (in "dsp.c"), which uses the
2029                          * display_flags, display_params & port_order params.  In the case of
2030                          * display_params, each element of the array contains dtd_list and
2031                          * attr_list, both of which point to memory that must be separately
2032                          * copied to kernel-space.  The display_flags, display_params &
2033                          * port_order params affect the initialization of the DSP module, and
2034                          * as such, it may not be easy to simply poke values here.
2035                          *
2036                          * Thus, it appears that the DSP module must somehow be re-initialized.
2037                          *
2038                          * Note: dsp_init() also calls full_dsp_init() and the device-specific
2039                          * init procedures, none of which uses any params.
2040                          */
2041                         EMGD_DEBUG("Calling dsp_shutdown()");
2042                         dsp_shutdown(handle);
2043
2044                         EMGD_DEBUG("Calling dsp_init()");
2045                         dsp_init(handle);
2046
2047
2048                         /* Poke any new port attributes & DTDs into the port drivers: */
2049                         while ((port = context->mod_dispatch.dsp_get_next_port(context,
2050                                                 port, 0)) != NULL) {
2051                                         if (port->pd_driver && !mode_context->seamless) {
2052                                                 EMGD_DEBUG("Insert new port attrs/DTDs for port %lu",
2053                                                 port->port_number);
2054                                         pi_pd_init(port, 0, 0, FALSE);
2055                                 }
2056                         }
2057
2058                         /*
2059                          * Because dsp_init was called above, a lot of the configuration
2060                          * performed by the driver at initializat is now invalid.
2061                          *
2062                          * Setting the dc to 0 makes sure we don't try to use other
2063                          * data structures before alter_displays has been called again.
2064                          */
2065                         priv->dc = 0;
2066                 }
2067
2068
2069                 /* Set a flag so that emgd_alter_displays() will turn back on the port
2070                  * drivers' hardware:
2071                  */
2072                 if(!mode_context->seamless) {
2073                         priv->must_power_on_ports = 1;
2074                 }
2075
2076                 /* OVERLAY_INIT() translates to the _overlay_init() procedure (in
2077                  * "micro_ovl.c").  It calls ovl_full_init() (in "igd_ovl.c").  If the
2078                  * IGD_DISPLAY_FB_BLEND_OVL bit in "display_flags" is set, it sets
2079                  * ovl_context->fb_blend_ovl to 1, which affects future atler_ovl()
2080                  * calls.
2081                  */
2082                 if (x_params->display_flags & IGD_DISPLAY_FB_BLEND_OVL) {
2083                         ovl_context->fb_blend_ovl = 1;
2084                 }
2085         } /* if (!need_to_startup_hal) */
2086
2087 /* NOTE -- Below is our original analysis of what values/modules need
2088  * to be dealt with (above):
2089  *
2090  * - mode_init() (in "micro_mode.c") uses display_color.
2091  *
2092  *   - Note: the value is stored in a global variable:
2093  *     mode_context->display_color.  This value is used only once--in
2094  *     full_clear_fb() (igd_mode.c), which is only called by
2095  *     configure_display() (micro_mode.c), which is only called by
2096  *     igd_alter_displays() (micro_mode.c).
2097  *
2098  *   [ ] Implemented proposal: set the value.  Correct approach?
2099  *
2100  * - full_mode_init() (in "igd_mode.c", called by mode_init(); lives in
2101  *   "micro_mode.c", which is called by init_modules()) uses the quickboot &
2102  *   qb_* params.  The values are stored in a global variable: mode_context->*.
2103  *   Here's what I learned in terms of what is used (same is true for IEGD
2104  *   source):
2105  *
2106  *     - The mode_context->quickboot value is only set (here) and is never used.
2107  *
2108  *     - mode_context->seamless (corresponding to params->qb_seamless) is
2109  *       used in full_mode_init() (igd_mode.c) to decide whether (if TRUE) to
2110  *       call get_fw_info(), which may set it to FALSE depending on whether
2111  *       there is firmware info that should affect it.  It is also read by
2112  *       configure_display() (micro_mode.c), which is only called by
2113  *       igd_alter_displays() (micro_mode.c).  It is also read & used to decide
2114  *       something by igd_alter_displays() (micro_mode.c).
2115  *
2116  *     - mode_context->video_input (corresponding to params->qb_video_input) is
2117  *       only set (here) and is never used.
2118  *
2119  *     - mode_context->splash (corresponding to params->qb_splash) is only set
2120  *       (here) and is never used.
2121  *
2122  *   [ ] New Proposal: potentially set the values and do nothing else.  Is this
2123  *       the correct approach?
2124  *
2125  *   [-] Old Proposal: set the values, and if seamless is TRUE, call
2126  *       get_fw_info().  Can't actually do so, as get_fw_info() is a static
2127  *       procedure.
2128  *
2129  * - dsp_init() (in "dsp.c", called by mode_init(); lives in "micro_mode.c",
2130  *   which is called by init_modules()) uses the display_flags, display_params
2131  *   & port_order params.  It also calls full_dsp_init() and the
2132  *   device-specific init procedures, neither of which uses any params.  Within
2133  *   display_params, there are several params looked at: port_number,
2134  *   present_params, ddc_gpio, ddc_speed, ddc_dab, i2c_gpio, i2c_speed,
2135  *   i2c_dab, fp_info, dtd_list, and attr_list.  Right now, none of these are
2136  *   set.
2137  *
2138  * - Notes: Here's what I learned in terms of what is used:
2139  *
2140  *     - params->display_flags is stored in dsp_context->display_flags.  The
2141  *       value is used by dsp_dc_init() (dsp.c, called by igd_query_dc() and
2142  *       mode_init()--called after dsp_init()) to determine if
2143  *       IGD_DISPLAY_DETECT is set (used frequently in that procedure).  The
2144  *       value is used by igd_query_dc() (dsp.c, called by igd_query_dc() and
2145  *       mode_init()--called after dsp_init())--after calling dsp_dc_init()
2146  *       once, if there's only 1 DC, it uses this value to determine if
2147  *       IGD_DISPLAY_DETECT is set, and if so the bit is immediately turned off
2148  *       and dsp_dc_init() is called again.
2149  *
2150  *     - params->port_order is used as a parameter to do_port_order() (in
2151  *       "dsp.c"), which is only called this once via dsp_init().  Based on
2152  *       this, it seems that we should try to figure out how to re-init this
2153  *       code.  Correct approach?
2154  *
2155  *     - params->display_params is iterated over ... OUCH!  display_params IS A
2156  *       STRUCT OF TYPE igd_param_attr_list_t, AND SOME OF ITS MEMBERS HAVE
2157  *       POINTERS WITHIN THEM (i.e. HARDER TO GET ACROSS THE IOCTL BOUNDARY).
2158  *
2159  *       Based on the above, it seems that the idea of
2160  *       re-initializing the DSP module seems like the correct approach.  I'm
2161  *       not quite sure how to do that, but it seems like the right direction
2162  *       to both keep the HAL code unmodified, and do the user/kernel-space
2163  *       split.
2164  *
2165  *       [X] Implemented proposal: copy all user-space memory to kernel-space,
2166  *           and later free any temporarily allocated memory.
2167  *       [ ] Proposal: re-initialize the DSP module.  Correct approach?
2168  *
2169  * - OVERLAY_INIT() translates to _overlay_init() (in "micro_ovl.c") takes
2170  *   params as a parameter, which it passes to ovl_full_init() (in
2171  *   "igd_ovl.c").  If the IGD_DISPLAY_FB_BLEND_OVL bit in "display_flags" is
2172  *   set, it sets ovl_context->fb_blend_ovl to 1.  This flag is used in the
2173  *   following procedures:
2174  *
2175  *   - ovl_send_instr_plb() (in "emgd_drm/video/overlay/plb/ovl_plb.c") is
2176  *     called by alter_ovl_plb(), which is called through the ovl_dispatch_plb
2177  *     table (of type ovl_dispatch_t).
2178  *
2179  *   - ovl2_send_instr_plb() (in "emgd_drm/video/overlay/plb/ovl2_plb.c") is
2180  *     called by alter_ovl2_plb(), which is called through the ovl_dispatch_plb
2181  *     table (of type ovl_dispatch_t).
2182  *
2183  *   - ovl_send_instr_tnc() (in "emgd_drm/video/overlay/tnc/ovl_tnc.c") is
2184  *     called by alter_ovl_tnc(), which is called through the ovl_dispatch_tnc
2185  *     table (of type ovl_dispatch_t).
2186  *
2187  *   [ ] Implemented proposal: If the IGD_DISPLAY_FB_BLEND_OVL bit in
2188  *   "display_flags" is set, set ovl_context->fb_blend_ovl to 1.  Correct
2189  *   approach?
2190  *
2191  * - pi_pd_init() (in the file "emgd_drm/display/pi/cmd/pi.c") accesses
2192  *   params->display_params.  It is called by pi_pd_register() ("pi.c"), which
2193  *   is called by both igd_pd_register() (in "igd_pi.c") and pd_register() (in
2194  *   "emgd_drm/display/pd/pd.c").  igd_pd_register() is called by
2195  *   load_port_drivers() (in "emgd_drv/emgd_dpdloader.c") which is no longer
2196  *   called (was called during PreInit()).
2197  *   pd_register() is called by lvds_init() and sdvo_init(), both of which are
2198  *   called by pi_init_all(), which is not being called.
2199  *
2200  *   [ ] TODO - LEARN ABOUT HOW THE STATICALLY-LOADED PORT DRIVERS WILL GET
2201  *       THEIR params INFO, AND WHEN THEY WILL WANT IT (i.e. IN RELATION TO X
2202  *       DRIVER PreInit())
2203  *
2204  * None of the other modules use and/or need any params at this point:
2205  *
2206  * - REG_INIT translates to _reg_init() and uses preserve_reg.  It's too late
2207  *   to undo what we chose at kernel init time.
2208  * - gmm_init() ignores page_request and max_fb_size.
2209  * - CMD_INIT() translates to 0 (i.e. Koheo doesn't use this module).
2210  * - pi_init() (in "pi.c", called by mode_init(); lives in "micro_mode.c",
2211  *   which is called by init_modules()) uses no params.
2212  * - APPCONTEXT_INIT() translates to appcontext_init() doesn't use any params
2213  * - PWR_INIT() translates to _pwr_init() (in "igd_pwr.c") doesn't look a any
2214  *   params in context, nor does pwr_init_plb() (in "pwr_plb.c").
2215  * - RESET_INIT() translates to _reset_init() IS MISSING.  IS IT NEEDED???
2216  *   Just in case, I looked at the IEGD version (in "igd_reset.c"), which
2217  *   doesn't look at any params.
2218  * - OS_INIT_INTERRUPT() doesn't translate into anything real (i.e. IT IS
2219  *   MISSING).  IS IT NEEDED???  Just in case, I looked at the IEGD version (in
2220  *   "oal/xfree86/src/interrupt/interrupt.c"), and it is a no-op.
2221  * - BLEND_INIT() translates to 0 (i.e. Koheo doesn't use this module).
2222  * - INIT_2D() translates to 0 (i.e. Koheo doesn't use this module).
2223  */
2224
2225
2226         /* Call the HAL's igd_get_config_info() procedure: */
2227         drm_data->rtn = igd_get_config_info(handle,
2228                 /* Note: Since a pointer is passed to drm_data->config_info, there's no
2229                  * need to copy anything back into drm_data, except for the return
2230                  * value.
2231                  */
2232                 &(drm_data->config_info));
2233
2234         /* Check for a bit depth we support */
2235         pf_caps = drm_data->config_info.fb_caps;
2236
2237         while (pf_caps && pf_caps->pixel_format != 0) {
2238                 if (drm_data->bpp == IGD_PF_DEPTH(pf_caps->pixel_format)) {
2239                         EMGD_DEBUG("Found matching PF: %lx for depth %lx bpp.",
2240                                 pf_caps->pixel_format, drm_data->bpp);
2241                         drm_data->config_info.pixel_format = pf_caps->pixel_format;
2242                         break;
2243                 }
2244                 pf_caps++;
2245         }
2246         if (!drm_data->config_info.pixel_format) {
2247                 EMGD_DEBUG("Given depth (%lx) is not supported.", drm_data->bpp);
2248         }
2249
2250
2251         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2252         EMGD_TRACE_EXIT;
2253         return 0;
2254 } /* emgd_driver_pre_init() */
2255
2256
2257 /*!
2258  * IOCTL to support emgd_hal2drm_get_ports(), which replaces the X driver's
2259  * usage of igd_get_param(...,IGD_PARAM_PORT_LIST,...)
2260  */
2261 int emgd_driver_get_ports(struct drm_device *dev, void *arg,
2262         struct drm_file *file_priv)
2263 {
2264         emgd_drm_driver_get_ports_t *drm_data = arg;
2265
2266         EMGD_TRACE_ENTER;
2267
2268
2269         /* Call the HAL: */
2270         drm_data->rtn = igd_get_param(handle, IGD_PARAM_PORT_LIST,
2271                 /* Note: Since a pointer is passed to drm_data->ports,
2272                  * there's no need to copy anything back into drm_data, except
2273                  * for the return value.
2274                  */
2275                 drm_data->ports);
2276
2277
2278         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2279         EMGD_TRACE_EXIT;
2280         return 0;
2281 } /* emgd_driver_get_ports() */
2282
2283 /*!
2284  * IOCTL to support emgd_hal2drm_get_page_list(), which get's the list
2285  * of page address that make up a memory allocation.
2286  */
2287 int emgd_get_page_list(struct drm_device *dev, void *arg,
2288         struct drm_file *file_priv)
2289 {
2290         emgd_drm_get_page_list_t *drm_data = arg;
2291         unsigned long cnt;
2292         unsigned long *list;
2293         unsigned long *new_list;
2294         int i;
2295
2296         EMGD_TRACE_ENTER;
2297
2298         dispatch->gmm_get_page_list(drm_data->offset, &list, &cnt);
2299         if (cnt > drm_data->addr_count) {
2300                 /*
2301                  * The user didn't allocate enough space for the
2302                  * page list, this is an error.
2303                  */
2304                 drm_data->addr_count = cnt;
2305                 drm_data->rtn = -IGD_NO_MEM;
2306         } else {
2307                 /* Copy the address list to the caller */
2308                 new_list = (unsigned long *)(arg + sizeof(emgd_drm_get_page_list_t));
2309                 for (i = 0; i < cnt; i++) {
2310                         new_list[i] = list[i];
2311                 }
2312         }
2313
2314         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2315         EMGD_TRACE_EXIT;
2316         return 0;
2317 } /* emgd_driver_get_page_list() */
2318
2319 /*!
2320  * IOCTL to allow the X driver (in "egd_driver.c") to start the Imagination
2321  * Technologies PVR services DRM/kernel module, which will start our 3rd-party
2322  * display driver (3DD).
2323  */
2324 int emgd_start_pvrsrv(struct drm_device *dev, void *arg,
2325         struct drm_file *file_priv)
2326 {
2327         emgd_drm_start_pvrsrv_t *drm_data = arg;
2328         drm_emgd_priv_t *priv = dev->dev_private;
2329
2330         EMGD_TRACE_ENTER;
2331
2332         /* Tell the 3DD the status of whether the X server is running: */
2333         if (!priv->xserver_running && drm_data->xserver) {
2334                 priv->xserver_running = 1;
2335                 if (priv->reinit_3dd) {
2336                         priv->reinit_3dd(dev);
2337                 }
2338         }
2339
2340         drm_data->rtn = 0;
2341         EMGD_TRACE_EXIT;
2342         return 0;
2343 } /* emgd_start_pvrsrv() */
2344
2345
2346 /*!
2347  * IOCTL to bridge the IAL to the HAL's video_cmd_buf() procedure.
2348  */
2349 int emgd_video_cmd_buf(struct drm_device *dev, void *arg,
2350                 struct drm_file *file_priv)
2351 {
2352         emgd_drm_video_cmd_buf_t *drm_data = arg;
2353         drm_emgd_priv_t *priv = dev->dev_private;
2354         igd_context_t *context = priv->context;
2355
2356
2357         EMGD_TRACE_ENTER;
2358
2359         /* Call the HAL: */
2360         switch (drm_data->engine) {
2361                 case PSB_ENGINE_VIDEO:
2362                         drm_data->rtn = process_video_decode_plb(context, drm_data->offset,
2363                                                                 drm_data->kernel_virt_addr,
2364                                                                 &(drm_data->fence_id));
2365                         break;
2366                 case TNC_ENGINE_ENCODE:
2367                         drm_data->rtn = process_video_encode_tnc(context, drm_data->offset,
2368                                                                 drm_data->kernel_virt_addr,
2369                                                                 &(drm_data->fence_id));
2370                         break;
2371                 default:
2372                         break;
2373         }
2374
2375
2376         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2377         EMGD_TRACE_EXIT;
2378         return 0;
2379 } /* emgd_video_cmd_buf() */
2380
2381
2382 /*!
2383  * IOCTL to bridge the IAL to the HAL's get_device_info() procedure.
2384  */
2385 int emgd_get_device_info(struct drm_device *dev, void *arg,
2386     struct drm_file *file_priv)
2387 {
2388     emgd_drm_device_info_t *drm_data = arg;
2389     drm_emgd_priv_t *priv = dev->dev_private;
2390     igd_context_t *context = priv->context;
2391
2392     EMGD_TRACE_ENTER;
2393
2394     drm_data->display_memory_offset = context->device_context.fb_adr;
2395     drm_data->display_memory_size = context->device_context.mem_size;
2396     drm_data->device_id = context->device_context.did;
2397     drm_data->revision_id = context->device_context.rid;
2398     drm_data->bridge_id = context->device_context.bid;
2399
2400     EMGD_TRACE_EXIT;
2401     return 0;
2402 } /* emgd_get_device_info() */
2403
2404
2405 int emgd_init_video(struct drm_device *dev, void *arg,
2406                 struct drm_file *file_priv)
2407 {
2408         emgd_drm_init_video_t *drm_data = arg;
2409         drm_emgd_priv_t *priv = dev->dev_private;
2410         igd_context_t *context = priv->context;
2411
2412         EMGD_TRACE_ENTER;
2413
2414         switch (drm_data->cmd) {
2415         case CMD_VIDEO_STATE :
2416                 switch (drm_data->engine) {
2417                 case PSB_ENGINE_VIDEO:
2418                         drm_data->rtn = msvdx_query_plb(context, &drm_data->status);
2419                         break;
2420                 default:
2421                         drm_data->rtn = 1;
2422                         break;
2423                 }
2424                 break;
2425         case CMD_VIDEO_INITIALIZE :
2426                 /* Call the HAL: */
2427                 switch (drm_data->engine) {
2428                 case PSB_ENGINE_COMPOSITOR_MMU:
2429                         drm_data->rtn = msvdx_init_compositor_mmu(drm_data->base0);
2430                         break;
2431                 case PSB_ENGINE_VIDEO:
2432                         drm_data->rtn = msvdx_init_plb(drm_data->base0, drm_data->base1,
2433                                                        drm_data->fw_priv, drm_data->fw_size, 0);
2434                         break;
2435                 case TNC_ENGINE_ENCODE:
2436                         drm_data->rtn = topaz_init_tnc(drm_data->wb_offset, drm_data->wb_addr, drm_data->firm_addr);
2437                         break;
2438                 default:
2439                         break;
2440                 }
2441                 break;
2442         case CMD_VIDEO_UNINITIALIZE :
2443                 switch (drm_data->engine) {
2444                 case PSB_ENGINE_VIDEO:
2445                         drm_data->rtn = msvdx_uninit_plb(context);
2446                         break;
2447                 default:
2448                         break;
2449                 }
2450                 break;
2451         case CMD_VIDEO_CLOSE_CONTEXT :
2452                 switch (drm_data->engine) {
2453                 case PSB_ENGINE_VIDEO:
2454                         drm_data->rtn = msvdx_close_context(context, drm_data->context_id);
2455                         break;
2456                 default:
2457                         break;
2458                 }
2459                 break;
2460         case CMD_VIDEO_CREATE_CONTEXT:
2461                 switch (drm_data->engine) {
2462                 case PSB_ENGINE_VIDEO:
2463                         drm_data->rtn = msvdx_create_context(context, (void *) file_priv, drm_data->context_id);
2464                         break;
2465                 default:
2466                         break;
2467                 }
2468                 break;
2469         case CMD_VIDEO_SHUTDOWN:
2470                 switch (drm_data->engine) {
2471                 case PSB_ENGINE_VIDEO:
2472                         drm_data->rtn = msvdx_shutdown_plb(context);
2473                         break;
2474                 default:
2475                         break;
2476                 }
2477                 break;
2478         default:
2479                 break;
2480         }
2481
2482         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2483         EMGD_TRACE_EXIT;
2484         return 0;
2485 } /* emgd_init_video() */
2486
2487 int emgd_video_get_info(struct drm_device *dev, void *arg,
2488                         struct drm_file *file_priv)
2489 {
2490         emgd_drm_video_get_info_t *drm_data = arg;
2491         drm_emgd_priv_t *priv = dev->dev_private;
2492         igd_context_t *context = priv->context;
2493
2494         EMGD_TRACE_ENTER;
2495
2496         switch(drm_data->cmd) {
2497                 case CMD_VIDEO_GET_FENCE_ID:
2498                         switch(drm_data->engine){
2499                                 case PSB_ENGINE_VIDEO:
2500                                         drm_data->rtn = msvdx_get_fence_id(context, &(drm_data->fence_id));
2501                                         break;
2502                                 case TNC_ENGINE_ENCODE:
2503                                         drm_data->rtn = topaz_get_fence_id(context, &(drm_data->fence_id));
2504                                         break;
2505                                 default:
2506                                         break;
2507                         }
2508                         break;
2509                 case CMD_VIDOE_GET_FRAME_SKIP:
2510                         switch(drm_data->engine){
2511                                 case PSB_ENGINE_VIDEO:
2512                                         break;
2513                                 case TNC_ENGINE_ENCODE:
2514                                         drm_data->rtn = topaz_get_frame_skip(context, &(drm_data->frame_skip));
2515                                         break;
2516                                 default:
2517                                         break;
2518                         }
2519                         break;
2520                 case CMD_VIDEO_GET_MSVDX_STATUS:
2521                         if ((&context->mod_dispatch) && context->mod_dispatch.msvdx_status)
2522                                 drm_data->rtn = context->mod_dispatch.msvdx_status(context, &drm_data->queue_status, &drm_data->mtx_msg_status);
2523                         break;
2524                 default:
2525                         break;
2526         }
2527
2528         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2529         EMGD_TRACE_EXIT;
2530         return 0;
2531 }
2532
2533
2534 int emgd_video_flush_tlb(struct drm_device *dev, void *arg,
2535                         struct drm_file *file_priv)
2536 {
2537         emgd_drm_video_flush_tlb_t *drm_data = arg;
2538         drm_emgd_priv_t *priv = dev->dev_private;
2539         igd_context_t *context = priv->context;
2540
2541         EMGD_TRACE_ENTER;
2542
2543         switch(drm_data->engine) {
2544                 case PSB_ENGINE_VIDEO:
2545                         drm_data->rtn = 0;
2546                         break;
2547                 case TNC_ENGINE_ENCODE:
2548                         drm_data->rtn = topaz_flush_tnc(context);
2549                         break;
2550                 default:
2551                         break;
2552         }
2553
2554         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2555         EMGD_TRACE_EXIT;
2556         return 0;
2557 }
2558
2559 int emgd_preinit_mmu(struct drm_device *dev, void *arg,
2560                         struct drm_file *file_priv)
2561 {
2562         emgd_drm_preinit_mmu_t *drm_data = arg;
2563
2564         EMGD_TRACE_ENTER;
2565
2566         drm_data->rtn = msvdx_preinit_mmu(drm_data->memcontext);
2567
2568         EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2569         EMGD_TRACE_EXIT;
2570         return 0;
2571 }
2572
2573 int emgd_get_golden_htotal(struct drm_device *dev, void *arg,
2574                 struct drm_file *file_priv){
2575
2576
2577         emgd_drm_get_golden_htotal_t *drm_data = arg;
2578         igd_context_t *context = (igd_context_t *) handle;
2579         igd_display_context_t *display;
2580         pd_timing_t igd_mode_table_in[2];
2581         pd_timing_t igd_mode_table_out;
2582
2583         igd_display_info_t *out_mode = (igd_display_info_t *) drm_data->out_mode;
2584         igd_display_info_t *in_mode = (igd_display_info_t *) drm_data->in_mode;
2585
2586
2587         EMGD_DEBUG("emgd_get_golden_htotal : Entry");
2588
2589         /* parameters sanity check */
2590         if (out_mode == NULL) {
2591                 EMGD_ERROR("emgd_get_golden_htotal : NO Output Buffer");
2592                 return -IGD_ERROR_INVAL;
2593         }
2594
2595         if (in_mode == NULL) {
2596                 EMGD_ERROR("emgD_get_golden_htotal : NO Input Buffer");
2597                 return -IGD_ERROR_INVAL;
2598
2599         }
2600
2601         /* Zero out the data structures so that we can check for error later */
2602         memset(igd_mode_table_in, 0, 2 * sizeof(pd_timing_t));
2603         memset(&igd_mode_table_out, 0, sizeof(pd_timing_t));
2604
2605         /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
2606         display = context->mod_dispatch.dsp_display_list[2];
2607         if ((display == NULL) || (PORT(display, 2) == NULL)) {
2608                 EMGD_ERROR_EXIT("emgd_get_golden_htotal() given an invalid port "
2609                         "number (%d)\n", 2);
2610                 return -IGD_ERROR_INVAL;
2611         }
2612
2613     /* convert the data from escape structure to pd_timing */
2614     igd_mode_table_in[0].width = in_mode->width;
2615     igd_mode_table_in[0].height = in_mode->height;
2616     igd_mode_table_in[0].refresh = in_mode->refresh;
2617
2618     /* Set the end of list */
2619     igd_mode_table_in[1].width = PD_TIMING_LIST_END;
2620     igd_mode_table_in[1].extn_ptr = NULL;
2621
2622     /************************************************************/
2623     /* call dispatch function that will generate the golden htotal
2624      * for all the modes. The pd_timing_t has the same structure as
2625      * igd_display_t so we can typecast without issue.
2626      */
2627     /************************************************************/
2628     context->mod_dispatch.get_dd_timing(display,
2629                             (pd_timing_t*)&igd_mode_table_in);
2630
2631     /************************************************************/
2632     /* Send back the modified mode list that contains the delta */
2633     /************************************************************/
2634
2635     memcpy (out_mode, in_mode, sizeof(igd_display_info_t));
2636     out_mode->reserved_dd = igd_mode_table_in[0].reserved_dd;
2637
2638         out_mode->hblank_end = igd_mode_table_in[0].hblank_end;
2639         out_mode->vblank_end = igd_mode_table_in[0].vblank_end;
2640
2641
2642     return 0;
2643 }
2644
2645 int emgd_control_plane_format(struct drm_device *dev, void *arg,
2646         struct drm_file *file_priv)
2647 {
2648         emgd_drm_control_plane_format_t *drm_data = arg;
2649         igd_context_t *context = (igd_context_t *) handle;
2650         igd_plane_t *plane_override;
2651
2652         EMGD_DEBUG("emgd_control_plane_format : Entry");
2653
2654         if (drm_data->use_plane == FALSE)
2655         {
2656                 /* Do some error checking first */
2657                 if((drm_data->enable != 0 && drm_data->enable != 1) ||
2658                         (drm_data->primary_secondary_dsp == NULL)) {
2659                         EMGD_ERROR("emgd_control_plane_format: Invalid parameters");
2660                         return -IGD_ERROR_INVAL;
2661                 }
2662
2663                 plane_override = ((igd_plane_t *)(PLANE(drm_data->primary_secondary_dsp)));
2664         } else {
2665                 /* Do some error checking first */
2666                 if((drm_data->enable != 0 && drm_data->enable != 1) ||
2667                         (drm_data->display_plane != 0 && drm_data->display_plane != 1)) {
2668                         EMGD_ERROR("emgd_control_plane_format: Invalid parameters");
2669                         return -IGD_ERROR_INVAL;
2670                 }
2671
2672                 /* Set plane_override to NULL */
2673                 plane_override = NULL;
2674         }
2675
2676         /* Call the DSP modules function if no errors */
2677         context->mod_dispatch.dsp_control_plane_format(drm_data->enable,
2678                         drm_data->display_plane, plane_override);
2679
2680         return 0;
2681 }
2682
2683 int emgd_set_overlay_display(struct drm_device *dev, void *arg,
2684         struct drm_file *file_priv)
2685 {
2686         emgd_drm_set_overlay_display_t *drm_data = arg;
2687         igd_context_t *context = (igd_context_t *) handle;
2688
2689         EMGD_DEBUG("emgd_set_overlay_display : Entry");
2690
2691         /* Do some error checking first */
2692         if((drm_data->ovl_display[OVL_PRIMARY] == 0) ||
2693                 (drm_data->ovl_display[OVL_SECONDARY] == 0)) {
2694                 /* Both Ovl displays need to have valid handle
2695                  * (i.e. Single mode is not supported) */
2696                 EMGD_ERROR("emgd_set_overlay_display: Invalid parameters");
2697                 return -IGD_ERROR_INVAL;
2698         }
2699
2700         /* Call the set_ovl_display if no errors */
2701         context->dispatch.set_ovl_display(drm_data->ovl_display);
2702
2703         return 0;
2704 }
2705
2706 int emgd_query_2d_caps_hwhint(struct drm_device *dev, void *arg,
2707         struct drm_file *file_priv){
2708
2709
2710         emgd_drm_query_2d_caps_hwhint_t *drm_data;
2711         unsigned long caps_val;
2712         unsigned long *status;
2713
2714         EMGD_DEBUG("emgd_query_2d_caps_hwhint : Entry");
2715
2716     /* parameters sanity check */
2717         if (arg == NULL) {
2718           EMGD_ERROR("emgd_query_2d_caps_hwhint : invalid argument");
2719         return -IGD_ERROR_INVAL;
2720     }
2721
2722
2723         drm_data = arg;
2724         caps_val = (unsigned long) drm_data->caps_val;
2725         status = (unsigned long *) drm_data->status;
2726
2727     igd_query_2d_caps_hwhint(handle, caps_val, status);
2728
2729     return 0;
2730 }