1 /*-----------------------------------------------------------------------------
2 * Filename: emgd_interface.c
4 *-----------------------------------------------------------------------------
5 * Copyright (c) 2002-2010, Intel Corporation.
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
25 *-----------------------------------------------------------------------------
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 *-----------------------------------------------------------------------------
36 #define MODULE_NAME hal.oal
41 #include "drm_emgd_private.h"
46 #include "module_init.h"
47 #include "mode_dispatch.h"
48 #include "ovl_dispatch.h"
58 #include "pvr_bridge_km.h"
59 #include "syscommon.h"
64 #include "pvrversion.h"
66 /* Turn on tracing for this file only */
68 #undef EMGD_TRACE_ENTER
69 #define EMGD_TRACE_ENTER printk( KERN_ERR "%s Entry. ",__FUNCTION__)
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;
78 extern void emgd_init_display(int merge_mod_params, drm_emgd_priv_t *priv);
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.
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;
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.
95 * @param drm_handle (IN) the kernel-space HAL's "real" driver handle
97 void emgd_set_real_handle(igd_driver_h drm_handle)
100 } /* emgd_set_real_handle() */
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.
106 * @param drm_dispatch (OUT) the kernel-space HAL's dispatch table
108 void emgd_set_real_dispatch(igd_dispatch_t *drm_dispatch)
110 dispatch = drm_dispatch;
111 } /* emgd_set_real_dispatch() */
115 * Externally-accessible global variables and functions, for PreInit()-time
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);
125 extern void emgd_modeset_destroy(struct drm_device *dev);
129 * NOTE: The rest of this file contains implementations of the HAL-to-DRM
130 * ioctl-handling procedures.
132 * The naming convention is: emgd_<HAL-procedure-pointer-name>()
137 * IOCTL to get chipset information from DRM.
139 int emgd_get_chipset_info(struct drm_device *dev, void *arg,
140 struct drm_file *file_priv)
142 emgd_drm_driver_get_chipset_info_t *drm_data = arg;
143 drm_emgd_priv_t *priv = dev->dev_private;
145 drm_data->device_id = priv->init_info->device_id;
146 drm_data->revision_id = priv->init_info->vendor_id;
149 * Copy over the name and description fields. Currently these
150 * are hard coded to a maximum of 40 and 20 characters respectively.
152 if (strlen(priv->init_info->name) > 39) {
153 strncpy(drm_data->name, priv->init_info->name, 39);
154 drm_data->name[39] = '\0';
156 strcpy(drm_data->name, priv->init_info->name);
159 if (strlen(priv->init_info->chipset) > 19) {
160 strncpy(drm_data->description, priv->init_info->chipset, 19);
161 drm_data->description[19] = '\0';
163 strcpy(drm_data->description, priv->init_info->chipset);
170 int do_wait_vblank(void *display, int headline, int footline)
176 unsigned long height = PIPE((igd_display_context_t *)display)->timing->height;
178 /*EMGD_TRACE_ENTER;*/
180 if (footline + 50 > height)
183 timeout = OS_SET_ALARM(50);
186 rtn = dispatch->get_scanline((igd_display_context_t *)display, &scnlne);
187 if (rtn || (scnlne >= footline && scnlne <= footline + 50) || ext == scnlne) {
191 } while (!OS_TEST_ALARM(timeout));
193 /*EMGD_DEBUG("rtn = %d", rtn);*/
199 * IOCTL to bridge the IAL to the HAL's wait_vblank() procedure.
201 int emgd_wait_vblank(struct drm_device *dev, void *arg,
202 struct drm_file *file_priv)
205 emgd_drm_driver_set_sync_refresh_t *refresh = arg;
206 igd_display_h *display_handle = &(refresh->display_handle);
208 /*EMGD_TRACE_ENTER;*/
209 rtn = do_wait_vblank((igd_display_context_t *)(*display_handle), refresh->start_line, refresh->bottom_line);
211 /*EMGD_DEBUG("rtn = %d", rtn);*/
214 } /* emgd_wait_vblank() */
217 * IOCTL to bridge the IAL to the HAL's alter_cursor() procedure.
219 int emgd_alter_cursor(struct drm_device *dev, void *arg,
220 struct drm_file *file_priv)
222 emgd_drm_alter_cursor_t *drm_data = arg;
224 /*EMGD_TRACE_ENTER;*/
228 drm_data->rtn = dispatch->alter_cursor(drm_data->display_handle,
229 &(drm_data->cursor_info),
233 /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
236 } /* emgd_alter_cursor() */
240 * IOCTL to bridge the IAL to the HAL's alter_cursor_pos() procedure.
242 int emgd_alter_cursor_pos(struct drm_device *dev, void *arg,
243 struct drm_file *file_priv)
245 emgd_drm_alter_cursor_pos_t *drm_data = arg;
247 /*EMGD_TRACE_ENTER;*/
251 drm_data->rtn = dispatch->alter_cursor_pos(drm_data->display_handle,
252 &(drm_data->cursor_info));
255 /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
258 } /* emgd_alter_cursor_pos() */
261 * IOCTL to bridge the IAL to the HAL's emgd_get_display_info() procedure.
263 int emgd_get_display_info(struct drm_device *dev, void *arg,
264 struct drm_file *file_priv)
267 emgd_drm_get_display_info_t *drm_data = arg;
269 igd_context_t *context = (igd_context_t *) handle;
270 drm_emgd_priv_t *priv = (drm_emgd_priv_t *)dev->dev_private;
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);
277 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn); */
280 } /* emgd_get_display_info() */
283 * IOCTL to bridge the IAL to the HAL's alter_displays() procedure.
285 int emgd_alter_displays(struct drm_device *dev, void *arg,
286 struct drm_file *file_priv)
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;
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.
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;
309 if(drm_data->secondary_pt_info.height ==
310 drm_data->secondary_fb_info.height) {
311 drm_data->secondary_fb_info.height *= 2;
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.
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),
331 if (!drm_data->rtn) {
333 * Special for Vertical Extended, pan the second display
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);
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;
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.
353 igd_context_t *context = (igd_context_t *) handle;
354 igd_display_port_t *port = NULL;
356 while ((port = context->mod_dispatch.dsp_get_next_port(context,
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);
362 dispatch->power_display(context, port->port_number,
366 priv->must_power_on_ports = 0;
369 if (priv->reinit_3dd) {
370 priv->reinit_3dd(dev);
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);
379 } /* emgd_alter_displays() */
383 * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
385 int emgd_alter_ovl(struct drm_device *dev, void *arg,
386 struct drm_file *file_priv)
388 emgd_drm_alter_ovl_t *drm_data = arg;
391 EMGD_DEBUG("Deprecated version of alter_ovl. FIX ME.");
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),
401 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
404 } /* emgd_alter_ovl() */
408 * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
410 int emgd_alter_ovl2(struct drm_device *dev, void *arg,
411 struct drm_file *file_priv)
413 emgd_drm_alter_ovl2_t *drm_data = arg;
416 /* Dump the overlay parameters for debugging */
418 printk (KERN_ERR "emgd_alter_ovl2 Entry."
426 "pvr2d_mem_info=0x%X "
427 "pvr2d_context_h=0x%X "
428 "hPVR2DFlipChain=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 "
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
468 switch (drm_data->cmd) {
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),
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),
489 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
493 } /* emgd_alter_ovl2() */
497 * IOCTL to bridge the IAL to the HAL's get_ovl_init_params() procedure.
499 int emgd_get_ovl_init_params(struct drm_device *dev, void *arg,
500 struct drm_file *file_priv)
502 emgd_drm_get_ovl_init_params_t *drm_data = arg;
503 ovl_um_context_t *ovl_um_context;
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
514 EMGD_DEBUG("Invalid drm_data in emgd_get_ovl_init_params.\n");
518 ovl_um_context = drm_data->ovl_um_context;
520 if (!ovl_um_context) {
525 drm_data->rtn = dispatch->get_ovl_init_params(handle, ovl_um_context);
527 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
530 } /* emgd_get_ovl_init_params() */
534 * IOCTL to bridge the IAL to the HAL's appcontext_alloc() procedure.
536 int emgd_appcontext_alloc(struct drm_device *dev, void *arg,
537 struct drm_file *file_priv)
539 emgd_drm_appcontext_alloc_t *drm_data = arg;
545 /* NOTE: the return value is different than normal: */
546 drm_data->appcontext_h =
547 dispatch->appcontext_alloc(drm_data->display_handle,
552 EMGD_DEBUG("drm_data->appcontext_h = %p", drm_data->appcontext_h);
555 } /* emgd_appcontext_alloc() */
559 * IOCTL to bridge the IAL to the HAL's appcontext_free() procedure.
561 int emgd_appcontext_free(struct drm_device *dev, void *arg,
562 struct drm_file *file_priv)
564 emgd_drm_appcontext_free_t *drm_data = arg;
570 /* NOTE: no return value is desired: */
571 dispatch->appcontext_free(drm_data->display_handle,
573 drm_data->appcontext_h);
576 EMGD_DEBUG("This function has no drm_data->rtn value");
579 } /* emgd_appcontext_free() */
583 * IOCTL to bridge the IAL to the HAL's driver_save_restore() procedure.
585 int emgd_driver_save_restore(struct drm_device *dev, void *arg,
586 struct drm_file *file_priv)
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;
594 if (config_drm.init) {
595 save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
598 save_flags = IGD_REG_SAVE_ALL;
602 drm_data->rtn = dispatch->driver_save_restore(handle, save_flags);
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");
609 priv->saved_registers = CONSOLE_STATE_SAVED;
610 EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
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);
618 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
622 } /* emgd_driver_save_restore() */
626 * IOCTL to bridge the IAL to the HAL's enable_port() procedure.
628 int emgd_enable_port(struct drm_device *dev, void *arg,
629 struct drm_file *file_priv)
631 emgd_drm_enable_port_t *drm_data = arg;
637 drm_data->rtn = dispatch->enable_port(drm_data->display_handle,
638 drm_data->port_number,
643 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
646 } /* emgd_enable_port() */
650 * IOCTL to bridge the IAL to the HAL's get_attrs() procedure.
652 int emgd_get_attrs(struct drm_device *dev, void *arg,
653 struct drm_file *file_priv)
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;
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
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.
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) {
691 tmp = (igd_extension_attr_t *)&attr_list[i];
692 ext_list = tmp->extension;
694 /* Count extension attributes */
695 while ((ext_cnt < drm_data->list_size) &&
696 (ext_list[ext_cnt].id != PD_ATTR_LIST_END)){
704 if(drm_data->port_number == IGD_PORT_TYPE_LVDS) {
705 /* LVDS port driver returns +1 is to include the end attribute */
708 if (drm_data->extended) {
709 drm_data->list_size = ext_cnt; /* size of extension list */
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)));
718 drm_data->list_size = core_cnt;
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)));
729 drm_data->extended = extended;
731 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
734 } /* emgd_get_attrs() */
738 * IOCTL to bridge the IAL to the HAL's get_display() procedure.
740 int emgd_get_display(struct drm_device *dev, void *arg,
741 struct drm_file *file_priv)
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;
749 int do_reinit_3dd = 1;
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;
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;
767 dc = *(context->mod_dispatch.dsp_current_dc);
768 port_num = drm_data->port_number;
770 if (drm_data->flags & IGD_GET_DISPLAY_NO_3DD_REINIT){
772 drm_data->flags &= (~IGD_GET_DISPLAY_NO_3DD_REINIT);
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.
782 &(drm_data->fb_info),
783 &(drm_data->pt_info),
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.
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;
800 priv->dc = *(context->mod_dispatch.dsp_current_dc);
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);
813 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
816 } /* emgd_get_display() */
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,...)).
825 int emgd_get_drm_config(struct drm_device *dev, void *arg,
826 struct drm_file *file_priv)
828 emgd_drm_get_drm_config_t *drm_data = arg;
837 * Return the igd_param_t parameter values used at module load time:
839 if (drm_emgd_configid < 0) {
840 params = config_drm.hal_params[2];
842 params = config_drm.hal_params[drm_emgd_configid-1];
844 if (config_drm.init) {
845 drm_data->display_config = drm_emgd_dc;
847 drm_data->display_config = config_drm.dc;
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;
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.
912 * Return the "ConfigID" to return (either the module parameter or the
913 * value stored in VBIOS:
915 if (drm_emgd_configid > 0) {
916 drm_data->config_id = drm_emgd_configid;
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.
924 &drm_data->config_id);
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
930 drm_data->config_id = -1;
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;
938 drm_data->build_config.debug = 1;
940 drm_data->build_config.debug = 0;
944 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
947 } /* emgd_get_drm_config() */
951 * IOCTL to bridge the IAL to the HAL's get_EDID_block() procedure.
953 int emgd_get_EDID_block(struct drm_device *dev, void *arg,
954 struct drm_file *file_priv)
956 emgd_drm_get_EDID_block_t *drm_data = arg;
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.
968 drm_data->edid_block,
969 drm_data->block_number);
972 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
975 } /* emgd_get_EDID_block() */
979 * IOCTL to bridge the IAL to the HAL's get_EDID_info() procedure.
981 int emgd_get_EDID_info(struct drm_device *dev, void *arg,
982 struct drm_file *file_priv)
984 emgd_drm_get_EDID_info_t *drm_data = arg;
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.
996 &(drm_data->edid_version),
997 &(drm_data->edid_revision),
998 &(drm_data->edid_size));
1001 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1004 } /* emgd_get_EDID_info() */
1008 * IOCTL to bridge the IAL to the HAL's get_pixelformats() procedure.
1010 int emgd_get_pixelformats(struct drm_device *dev, void *arg,
1011 struct drm_file *file_priv)
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;
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:-):
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;
1045 drm_data->rtn = dispatch->get_pixelformats(drm_data->display_handle,
1046 &fb_list_pfs, &cu_list_pfs, &overlay_pfs, &render_pfs, &texture_pfs);
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;
1063 /* Count how many pixelformats were returned: */
1069 drm_data->list_size = count;
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).
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)));
1081 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1084 } /* emgd_get_pixelformats() */
1088 * IOCTL to bridge the IAL to the HAL's get_port_info() procedure.
1090 int emgd_get_port_info(struct drm_device *dev, void *arg,
1091 struct drm_file *file_priv)
1093 emgd_drm_get_port_info_t *drm_data = arg;
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.
1105 &(drm_data->port_info));
1108 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1111 } /* emgd_get_port_info() */
1115 * IOCTL to bridge the IAL to the HAL's gmm_alloc_region() procedure.
1117 int emgd_gmm_alloc_region(struct drm_device *dev, void *arg,
1118 struct drm_file *file_priv)
1120 emgd_drm_gmm_alloc_region_t *drm_data = arg;
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.
1131 &(drm_data->offset),
1137 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1140 } /* emgd_gmm_alloc_region() */
1144 * IOCTL to bridge the IAL to the HAL's gmm_alloc_surface() procedure.
1146 int emgd_gmm_alloc_surface(struct drm_device *dev, void *arg,
1147 struct drm_file *file_priv)
1149 emgd_drm_gmm_alloc_surface_t *drm_data = arg;
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.
1160 &(drm_data->offset),
1161 drm_data->pixel_format,
1163 &(drm_data->height),
1167 &(drm_data->flags));
1170 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1173 } /* emgd_gmm_alloc_surface() */
1175 int emgd_gmm_get_num_surface(struct drm_device *dev, void *arg,
1176 struct drm_file *file_priv)
1178 emgd_drm_gmm_get_num_surface_t *drm_data = arg;
1181 drm_data->rtn = dispatch->gmm_get_num_surface(
1182 &(drm_data->count));
1184 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1189 int emgd_gmm_get_surface_list(struct drm_device *dev, void *arg,
1190 struct drm_file *file_priv)
1192 emgd_drm_gmm_get_surface_list_t *drm_data = arg;
1193 igd_surface_list_t *surface_list = NULL;
1196 drm_data->rtn = dispatch->gmm_get_surface_list(
1197 drm_data->allocated_size,
1198 &(drm_data->list_size),
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)));
1208 vfree(surface_list);
1210 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1216 * IOCTL to bridge the IAL to the HAL's gmm_free() procedure.
1218 int emgd_gmm_free(struct drm_device *dev, void *arg,
1219 struct drm_file *file_priv)
1221 emgd_drm_gmm_free_t *drm_data = arg;
1227 /* NOTE: no return value is desired: */
1228 dispatch->gmm_free(drm_data->offset);
1231 EMGD_DEBUG("This function has no drm_data->rtn value");
1234 } /* emgd_gmm_free() */
1238 * IOCTL to bridge the IAL to the HAL's gmm_flush_cache() procedure.
1240 int emgd_gmm_flush_cache(struct drm_device *dev, void *arg,
1241 struct drm_file *file_priv)
1243 emgd_drm_gmm_flush_cache_t *drm_data = arg;
1249 drm_data->rtn = dispatch->gmm_flush_cache();
1252 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1255 } /* emgd_gmm_flush_cache() */
1259 * IOCTL to bridge the IAL to the HAL's pan_display() procedure.
1261 int emgd_pan_display(struct drm_device *dev, void *arg,
1262 struct drm_file *file_priv)
1264 emgd_drm_pan_display_t *drm_data = arg;
1270 /* NOTE: the return value is different than normal: */
1271 drm_data->rtn = dispatch->pan_display(drm_data->display_handle,
1273 drm_data->y_offset);
1276 EMGD_DEBUG("drm_data->rtn = %ld", drm_data->rtn);
1279 } /* emgd_pan_display() */
1283 * IOCTL to bridge the IAL to the HAL's power_display() procedure.
1285 int emgd_power_display(struct drm_device *dev, void *arg,
1286 struct drm_file *file_priv)
1288 emgd_drm_power_display_t *drm_data = arg;
1289 igd_context_t *context = (igd_context_t *) handle;
1290 igd_display_context_t *display;
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;
1305 drm_data->rtn = dispatch->power_display(handle,
1306 drm_data->port_number,
1307 drm_data->power_state);
1310 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1313 } /* emgd_power_display() */
1317 * IOCTL to bridge the IAL to the HAL's pwr_alter() procedure.
1319 int emgd_pwr_alter(struct drm_device *dev, void *arg,
1320 struct drm_file *file_priv)
1322 emgd_drm_pwr_alter_t *drm_data = arg;
1328 drm_data->rtn = dispatch->pwr_alter(handle, drm_data->power_state);
1331 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1334 } /* emgd_pwr_alter() */
1338 * IOCTL to bridge the IAL to the HAL's query_dc() procedure.
1340 int emgd_query_dc(struct drm_device *dev, void *arg,
1341 struct drm_file *file_priv)
1343 emgd_drm_query_dc_t *drm_data = arg;
1344 unsigned long *dc_list = NULL;
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.
1357 drm_data->rtn = dispatch->query_dc(handle,
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).
1370 /* Count how many DCs were returned: */
1371 if(dc_list == NULL){
1372 EMGD_ERROR("query_dc() returned NULL !");
1381 drm_data->list_size = count;
1382 EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
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");
1393 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1396 } /* emgd_query_dc() */
1400 * IOCTL to bridge the IAL to the HAL's query_max_size_ovl() procedure.
1402 int emgd_query_max_size_ovl(struct drm_device *dev, void *arg,
1403 struct drm_file *file_priv)
1405 emgd_drm_query_max_size_ovl_t *drm_data = arg;
1411 drm_data->rtn = dispatch->query_max_size_ovl(drm_data->display_handle,
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.
1417 &(drm_data->max_width),
1418 &(drm_data->max_height));
1421 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1424 } /* emgd_query_max_size_ovl() */
1428 * IOCTL to bridge the IAL to the HAL's query_ovl() procedure.
1430 int emgd_query_ovl(struct drm_device *dev, void *arg,
1431 struct drm_file *file_priv)
1433 emgd_drm_query_ovl_t *drm_data = arg;
1439 drm_data->rtn = dispatch->query_ovl(drm_data->display_handle,
1442 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1445 } /* emgd_query_ovl() */
1449 * IOCTL to bridge the IAL to the HAL's query_mode_list() procedure.
1451 int emgd_query_mode_list(struct drm_device *dev, void *arg,
1452 struct drm_file *file_priv)
1454 emgd_drm_query_mode_list_t *drm_data = arg;
1455 igd_display_info_t *mode_list = NULL;
1456 igd_display_info_t *mode;
1463 drm_data->rtn = dispatch->query_mode_list(handle,
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).
1476 /* Count how many modes were returned: */
1478 while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
1482 drm_data->list_size = count;
1483 EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
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");
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);
1499 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1502 } /* emgd_query_mode_list() */
1506 * IOCTL to bridge the IAL to the HAL's set_attrs() procedure.
1508 int emgd_set_attrs(struct drm_device *dev, void *arg,
1509 struct drm_file *file_priv)
1511 emgd_drm_set_attrs_t *drm_data = arg;
1512 igd_attr_t *attr_list = drm_data->attr_list;
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.
1524 drm_data->list_size,
1528 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1531 } /* emgd_set_attrs() */
1535 * IOCTL to bridge the IAL to the HAL's set_palette_entry() procedure.
1537 int emgd_set_palette_entry(struct drm_device *dev, void *arg,
1538 struct drm_file *file_priv)
1540 emgd_drm_set_palette_entry_t *drm_data = arg;
1542 /*EMGD_TRACE_ENTER;*/
1546 drm_data->rtn = dispatch->set_palette_entry(drm_data->display_handle,
1547 drm_data->palette_entry,
1548 drm_data->palette_color);
1551 /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
1552 /*EMGD_TRACE_EXIT;*/
1554 } /* emgd_set_palette_entry() */
1558 * IOCTL to bridge the IAL to the HAL's set_surface() procedure.
1560 int emgd_set_surface(struct drm_device *dev, void *arg,
1561 struct drm_file *file_priv)
1563 emgd_drm_set_surface_t *drm_data = arg;
1569 drm_data->rtn = dispatch->set_surface(drm_data->display_handle,
1572 &(drm_data->surface),
1573 drm_data->appcontext,
1577 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1580 } /* emgd_set_surface() */
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
1592 int emgd_dihclone_set_surface(struct drm_device *dev, void *arg,
1593 struct drm_file *file_priv)
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;
1602 unsigned long x_offset, y_offset;
1606 memset(&surf, 0, sizeof(igd_surface_t));
1607 dc = *(context->mod_dispatch.dsp_current_dc);
1609 context->mod_dispatch.dsp_get_planes_pipes(
1610 &display_plane1, &display_plane2,
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;
1621 if( drm_data->dih_clone_display != CLONE_PRIMARY && drm_data->dih_clone_display != CLONE_SECONDARY){
1623 EMGD_ERROR(" emgd_dihclone_set_surface: Invalid Clone Display number");
1624 return -IGD_ERROR_INVAL;
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;
1633 display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1635 /*reverting back to DIH from fake clone */
1636 if( drm_data->mode == DIH){
1637 if (IGD_DC_VEXT(drm_emgd_dc)) {
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);
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 */
1652 if(context->mod_dispatch.dih_clone_display == CLONE_PRIMARY) {
1654 EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH1");
1655 surf.offset = pipe1->plane->fb_info->fb_base_offset;
1657 drm_data->rtn = dispatch->set_surface(display,
1658 IGD_PRIORITY_NORMAL,
1665 EMGD_ERROR(" emgd_dihclone_set_surface1: failed");
1666 return -IGD_ERROR_INVAL;
1668 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1669 surf.offset = pipe2->plane->fb_info->saved_offset;
1671 drm_data->rtn = dispatch->set_surface(display,
1672 IGD_PRIORITY_NORMAL,
1678 EMGD_ERROR(" emgd_dihclone_set_surface2: failed");
1679 return -IGD_ERROR_INVAL;
1683 } else { // if secondary clone
1685 EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH2");
1686 surf.offset = pipe1->plane->fb_info->saved_offset;
1688 drm_data->rtn = dispatch->set_surface(display,
1689 IGD_PRIORITY_NORMAL,
1694 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1695 surf.offset = pipe2->plane->fb_info->fb_base_offset;
1697 drm_data->rtn = dispatch->set_surface(display,
1698 IGD_PRIORITY_NORMAL,
1706 if (drm_data->rtn == 0) {
1707 context->mod_dispatch.in_dih_clone_mode = false;
1710 /* setting fake clone (dih clone) mode */
1711 if (drm_data->mode == CLONE) {
1712 if (IGD_DC_VEXT(drm_emgd_dc)) {
1715 if( drm_data->dih_clone_display == CLONE_PRIMARY){
1717 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1719 y_offset = (pipe1->plane->fb_info->height / 2);
1720 display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
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 */
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,
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,
1746 /* primary display */
1747 if( drm_data->dih_clone_display == CLONE_PRIMARY){
1748 surf.offset = pipe1->plane->fb_info->fb_base_offset;
1750 surf.offset = pipe2->plane->fb_info->fb_base_offset;
1753 display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
1756 drm_data->rtn = dispatch->set_surface(display,
1757 IGD_PRIORITY_NORMAL,
1763 /* secondary display */
1764 display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
1766 drm_data->rtn = dispatch->set_surface(display,
1767 IGD_PRIORITY_NORMAL,
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;
1780 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1782 EMGD_DEBUG("Returning 0");
1785 } /* emgd_dihclone_set_surface() */
1790 * IOCTL to bridge the IAL to the HAL's sync() procedure.
1792 int emgd_sync(struct drm_device *dev, void *arg,
1793 struct drm_file *file_priv)
1795 emgd_drm_sync_t *drm_data = arg;
1801 drm_data->rtn = dispatch->sync(drm_data->display_handle,
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.
1807 &(drm_data->in_sync),
1811 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
1818 * IOCTL to bridge the IAL to the HAL's driver_pre_init() procedure.
1820 int emgd_driver_pre_init(struct drm_device *dev, void *arg,
1821 struct drm_file *file_priv)
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;
1835 /* This flag will cause a call to emgd_init_display() in
1836 * emgd_driver_lastclose() if config_drm.init is true */
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().
1849 x_params = &(drm_data->params);
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).
1857 if (drm_emgd_configid < 0) {
1858 uc_params = config_drm.hal_params[2];
1860 uc_params = config_drm.hal_params[drm_emgd_configid-1];
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;
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"
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) {
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;
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"
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) {
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;
1905 #ifdef DEBUG_BUILD_TYPE
1906 if(emgd_debug && emgd_debug->MODULE_NAME)
1907 emgd_print_params(x_params);
1911 if (need_to_startup_hal) {
1912 /* emgd_driver_load() deferred driver initialization and configuration.
1913 * Therefore, do it now.
1915 * Before doing so, ensure both ports are turned on, even if the user
1916 * only requested one port.
1918 * TODO/FIXME - This assumes only two ports; is that wise long-term?
1920 if (x_params->port_order[1] == 0) {
1921 if (x_params->port_order[0] == 2) {
1922 x_params->port_order[1] = 4;
1924 x_params->port_order[1] = 2;
1928 EMGD_DEBUG("Starting the HAL");
1929 err = emgd_startup_hal(dev, x_params);
1931 mutex_unlock(&dev->struct_mutex);
1934 priv = dev->dev_private;
1935 priv->hal_running = 1;
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;
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;
1946 save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT &
1947 ~IGD_REG_SAVE_RB) | IGD_REG_SAVE_TYPE_REG;
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;
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.
1959 EMGD_DEBUG("Re-initializing the HAL with X driver values");
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.
1965 mode_context->display_color = x_params->display_color;
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.
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
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;
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;
1990 toggle_vblank_interrupts(TRUE);
1993 /* In case the X server ran, exited, and is starting again, we may need
1994 * to put the X server's state back:
1996 if (priv->saved_registers == X_SERVER_STATE_SAVED) {
1997 EMGD_DEBUG("Need to restore the X server's saved register state");
1999 if (config_drm.init) {
2000 save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
2003 save_flags = IGD_REG_SAVE_ALL;
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;
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.
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,
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.
2036 * Thus, it appears that the DSP module must somehow be re-initialized.
2038 * Note: dsp_init() also calls full_dsp_init() and the device-specific
2039 * init procedures, none of which uses any params.
2041 EMGD_DEBUG("Calling dsp_shutdown()");
2042 dsp_shutdown(handle);
2044 EMGD_DEBUG("Calling dsp_init()");
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",
2054 pi_pd_init(port, 0, 0, FALSE);
2059 * Because dsp_init was called above, a lot of the configuration
2060 * performed by the driver at initializat is now invalid.
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.
2069 /* Set a flag so that emgd_alter_displays() will turn back on the port
2070 * drivers' hardware:
2072 if(!mode_context->seamless) {
2073 priv->must_power_on_ports = 1;
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()
2082 if (x_params->display_flags & IGD_DISPLAY_FB_BLEND_OVL) {
2083 ovl_context->fb_blend_ovl = 1;
2085 } /* if (!need_to_startup_hal) */
2087 /* NOTE -- Below is our original analysis of what values/modules need
2088 * to be dealt with (above):
2090 * - mode_init() (in "micro_mode.c") uses display_color.
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).
2098 * [ ] Implemented proposal: set the value. Correct approach?
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
2106 * - The mode_context->quickboot value is only set (here) and is never used.
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).
2116 * - mode_context->video_input (corresponding to params->qb_video_input) is
2117 * only set (here) and is never used.
2119 * - mode_context->splash (corresponding to params->qb_splash) is only set
2120 * (here) and is never used.
2122 * [ ] New Proposal: potentially set the values and do nothing else. Is this
2123 * the correct approach?
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
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
2138 * - Notes: Here's what I learned in terms of what is used:
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.
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?
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).
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
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?
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:
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).
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).
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).
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
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.
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
2204 * None of the other modules use and/or need any params at this point:
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).
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
2232 &(drm_data->config_info));
2234 /* Check for a bit depth we support */
2235 pf_caps = drm_data->config_info.fb_caps;
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;
2246 if (!drm_data->config_info.pixel_format) {
2247 EMGD_DEBUG("Given depth (%lx) is not supported.", drm_data->bpp);
2251 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2254 } /* emgd_driver_pre_init() */
2258 * IOCTL to support emgd_hal2drm_get_ports(), which replaces the X driver's
2259 * usage of igd_get_param(...,IGD_PARAM_PORT_LIST,...)
2261 int emgd_driver_get_ports(struct drm_device *dev, void *arg,
2262 struct drm_file *file_priv)
2264 emgd_drm_driver_get_ports_t *drm_data = arg;
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.
2278 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2281 } /* emgd_driver_get_ports() */
2284 * IOCTL to support emgd_hal2drm_get_page_list(), which get's the list
2285 * of page address that make up a memory allocation.
2287 int emgd_get_page_list(struct drm_device *dev, void *arg,
2288 struct drm_file *file_priv)
2290 emgd_drm_get_page_list_t *drm_data = arg;
2292 unsigned long *list;
2293 unsigned long *new_list;
2298 dispatch->gmm_get_page_list(drm_data->offset, &list, &cnt);
2299 if (cnt > drm_data->addr_count) {
2301 * The user didn't allocate enough space for the
2302 * page list, this is an error.
2304 drm_data->addr_count = cnt;
2305 drm_data->rtn = -IGD_NO_MEM;
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];
2314 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2317 } /* emgd_driver_get_page_list() */
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).
2324 int emgd_start_pvrsrv(struct drm_device *dev, void *arg,
2325 struct drm_file *file_priv)
2327 emgd_drm_start_pvrsrv_t *drm_data = arg;
2328 drm_emgd_priv_t *priv = dev->dev_private;
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);
2343 } /* emgd_start_pvrsrv() */
2347 * IOCTL to bridge the IAL to the HAL's video_cmd_buf() procedure.
2349 int emgd_video_cmd_buf(struct drm_device *dev, void *arg,
2350 struct drm_file *file_priv)
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;
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));
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));
2376 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2379 } /* emgd_video_cmd_buf() */
2383 * IOCTL to bridge the IAL to the HAL's get_device_info() procedure.
2385 int emgd_get_device_info(struct drm_device *dev, void *arg,
2386 struct drm_file *file_priv)
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;
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;
2402 } /* emgd_get_device_info() */
2405 int emgd_init_video(struct drm_device *dev, void *arg,
2406 struct drm_file *file_priv)
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;
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);
2425 case CMD_VIDEO_INITIALIZE :
2427 switch (drm_data->engine) {
2428 case PSB_ENGINE_COMPOSITOR_MMU:
2429 drm_data->rtn = msvdx_init_compositor_mmu(drm_data->base0);
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);
2435 case TNC_ENGINE_ENCODE:
2436 drm_data->rtn = topaz_init_tnc(drm_data->wb_offset, drm_data->wb_addr, drm_data->firm_addr);
2442 case CMD_VIDEO_UNINITIALIZE :
2443 switch (drm_data->engine) {
2444 case PSB_ENGINE_VIDEO:
2445 drm_data->rtn = msvdx_uninit_plb(context);
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);
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);
2469 case CMD_VIDEO_SHUTDOWN:
2470 switch (drm_data->engine) {
2471 case PSB_ENGINE_VIDEO:
2472 drm_data->rtn = msvdx_shutdown_plb(context);
2482 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2485 } /* emgd_init_video() */
2487 int emgd_video_get_info(struct drm_device *dev, void *arg,
2488 struct drm_file *file_priv)
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;
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));
2502 case TNC_ENGINE_ENCODE:
2503 drm_data->rtn = topaz_get_fence_id(context, &(drm_data->fence_id));
2509 case CMD_VIDOE_GET_FRAME_SKIP:
2510 switch(drm_data->engine){
2511 case PSB_ENGINE_VIDEO:
2513 case TNC_ENGINE_ENCODE:
2514 drm_data->rtn = topaz_get_frame_skip(context, &(drm_data->frame_skip));
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);
2528 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2534 int emgd_video_flush_tlb(struct drm_device *dev, void *arg,
2535 struct drm_file *file_priv)
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;
2543 switch(drm_data->engine) {
2544 case PSB_ENGINE_VIDEO:
2547 case TNC_ENGINE_ENCODE:
2548 drm_data->rtn = topaz_flush_tnc(context);
2554 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2559 int emgd_preinit_mmu(struct drm_device *dev, void *arg,
2560 struct drm_file *file_priv)
2562 emgd_drm_preinit_mmu_t *drm_data = arg;
2566 drm_data->rtn = msvdx_preinit_mmu(drm_data->memcontext);
2568 EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
2573 int emgd_get_golden_htotal(struct drm_device *dev, void *arg,
2574 struct drm_file *file_priv){
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;
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;
2587 EMGD_DEBUG("emgd_get_golden_htotal : Entry");
2589 /* parameters sanity check */
2590 if (out_mode == NULL) {
2591 EMGD_ERROR("emgd_get_golden_htotal : NO Output Buffer");
2592 return -IGD_ERROR_INVAL;
2595 if (in_mode == NULL) {
2596 EMGD_ERROR("emgD_get_golden_htotal : NO Input Buffer");
2597 return -IGD_ERROR_INVAL;
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));
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;
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;
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;
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.
2627 /************************************************************/
2628 context->mod_dispatch.get_dd_timing(display,
2629 (pd_timing_t*)&igd_mode_table_in);
2631 /************************************************************/
2632 /* Send back the modified mode list that contains the delta */
2633 /************************************************************/
2635 memcpy (out_mode, in_mode, sizeof(igd_display_info_t));
2636 out_mode->reserved_dd = igd_mode_table_in[0].reserved_dd;
2638 out_mode->hblank_end = igd_mode_table_in[0].hblank_end;
2639 out_mode->vblank_end = igd_mode_table_in[0].vblank_end;
2645 int emgd_control_plane_format(struct drm_device *dev, void *arg,
2646 struct drm_file *file_priv)
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;
2652 EMGD_DEBUG("emgd_control_plane_format : Entry");
2654 if (drm_data->use_plane == FALSE)
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;
2663 plane_override = ((igd_plane_t *)(PLANE(drm_data->primary_secondary_dsp)));
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;
2672 /* Set plane_override to NULL */
2673 plane_override = NULL;
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);
2683 int emgd_set_overlay_display(struct drm_device *dev, void *arg,
2684 struct drm_file *file_priv)
2686 emgd_drm_set_overlay_display_t *drm_data = arg;
2687 igd_context_t *context = (igd_context_t *) handle;
2689 EMGD_DEBUG("emgd_set_overlay_display : Entry");
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;
2700 /* Call the set_ovl_display if no errors */
2701 context->dispatch.set_ovl_display(drm_data->ovl_display);
2706 int emgd_query_2d_caps_hwhint(struct drm_device *dev, void *arg,
2707 struct drm_file *file_priv){
2710 emgd_drm_query_2d_caps_hwhint_t *drm_data;
2711 unsigned long caps_val;
2712 unsigned long *status;
2714 EMGD_DEBUG("emgd_query_2d_caps_hwhint : Entry");
2716 /* parameters sanity check */
2718 EMGD_ERROR("emgd_query_2d_caps_hwhint : invalid argument");
2719 return -IGD_ERROR_INVAL;
2724 caps_val = (unsigned long) drm_data->caps_val;
2725 status = (unsigned long *) drm_data->status;
2727 igd_query_2d_caps_hwhint(handle, caps_val, status);