[linux-yocto] [PATCH 1/3] emgd: add emgd 1.18 driver sources
nitin.a.kamble at intel.com
nitin.a.kamble at intel.com
Tue Jul 2 12:51:29 PDT 2013
From: Nitin A Kamble <nitin.a.kamble at intel.com>
This is starting-point code that subsequent patches will modify. This is
a virgin copy of the code from the emgd 1.18 driver.
This code is coming from
IEMGD_HEAD_Linux/common/drm/emgd_drm.tgz
which is a piece from the 'Linux Tar Ball' release of EMGD 1.18 downloaded
from here:
http://downloadmirror.intel.com/22865/eng/LIN_IEMGD_1_18_GOLD_3398.tgz
Signed-off-by: Nitin A Kamble <nitin.a.kamble at intel.com>
---
drivers/gpu/drm/emgd/Makefile | 331 ++
drivers/gpu/drm/emgd/emgd/cfg/config.h | 113 +
drivers/gpu/drm/emgd/emgd/cfg/config_default.h | 199 +
drivers/gpu/drm/emgd/emgd/cfg/config_helper.c | 244 ++
.../gpu/drm/emgd/emgd/core/init/cmn/igd_global.c | 34 +
drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c | 918 +++++
.../drm/emgd/emgd/core/init/cmn/init_dispatch.h | 65 +
drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c | 458 +++
.../drm/emgd/emgd/core/init/plb/micro_init_plb.c | 631 ++++
drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c | 621 ++++
.../drm/emgd/emgd/core/init/tnc/micro_init_tnc.c | 1025 +++++
drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c | 2368 ++++++++++++
.../drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h | 64 +
.../gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c | 709 ++++
.../gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c | 542 +++
.../gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c | 2362 ++++++++++++
drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c | 1347 +++++++
drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h | 59 +
.../drm/emgd/emgd/display/mode/cmn/micro_mode.c | 1772 +++++++++
.../drm/emgd/emgd/display/mode/cmn/mode_dispatch.h | 393 ++
.../gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c | 1467 ++++++++
.../drm/emgd/emgd/display/mode/plb/clocks_plb.c | 711 ++++
.../drm/emgd/emgd/display/mode/plb/kms_mode_plb.c | 1102 ++++++
.../emgd/emgd/display/mode/plb/micro_mode_plb.c | 1391 +++++++
.../gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c | 1963 ++++++++++
.../gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h | 47 +
.../drm/emgd/emgd/display/mode/tnc/clocks_tnc.c | 1184 ++++++
.../drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c | 1746 +++++++++
.../emgd/emgd/display/mode/tnc/micro_mode_tnc.c | 2659 +++++++++++++
.../gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c | 2219 +++++++++++
.../gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h | 52 +
drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c | 528 +++
.../gpu/drm/emgd/emgd/display/pi/cmn/displayid.c | 1109 ++++++
drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c | 1187 ++++++
.../drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h | 78 +
drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c | 260 ++
.../gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c | 2545 +++++++++++++
.../gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c | 215 ++
drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c | 1921 ++++++++++
drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c | 943 +++++
.../drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c | 599 +++
.../drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c | 929 +++++
drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h | 176 +
drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c | 516 +++
drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c | 1023 +++++
drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c | 2596 +++++++++++++
drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h | 211 ++
drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c | 478 +++
drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c | 1450 ++++++++
drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c | 874 +++++
drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c | 2765 ++++++++++++++
drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c | 186 +
drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c | 1365 +++++++
drivers/gpu/drm/emgd/emgd/drm/image_data.h | 33 +
drivers/gpu/drm/emgd/emgd/drm/splash_screen.c | 2221 +++++++++++
drivers/gpu/drm/emgd/emgd/drm/splash_screen.h | 280 ++
drivers/gpu/drm/emgd/emgd/drm/user_config.c | 257 ++
drivers/gpu/drm/emgd/emgd/drm/user_config.h | 119 +
drivers/gpu/drm/emgd/emgd/gmm/gmm.c | 1421 +++++++
drivers/gpu/drm/emgd/emgd/gmm/gtt.c | 436 +++
drivers/gpu/drm/emgd/emgd/include/cmd.h | 47 +
drivers/gpu/drm/emgd/emgd/include/context.h | 256 ++
drivers/gpu/drm/emgd/emgd/include/debug.h | 169 +
drivers/gpu/drm/emgd/emgd/include/decode.h | 76 +
drivers/gpu/drm/emgd/emgd/include/dispatch.h | 59 +
drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h | 78 +
drivers/gpu/drm/emgd/emgd/include/displayid.h | 663 ++++
drivers/gpu/drm/emgd/emgd/include/dsp.h | 46 +
drivers/gpu/drm/emgd/emgd/include/edid.h | 130 +
drivers/gpu/drm/emgd/emgd/include/general.h | 84 +
drivers/gpu/drm/emgd/emgd/include/instr_common.h | 54 +
drivers/gpu/drm/emgd/emgd/include/intelpci.h | 98 +
drivers/gpu/drm/emgd/emgd/include/math_fix.h | 59 +
drivers/gpu/drm/emgd/emgd/include/memlist.h | 153 +
drivers/gpu/drm/emgd/emgd/include/memory.h | 421 +++
drivers/gpu/drm/emgd/emgd/include/mode.h | 444 +++
drivers/gpu/drm/emgd/emgd/include/mode_access.h | 52 +
drivers/gpu/drm/emgd/emgd/include/module_init.h | 109 +
drivers/gpu/drm/emgd/emgd/include/msvdx.h | 259 ++
drivers/gpu/drm/emgd/emgd/include/pci.h | 257 ++
drivers/gpu/drm/emgd/emgd/include/pd.h | 767 ++++
drivers/gpu/drm/emgd/emgd/include/pd_init.h | 191 +
drivers/gpu/drm/emgd/emgd/include/pi.h | 86 +
drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h | 67 +
drivers/gpu/drm/emgd/emgd/include/plb/cmd.h | 43 +
drivers/gpu/drm/emgd/emgd/include/plb/context.h | 212 ++
drivers/gpu/drm/emgd/emgd/include/plb/instr.h | 224 ++
drivers/gpu/drm/emgd/emgd/include/plb/mi.h | 77 +
drivers/gpu/drm/emgd/emgd/include/plb/regs.h | 747 ++++
drivers/gpu/drm/emgd/emgd/include/plb/sgx.h | 217 ++
drivers/gpu/drm/emgd/emgd/include/plb/state3d.h | 398 ++
.../gpu/drm/emgd/emgd/include/plb/state3d_plb.h | 1299 +++++++
drivers/gpu/drm/emgd/emgd/include/psb_regs.h | 658 ++++
drivers/gpu/drm/emgd/emgd/include/rb.h | 186 +
drivers/gpu/drm/emgd/emgd/include/reset.h | 43 +
drivers/gpu/drm/emgd/emgd/include/sched.h | 197 +
drivers/gpu/drm/emgd/emgd/include/state2d.h | 69 +
drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h | 40 +
drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h | 39 +
drivers/gpu/drm/emgd/emgd/include/tnc/context.h | 37 +
drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h | 133 +
drivers/gpu/drm/emgd/emgd/include/tnc/instr.h | 40 +
drivers/gpu/drm/emgd/emgd/include/tnc/mi.h | 41 +
drivers/gpu/drm/emgd/emgd/include/tnc/regs.h | 889 +++++
drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h | 36 +
drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h | 43 +
.../gpu/drm/emgd/emgd/include/tnc/state3d_plb.h | 38 +
drivers/gpu/drm/emgd/emgd/include/topaz.h | 212 ++
drivers/gpu/drm/emgd/emgd/include/utils.h | 174 +
drivers/gpu/drm/emgd/emgd/include/vga.h | 116 +
drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c | 138 +
drivers/gpu/drm/emgd/emgd/oal/src/memmap.c | 55 +
drivers/gpu/drm/emgd/emgd/oal/src/pci.c | 277 ++
drivers/gpu/drm/emgd/emgd/pal/Makefile.include | 50 +
drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu | 43 +
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c | 2366 ++++++++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h | 51 +
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c | 1061 ++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h | 85 +
.../drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h | 700 ++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c | 468 +++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h | 213 ++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c | 296 ++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h | 52 +
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c | 1994 ++++++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h | 243 ++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c | 494 +++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c | 1565 ++++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h | 59 +
.../drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c | 224 ++
.../drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h | 125 +
.../gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h | 472 +++
drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h | 73 +
drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car | 3362 +++++++++++++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c | 1587 ++++++++
drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h | 170 +
drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c | 114 +
drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h | 65 +
drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c | 1559 ++++++++
drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h | 164 +
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def | 25 +
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c | 1484 ++++++++
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h | 141 +
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c | 524 +++
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h | 182 +
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c | 725 ++++
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h | 482 +++
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c | 3899 ++++++++++++++++++++
drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h | 71 +
.../state/appcontext/cmn/appcontext_dispatch.h | 56 +
.../emgd/state/appcontext/cmn/igd_appcontext.c | 148 +
.../emgd/state/appcontext/plb/appcontext_plb.c | 207 ++
.../gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c | 305 ++
.../drm/emgd/emgd/state/power/cmn/pwr_dispatch.h | 52 +
.../gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c | 123 +
drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c | 451 +++
.../gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h | 73 +
drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c | 1157 ++++++
drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c | 1206 ++++++
drivers/gpu/drm/emgd/emgd/utils/math_fix.c | 138 +
drivers/gpu/drm/emgd/emgd/utils/memmap.c | 55 +
drivers/gpu/drm/emgd/emgd/utils/pci.c | 277 ++
drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c | 928 +++++
drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c | 1753 +++++++++
drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c | 583 +++
drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h | 78 +
.../gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c | 554 +++
.../drm/emgd/emgd/video/overlay/cmn/micro_ovl.c | 165 +
.../drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c | 1127 ++++++
.../drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h | 45 +
.../drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h | 57 +
.../gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h | 107 +
.../emgd/emgd/video/overlay/plb/micro_ovl_plb.c | 1725 +++++++++
.../gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c | 542 +++
.../gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h | 55 +
.../emgd/emgd/video/overlay/plb/ovl2_regs_plb.h | 76 +
.../gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c | 2188 +++++++++++
.../emgd/emgd/video/overlay/plb/ovl_plb_cache.c | 323 ++
.../emgd/emgd/video/overlay/plb/ovl_plb_cache.h | 161 +
.../drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h | 185 +
.../emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c | 1822 +++++++++
.../emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h | 76 +
.../gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c | 478 +++
.../gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h | 55 +
.../drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h | 190 +
.../gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c | 2469 +++++++++++++
.../emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c | 244 ++
.../emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h | 162 +
drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c | 342 ++
drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h | 128 +
drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c | 1201 ++++++
drivers/gpu/drm/emgd/include/emgd_drm.h | 938 +++++
drivers/gpu/drm/emgd/include/emgd_shared.h | 98 +
drivers/gpu/drm/emgd/include/gart.h | 38 +
drivers/gpu/drm/emgd/include/igd.h | 1630 ++++++++
drivers/gpu/drm/emgd/include/igd_2d.h | 380 ++
drivers/gpu/drm/emgd/include/igd_appcontext.h | 72 +
drivers/gpu/drm/emgd/include/igd_blend.h | 73 +
drivers/gpu/drm/emgd/include/igd_debug.h | 72 +
drivers/gpu/drm/emgd/include/igd_errno.h | 60 +
drivers/gpu/drm/emgd/include/igd_gart.h | 77 +
drivers/gpu/drm/emgd/include/igd_gmm.h | 390 ++
drivers/gpu/drm/emgd/include/igd_init.h | 895 +++++
drivers/gpu/drm/emgd/include/igd_interrupt.h | 300 ++
drivers/gpu/drm/emgd/include/igd_mode.h | 936 +++++
drivers/gpu/drm/emgd/include/igd_ovl.h | 327 ++
drivers/gpu/drm/emgd/include/igd_pd.h | 544 +++
drivers/gpu/drm/emgd/include/igd_pi.h | 130 +
drivers/gpu/drm/emgd/include/igd_pwr.h | 65 +
drivers/gpu/drm/emgd/include/igd_rb.h | 92 +
drivers/gpu/drm/emgd/include/igd_render.h | 573 +++
drivers/gpu/drm/emgd/include/igd_reset.h | 55 +
drivers/gpu/drm/emgd/include/igd_version.h | 41 +
drivers/gpu/drm/emgd/include/igd_vga.h | 65 +
drivers/gpu/drm/emgd/include/io.h | 422 +++
drivers/gpu/drm/emgd/include/memmap.h | 104 +
drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h | 263 ++
drivers/gpu/drm/emgd/pvr/include4/img_defs.h | 104 +
drivers/gpu/drm/emgd/pvr/include4/img_types.h | 124 +
drivers/gpu/drm/emgd/pvr/include4/ioctldef.h | 94 +
drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h | 95 +
drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h | 123 +
drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h | 27 +
drivers/gpu/drm/emgd/pvr/include4/pvrversion.h | 34 +
drivers/gpu/drm/emgd/pvr/include4/regpaths.h | 39 +
drivers/gpu/drm/emgd/pvr/include4/services.h | 866 +++++
drivers/gpu/drm/emgd/pvr/include4/servicesext.h | 647 ++++
drivers/gpu/drm/emgd/pvr/include4/sgx_options.h | 220 ++
drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h | 323 ++
drivers/gpu/drm/emgd/pvr/include4/sgxscript.h | 77 +
.../services4/3rdparty/emgd_bufferclass/emgd_bc.c | 390 ++
.../services4/3rdparty/emgd_bufferclass/emgd_bc.h | 174 +
.../3rdparty/emgd_bufferclass/emgd_bc_linux.c | 1055 ++++++
.../services4/3rdparty/emgd_displayclass/emgd_dc.c | 2815 ++++++++++++++
.../services4/3rdparty/emgd_displayclass/emgd_dc.h | 342 ++
.../3rdparty/emgd_displayclass/emgd_dc_linux.c | 153 +
.../services4/include/env/linux/pvr_drm_shared.h | 59 +
.../drm/emgd/pvr/services4/include/kernelbuffer.h | 57 +
.../drm/emgd/pvr/services4/include/kerneldisplay.h | 152 +
.../drm/emgd/pvr/services4/include/pvr_bridge.h | 1380 +++++++
.../drm/emgd/pvr/services4/include/pvr_bridge_km.h | 292 ++
.../gpu/drm/emgd/pvr/services4/include/pvrmmap.h | 32 +
.../drm/emgd/pvr/services4/include/pvrsrv_errors.h | 189 +
.../drm/emgd/pvr/services4/include/servicesint.h | 272 ++
.../drm/emgd/pvr/services4/include/sgx_bridge.h | 473 +++
.../drm/emgd/pvr/services4/include/sgx_mkif_km.h | 339 ++
.../gpu/drm/emgd/pvr/services4/include/sgxinfo.h | 288 ++
.../services4/srvkm/bridged/bridged_pvr_bridge.c | 3447 +++++++++++++++++
.../services4/srvkm/bridged/bridged_pvr_bridge.h | 227 ++
.../pvr/services4/srvkm/bridged/bridged_support.c | 81 +
.../pvr/services4/srvkm/bridged/bridged_support.h | 39 +
.../srvkm/bridged/sgx/bridged_sgx_bridge.c | 2510 +++++++++++++
.../srvkm/bridged/sgx/bridged_sgx_bridge.h | 38 +
.../pvr/services4/srvkm/common/buffer_manager.c | 2069 +++++++++++
.../emgd/pvr/services4/srvkm/common/deviceclass.c | 2060 +++++++++++
.../emgd/pvr/services4/srvkm/common/devicemem.c | 1546 ++++++++
.../drm/emgd/pvr/services4/srvkm/common/handle.c | 1545 ++++++++
.../gpu/drm/emgd/pvr/services4/srvkm/common/hash.c | 459 +++
.../drm/emgd/pvr/services4/srvkm/common/lists.c | 95 +
.../gpu/drm/emgd/pvr/services4/srvkm/common/mem.c | 147 +
.../emgd/pvr/services4/srvkm/common/mem_debug.c | 246 ++
.../drm/emgd/pvr/services4/srvkm/common/metrics.c | 156 +
.../emgd/pvr/services4/srvkm/common/pdump_common.c | 1723 +++++++++
.../drm/emgd/pvr/services4/srvkm/common/perproc.c | 279 ++
.../drm/emgd/pvr/services4/srvkm/common/power.c | 743 ++++
.../drm/emgd/pvr/services4/srvkm/common/pvrsrv.c | 1194 ++++++
.../drm/emgd/pvr/services4/srvkm/common/queue.c | 1161 ++++++
.../gpu/drm/emgd/pvr/services4/srvkm/common/ra.c | 1867 ++++++++++
.../drm/emgd/pvr/services4/srvkm/common/resman.c | 704 ++++
.../drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c | 2772 ++++++++++++++
.../drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h | 135 +
.../drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c | 454 +++
.../services4/srvkm/devices/sgx/sgx_bridge_km.h | 143 +
.../pvr/services4/srvkm/devices/sgx/sgxconfig.h | 161 +
.../pvr/services4/srvkm/devices/sgx/sgxinfokm.h | 348 ++
.../emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c | 2267 ++++++++++++
.../emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c | 740 ++++
.../pvr/services4/srvkm/devices/sgx/sgxpower.c | 465 +++
.../pvr/services4/srvkm/devices/sgx/sgxreset.c | 485 +++
.../pvr/services4/srvkm/devices/sgx/sgxtransfer.c | 549 +++
.../pvr/services4/srvkm/devices/sgx/sgxutils.c | 1054 ++++++
.../pvr/services4/srvkm/devices/sgx/sgxutils.h | 95 +
.../emgd/pvr/services4/srvkm/env/linux/env_data.h | 62 +
.../pvr/services4/srvkm/env/linux/env_perproc.h | 52 +
.../drm/emgd/pvr/services4/srvkm/env/linux/event.c | 272 ++
.../drm/emgd/pvr/services4/srvkm/env/linux/event.h | 28 +
.../pvr/services4/srvkm/env/linux/kbuild/Makefile | 151 +
.../emgd/pvr/services4/srvkm/env/linux/linkage.h | 57 +
.../drm/emgd/pvr/services4/srvkm/env/linux/lock.h | 28 +
.../drm/emgd/pvr/services4/srvkm/env/linux/mm.c | 2377 ++++++++++++
.../drm/emgd/pvr/services4/srvkm/env/linux/mm.h | 323 ++
.../drm/emgd/pvr/services4/srvkm/env/linux/mmap.c | 1149 ++++++
.../drm/emgd/pvr/services4/srvkm/env/linux/mmap.h | 103 +
.../emgd/pvr/services4/srvkm/env/linux/module.c | 756 ++++
.../drm/emgd/pvr/services4/srvkm/env/linux/mutex.c | 28 +
.../drm/emgd/pvr/services4/srvkm/env/linux/mutex.h | 37 +
.../emgd/pvr/services4/srvkm/env/linux/mutils.c | 126 +
.../emgd/pvr/services4/srvkm/env/linux/mutils.h | 93 +
.../emgd/pvr/services4/srvkm/env/linux/osfunc.c | 2534 +++++++++++++
.../emgd/pvr/services4/srvkm/env/linux/osperproc.c | 109 +
.../drm/emgd/pvr/services4/srvkm/env/linux/pdump.c | 658 ++++
.../pvr/services4/srvkm/env/linux/private_data.h | 63 +
.../drm/emgd/pvr/services4/srvkm/env/linux/proc.c | 962 +++++
.../drm/emgd/pvr/services4/srvkm/env/linux/proc.h | 119 +
.../pvr/services4/srvkm/env/linux/pvr_bridge_k.c | 647 ++++
.../emgd/pvr/services4/srvkm/env/linux/pvr_debug.c | 418 +++
.../emgd/pvr/services4/srvkm/env/linux/pvr_drm.c | 301 ++
.../emgd/pvr/services4/srvkm/env/linux/pvr_drm.h | 65 +
.../emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h | 633 ++++
.../emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h | 586 +++
.../emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h | 828 +++++
.../drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h | 78 +
.../emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h | 310 ++
.../pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h | 159 +
.../drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h | 75 +
.../pvr/services4/srvkm/include/buffer_manager.h | 214 ++
.../drm/emgd/pvr/services4/srvkm/include/device.h | 274 ++
.../drm/emgd/pvr/services4/srvkm/include/handle.h | 378 ++
.../drm/emgd/pvr/services4/srvkm/include/hash.h | 69 +
.../drm/emgd/pvr/services4/srvkm/include/lists.h | 172 +
.../drm/emgd/pvr/services4/srvkm/include/metrics.h | 126 +
.../drm/emgd/pvr/services4/srvkm/include/osfunc.h | 483 +++
.../emgd/pvr/services4/srvkm/include/osperproc.h | 72 +
.../emgd/pvr/services4/srvkm/include/pdump_km.h | 448 +++
.../pvr/services4/srvkm/include/pdump_osfunc.h | 133 +
.../drm/emgd/pvr/services4/srvkm/include/perproc.h | 106 +
.../drm/emgd/pvr/services4/srvkm/include/power.h | 116 +
.../drm/emgd/pvr/services4/srvkm/include/queue.h | 115 +
.../gpu/drm/emgd/pvr/services4/srvkm/include/ra.h | 151 +
.../drm/emgd/pvr/services4/srvkm/include/resman.h | 109 +
.../pvr/services4/srvkm/include/services_headers.h | 45 +
.../drm/emgd/pvr/services4/srvkm/include/srvkm.h | 65 +
.../emgd/pvr/services4/system/common/sysconfig.c | 1367 +++++++
.../emgd/pvr/services4/system/common/sysutils.c | 26 +
.../emgd/pvr/services4/system/include/oemfuncs.h | 68 +
.../services4/system/include/sys_pvr_drm_shared.h | 34 +
.../emgd/pvr/services4/system/include/syscommon.h | 27 +
.../emgd/pvr/services4/system/include/sysconfig.h | 326 ++
.../emgd/pvr/services4/system/include/sysinfo.h | 42 +
.../emgd/pvr/services4/system/include/syslocal.h | 80 +
.../drm/emgd/pvr/services4/system/plb/sysconfig.c | 48 +
.../gpu/drm/emgd/pvr/services4/system/plb/sysplb.h | 33 +
.../drm/emgd/pvr/services4/system/tnc/sysconfig.c | 48 +
.../gpu/drm/emgd/pvr/services4/system/tnc/systnc.h | 33 +
.../emgd/pvr/tools/intern/debug/client/linuxsrv.h | 44 +
.../tools/intern/debug/dbgdriv/common/dbgdriv.c | 2072 +++++++++++
.../tools/intern/debug/dbgdriv/common/dbgdriv.h | 112 +
.../tools/intern/debug/dbgdriv/common/hostfunc.h | 54 +
.../pvr/tools/intern/debug/dbgdriv/common/hotkey.c | 131 +
.../pvr/tools/intern/debug/dbgdriv/common/hotkey.h | 56 +
.../pvr/tools/intern/debug/dbgdriv/common/ioctl.c | 367 ++
.../pvr/tools/intern/debug/dbgdriv/common/ioctl.h | 83 +
.../tools/intern/debug/dbgdriv/linux/hostfunc.c | 300 ++
.../intern/debug/dbgdriv/linux/kbuild/Makefile | 33 +
.../pvr/tools/intern/debug/dbgdriv/linux/main.c | 294 ++
.../debug/dbgdriv/linux/makefile.linux.common | 38 +
356 files changed, 188933 insertions(+)
create mode 100755 drivers/gpu/drm/emgd/Makefile
create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config.h
create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config_default.h
create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
create mode 100755 drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
create mode 100755 drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/image_data.h
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/user_config.c
create mode 100755 drivers/gpu/drm/emgd/emgd/drm/user_config.h
create mode 100755 drivers/gpu/drm/emgd/emgd/gmm/gmm.c
create mode 100644 drivers/gpu/drm/emgd/emgd/gmm/gtt.c
create mode 100644 drivers/gpu/drm/emgd/emgd/include/cmd.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/context.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/debug.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/decode.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/displayid.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/dsp.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/edid.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/general.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/instr_common.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/intelpci.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/math_fix.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/memlist.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/memory.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/mode.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/mode_access.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/module_init.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/msvdx.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/pci.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/pd.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/pd_init.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/pi.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
create mode 100755 drivers/gpu/drm/emgd/emgd/include/plb/context.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/instr.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/mi.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/regs.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/psb_regs.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/rb.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/reset.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/sched.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/state2d.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/context.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
create mode 100755 drivers/gpu/drm/emgd/emgd/include/topaz.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/utils.h
create mode 100644 drivers/gpu/drm/emgd/emgd/include/vga.h
create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/pci.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/Makefile.include
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
create mode 100644 drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
create mode 100755 drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/utils/math_fix.c
create mode 100644 drivers/gpu/drm/emgd/emgd/utils/memmap.c
create mode 100644 drivers/gpu/drm/emgd/emgd/utils/pci.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
create mode 100755 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
create mode 100755 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
create mode 100755 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
create mode 100755 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
create mode 100644 drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
create mode 100644 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
create mode 100755 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
create mode 100755 drivers/gpu/drm/emgd/include/emgd_drm.h
create mode 100644 drivers/gpu/drm/emgd/include/emgd_shared.h
create mode 100644 drivers/gpu/drm/emgd/include/gart.h
create mode 100755 drivers/gpu/drm/emgd/include/igd.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_2d.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_appcontext.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_blend.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_debug.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_errno.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_gart.h
create mode 100755 drivers/gpu/drm/emgd/include/igd_gmm.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_init.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_interrupt.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_mode.h
create mode 100755 drivers/gpu/drm/emgd/include/igd_ovl.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_pd.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_pi.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_pwr.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_rb.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_render.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_reset.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_version.h
create mode 100644 drivers/gpu/drm/emgd/include/igd_vga.h
create mode 100644 drivers/gpu/drm/emgd/include/io.h
create mode 100644 drivers/gpu/drm/emgd/include/memmap.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/img_defs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/img_types.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/regpaths.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/services.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/servicesext.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
create mode 100755 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
diff --git a/drivers/gpu/drm/emgd/Makefile b/drivers/gpu/drm/emgd/Makefile
new file mode 100755
index 0000000..18d87fc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/Makefile
@@ -0,0 +1,331 @@
+#----------------------------------------------------------------------------
+# Filename: Makefile.gnu
+# $Revision: 1.59 $
+#----------------------------------------------------------------------------
+# Copyright (c) 2002-2010, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#----------------------------------------------------------------------------
+export EGD_TOPLEVEL = DRM Driver
+
+KERNELVER ?= $(shell uname -r)
+KERNELDIR ?= /lib/modules/$(KERNELVER)/build
+INSTALLDIR ?= /lib/modules/$(KERNELVER)/kernel/drivers/gpu/drm/emgd
+
+BLUE = \033[34m
+OFF = \033[0m
+BUILD ?= release
+CONFIG_PVR_RELEASE ?= $(BUILD)
+CONFIG_DRM_EGD ?= m
+
+# Get the include paths pointed to the right place.
+export EMGD_MOD_DIR ?= $(CURDIR)
+
+BUILDDATE ?= $(shell date +%Y%m%d)
+
+PROJECT_INCLUDES = \
+ -I$(EMGD_MOD_DIR)/include \
+ -I$(EMGD_MOD_DIR)/emgd/display/mode/cmn \
+ -I$(EMGD_MOD_DIR)/emgd/video/overlay/cmn \
+ -I$(EMGD_MOD_DIR)/emgd/video/msvdx \
+ -I$(EMGD_MOD_DIR)/emgd/include \
+ -I$(EMGD_MOD_DIR)/emgd/cfg \
+ -I$(EMGD_MOD_DIR)/emgd/pal/lpd \
+ -I$(EMGD_MOD_DIR)/emgd/pal/lvds \
+ -I$(EMGD_MOD_DIR)/emgd/pal/ch7036 \
+ -I$(EMGD_MOD_DIR)/emgd/drm \
+ -I$(KERNELDIR)/include/drm \
+ -I/usr/src/linux-headers-2.6.32-5-common/include/drm \
+ -I$(EMGD_MOD_DIR)/pvr/include4 \
+ -I$(EMGD_MOD_DIR)/pvr/services4/include \
+ -I$(EMGD_MOD_DIR)/pvr/services4/include/env/linux \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/env/linux \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/include \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/bridged \
+ -I$(EMGD_MOD_DIR)/pvr/services4/system/plb \
+ -I$(EMGD_MOD_DIR)/pvr/services4/system/tnc \
+ -I$(EMGD_MOD_DIR)/pvr/services4/system/include \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/hwdefs \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/bridged/sgx \
+ -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/devices/sgx \
+ -I$(EMGD_MOD_DIR)/pvr/services4/3rdparty/emgd_bufferclass \
+ -I$(EMGD_MOD_DIR)/pvr/tools/intern/debug \
+ -DSUPPORT_DRI_DRM_EXT \
+ -DLINUX \
+ -DPVR_BUILD_DIR="\"emgd\"" \
+ -DPVR_BUILD_DATE="\"$(BUILDDATE)\"" \
+ -DPVR_BUILD_TYPE="\"$(CONFIG_PVR_RELEASE)\"" \
+ -DBUILD=$(CONFIG_PVR_RELEASE) \
+ -DPVR_SECURE_HANDLES \
+ -DPVR_PROC_USE_SEQ_FILE \
+ -DLDM_PCI \
+ -DSUPPORT_CACHEFLUSH_ON_ALLOC \
+ -DSUPPORT_DRI_DRM \
+ -DSGX535 \
+ -DSGX_CORE_REV=121 \
+ -UDEBUG_LOG_PATH_TRUNCATE \
+ -DDISPLAY_CONTROLLER=emgd_dc \
+ -D_XOPEN_SOURCE=600 \
+ -DSERVICES4 \
+ -DPVR2D_VALIDATE_INPUT_PARAMS \
+ -DSUPPORT_SRVINIT \
+ -DSUPPORT_SGX \
+ -DSUPPORT_PERCONTEXT_PB \
+ -DSUPPORT_LINUX_X86_WRITECOMBINE \
+ -DSUPPORT_SECURE_DRM_AUTH_EXPORT \
+ -DSUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION \
+ -DTRANSFER_QUEUE \
+ -DSYS_USING_INTERRUPTS \
+ -DSUPPORT_HW_RECOVERY \
+ -DSUPPORT_ACTIVE_POWER_MANAGEMENT \
+ -DPVR_SECURE_HANDLES \
+ -DUSE_PTHREADS \
+ -DSUPPORT_SGX_EVENT_OBJECT \
+ -DSUPPORT_SGX_HWPERF \
+ -DSUPPORT_LINUX_X86_PAT \
+ -DSUPPORT_SGX535 \
+ -DSUPPORT_CACHE_LINE_FLUSH \
+ -DSUPPORT_CPU_CACHED_BUFFERS \
+ -DDEBUG_MESA_OGL_TRACE \
+ -DSUPPORT_EGL_IMAGE_SYNC_DEPENDENCY \
+
+
+ifeq "$(strip $(CONFIG_PVR_RELEASE))" "release"
+ ccflags-y += -DRELEASE
+else
+ # FIXME: Looks like this causes conflicts in the emgd code.
+ ccflags-y += -DDEBUG
+ ccflags-y += -DDEBUG_BUILD_TYPE
+endif
+
+EXTRA_CFLAGS += $(PROJECT_INCLUDES)
+
+ifeq ($(PDUMP),1)
+ EXTRA_CFLAGS += -DPDUMP=1
+endif
+
+EMGD_OBJS := \
+ emgd/drm/emgd_fb.o \
+ emgd/drm/emgd_fbcon.o \
+ emgd/drm/emgd_crtc.o \
+ emgd/drm/emgd_encoder.o \
+ emgd/drm/emgd_connector.o \
+ emgd/drm/emgd_mmap.o \
+ emgd/drm/emgd_drv.o \
+ emgd/drm/emgd_interface.o \
+ emgd/drm/emgd_test_pvrsrv.o \
+ emgd/drm/user_config.o \
+ emgd/drm/splash_screen.o \
+ emgd/display/pd/cmn/pd.o \
+ emgd/display/pi/cmn/igd_pi.o \
+ emgd/display/pi/cmn/displayid.o \
+ emgd/display/pi/cmn/pd_init_all.o \
+ emgd/display/pi/cmn/edid.o \
+ emgd/display/pi/cmn/pi.o \
+ emgd/display/pi/cmn/mode_table.o \
+ emgd/display/pi/tnc/i2c_gmbus_tnc.o \
+ emgd/display/pi/tnc/i2c_bitbash_tnc.o \
+ emgd/display/pi/plb/i2c_plb.o \
+ emgd/display/mode/cmn/match.o \
+ emgd/display/mode/cmn/micro_mode.o \
+ emgd/display/mode/cmn/vga_mode.o \
+ emgd/display/mode/cmn/igd_mode.o \
+ emgd/display/mode/tnc/micro_mode_tnc.o \
+ emgd/display/mode/tnc/mode_tnc.o \
+ emgd/display/mode/tnc/kms_mode_tnc.o \
+ emgd/display/mode/tnc/clocks_tnc.o \
+ emgd/display/mode/plb/micro_mode_plb.o \
+ emgd/display/mode/plb/clocks_plb.o \
+ emgd/display/mode/plb/mode_plb.o \
+ emgd/display/mode/plb/kms_mode_plb.o \
+ emgd/display/dsp/cmn/dsp.o \
+ emgd/display/dsp/tnc/dsp_tnc.o \
+ emgd/display/dsp/plb/dsp_plb.o \
+ emgd/core/init/cmn/igd_global.o \
+ emgd/core/init/cmn/igd_init.o \
+ emgd/core/init/tnc/micro_init_tnc.o \
+ emgd/core/init/tnc/init_tnc.o \
+ emgd/core/init/plb/init_plb.o \
+ emgd/core/init/plb/micro_init_plb.o \
+ emgd/state/power/cmn/igd_pwr.o \
+ emgd/state/power/plb/pwr_plb.o \
+ emgd/state/appcontext/cmn/igd_appcontext.o \
+ emgd/state/appcontext/plb/appcontext_plb.o \
+ emgd/state/reg/cmn/reg.o \
+ emgd/state/reg/tnc/reg_tnc.o \
+ emgd/state/reg/plb/reg_plb.o \
+ emgd/video/overlay/cmn/ovl_coeff.o \
+ emgd/video/overlay/cmn/igd_ovl.o \
+ emgd/video/overlay/cmn/micro_ovl.o \
+ emgd/video/overlay/tnc/ovl_tnc_cache.o \
+ emgd/video/overlay/tnc/ovl_tnc.o \
+ emgd/video/overlay/tnc/ovl2_tnc.o \
+ emgd/video/overlay/tnc/micro_ovl_tnc.o \
+ emgd/video/overlay/plb/ovl_plb_cache.o \
+ emgd/video/overlay/plb/ovl2_plb.o \
+ emgd/video/overlay/plb/ovl_plb.o \
+ emgd/video/overlay/plb/micro_ovl_plb.o \
+ emgd/video/msvdx/msvdx_init.o \
+ emgd/video/msvdx/msvdx.o \
+ emgd/video/msvdx/msvdx_pvr.o \
+ emgd/video/topaz/topaz_init.o \
+ emgd/video/topaz/topaz.o \
+ emgd/pal/sdvo/sdvo_attr.o \
+ emgd/pal/sdvo/sdvo_hdmi.o \
+ emgd/pal/sdvo/sdvo_port.o \
+ emgd/pal/sdvo/sdvo_intf.o \
+ emgd/pal/ch7036/ch7036_attr.o \
+ emgd/pal/ch7036/ch7036_fw.o \
+ emgd/pal/ch7036/ch7036_intf.o \
+ emgd/pal/ch7036/ch7036_port.o \
+ emgd/pal/ch7036/ch7036.o \
+ emgd/pal/ch7036/ch7036_iic.o \
+ emgd/pal/ch7036/ch7036_pm.o \
+ emgd/pal/ch7036/ch7036_reg_table.o \
+ emgd/pal/ch7036/lvds/lvds.o \
+ emgd/pal/lvds/lvds.o \
+ emgd/pal/lpd/lpd.o \
+ emgd/gmm/gmm.o \
+ emgd/gmm/gtt.o \
+ emgd/utils/pci.o \
+ emgd/utils/memmap.o \
+ emgd/utils/math_fix.o \
+
+ENVDIR = pvr/services4/srvkm/env/linux
+COMMONDIR = pvr/services4/srvkm/common
+BRIDGEDDIR = pvr/services4/srvkm/bridged
+SYSCONFIGDIR = pvr/services4/system/common
+SGXDIR = pvr/services4/srvkm/devices/sgx
+DISPCLASSDIR = pvr/services4/3rdparty/emgd_displayclass
+BUFFERCLASSDIR = pvr/services4/3rdparty/emgd_bufferclass
+
+ifeq ($(PDUMP),1)
+DBGDRVDIR = pvr/tools/intern/debug/dbgdriv
+
+DBGDRV_OBJS = $(DBGDRVDIR)/linux/main.o \
+ $(DBGDRVDIR)/common/dbgdriv.o \
+ $(DBGDRVDIR)/common/ioctl.o \
+ $(DBGDRVDIR)/linux/hostfunc.o \
+ $(DBGDRVDIR)/common/hotkey.o
+endif
+
+ENV_OBJS = $(ENVDIR)/osfunc.o \
+ $(ENVDIR)/mutils.o \
+ $(ENVDIR)/mmap.o \
+ $(ENVDIR)/module.o \
+ $(ENVDIR)/pdump.o \
+ $(ENVDIR)/proc.o \
+ $(ENVDIR)/pvr_bridge_k.o \
+ $(ENVDIR)/pvr_debug.o \
+ $(ENVDIR)/mm.o \
+ $(ENVDIR)/mutex.o \
+ $(ENVDIR)/event.o \
+ $(ENVDIR)/osperproc.o \
+ $(ENVDIR)/pvr_drm.o
+
+COMMON_OBJS = $(COMMONDIR)/buffer_manager.o \
+ $(COMMONDIR)/devicemem.o \
+ $(COMMONDIR)/deviceclass.o \
+ $(COMMONDIR)/handle.o \
+ $(COMMONDIR)/hash.o \
+ $(COMMONDIR)/metrics.o \
+ $(COMMONDIR)/pvrsrv.o \
+ $(COMMONDIR)/queue.o \
+ $(COMMONDIR)/ra.o \
+ $(COMMONDIR)/resman.o \
+ $(COMMONDIR)/power.o \
+ $(COMMONDIR)/mem.o \
+ $(COMMONDIR)/pdump_common.o \
+ $(COMMONDIR)/perproc.o \
+ $(COMMONDIR)/lists.o \
+ $(COMMONDIR)/mem_debug.o
+
+BRIDGED_OBJS = $(BRIDGEDDIR)/bridged_support.o \
+ $(BRIDGEDDIR)/bridged_pvr_bridge.o \
+ $(BRIDGEDDIR)/sgx/bridged_sgx_bridge.o
+
+SYSCONFIG_OBJS = $(SYSCONFIGDIR)/sysconfig.o \
+ pvr/services4/system/tnc/sysconfig.o \
+ pvr/services4/system/plb/sysconfig.o \
+ $(SYSCONFIGDIR)/sysutils.o
+# $(SYSCONFIGDIR)/sysirq.o
+# $(SYSCONFIGDIR)/ospm_power.o \
+
+SGX_OBJS = $(SGXDIR)/sgxinit.o \
+ $(SGXDIR)/sgxpower.o \
+ $(SGXDIR)/sgxreset.o \
+ $(SGXDIR)/sgxutils.o \
+ $(SGXDIR)/sgxkick.o \
+ $(SGXDIR)/sgxtransfer.o \
+ $(SGXDIR)/mmu.o \
+ $(SGXDIR)/pb.o
+
+DC_OBJS = $(DISPCLASSDIR)/emgd_dc.o \
+ $(DISPCLASSDIR)/emgd_dc_linux.o
+
+BC_OBJS = $(BUFFERCLASSDIR)/emgd_bc.o \
+ $(BUFFERCLASSDIR)/emgd_bc_linux.o
+
+
+emgd-y := \
+ $(DC_OBJS) \
+ $(EMGD_OBJS) \
+ $(ENV_OBJS) \
+ $(COMMON_OBJS) \
+ $(BRIDGED_OBJS) \
+ $(SYSCONFIG_OBJS) \
+ $(SGX_OBJS) \
+ $(BC_OBJS) \
+
+ifeq ($(PDUMP),1)
+ emgd-y += $(DBGDRV_OBJS)
+endif
+
+obj-$(CONFIG_DRM_EGD) += emgd.o
+
+all:: clean modules
+
+modules::
+ @echo $(CURDIR) -- $(CONFIG_PVR_RELEASE)
+ @echo "$(MAKE) -C $(KERNELDIR) M=$(CURDIR) modules"
+ @$(MAKE) -C $(KERNELDIR) M=$(CURDIR) modules
+
+clean::
+ @rm -f $(emgd-y)
+ @rm -f emgd.o emgd.mod.* emgd.ko Module.* modules.order
+ @find . -name "*.cmd" -exec rm '{}' \;
+
+install::
+ install -o root -g root -m 755 -d $(INSTALLDIR)
+ install -o root -g root -m 744 emgd.ko $(INSTALLDIR)
+ /sbin/depmod -a
+
+uninstall::
+ rmmod $(INSTALLDIR)/emgd.ko
+ rm -rf $(INSTALLDIR)/emgd.ko
+ /sbin/depmod -a
+
+debug::
+ export CONFIG_PVR_RELEASE=debug; $(MAKE) modules
+
+package:: clean
+ @echo -e "$(BLUE)Packaging $(EGD_TOPLEVEL)$(OFF)";
+ mkdir -p $(EGD_PKG)
+ tar -C $(EMGD_MOD_DIR) --exclude "CVS" -czf $(EGD_PKG)/emgd_drm.tgz *
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config.h b/drivers/gpu/drm/emgd/emgd/cfg/config.h
new file mode 100644
index 0000000..14e7ca8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config.h
@@ -0,0 +1,113 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config.h
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the compile options for the IGD compile. It is included
+ * by all IGD OAL and RAL modules. Do not remove valid options from this
+ * file, simply comment them out.
+ * Eventually a config tool will auto generate this file based on selected
+ * options.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_CONFIG_H
+#define _HAL_CONFIG_H
+
+/*
+ * Which Cores are supported
+ *
+ * Use Defaults
+ */
+
+/*
+ * This macro configures the DRM/kernel's EMGD_DEBUG() and EMGD_DEBUG_S() macros to
+ * use the KERN_INFO message priority, instead of the normal KERN_DEBUG message
+ * priority. This is useful for bugs (e.g. crashes) where dmesg can't be used
+ * to obtain debug messages.
+ */
+/* #define CONFIG_USE_INFO_PRIORITY */
+
+
+/*
+ * Which of the optional modules are included in the build
+ * for the most part this is for modules that need an init
+ * or power entry point.
+ *
+ * Use Defaults.
+ */
+
+/*
+ * Default FB/Display Resolution
+ */
+#define CONFIG_DEFAULT_WIDTH 640
+#define CONFIG_DEFAULT_HEIGHT 480
+#define CONFIG_DEFAULT_PF IGD_PF_ARGB32
+
+
+/*
+ power modes supported
+ 0 -don't support
+ 1 - support
+
+ Use Defaults.
+*/
+
+/*
+ * Turn off fences for performance analysis. 3d makes use of "Use Fences"
+ * So this will make fences regions become linear but everything should
+ * still work.
+ *
+ * #define CONFIG_NOFENCES
+ */
+
+/* Don't enable Dynamic port driver loading for simple driver. For simple,
+ * one can limit the port drivers by enabling CONFIG_LIMIT_PDS to
+ * required port drivers *
+ *
+ * Enable Dynamic port driver loading
+ *
+ * #define IGD_DPD_ENABLED 1 */
+
+/* Enable required port drivers. */
+#define CONFIG_LIMIT_PDS 1
+#define CONFIG_PD_ANALOG 0
+#define CONFIG_PD_LVDS 1
+#define CONFIG_PD_SDVO 1
+#define CONFIG_PD_TV 0 /* Integrated TV for NAPA */
+#define CONFIG_PD_CH7036 1
+
+#define CONFIG_LINK_PD_LVDS
+#define CONFIG_LINK_PD_SDVO
+#define CONFIG_LINK_PD_CH7036
+
+#define CONFIG_DECODE
+
+#define CONFIG_ST
+
+#include <config_default.h>
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config_default.h b/drivers/gpu/drm/emgd/emgd/cfg/config_default.h
new file mode 100644
index 0000000..18e97f5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config_default.h
@@ -0,0 +1,199 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config_default.h
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is used in conjunction with the platform's config.h to
+ * gererate a full set of build defines. This file should provide defaults
+ * for defines such that a platform's config.h can include only the
+ * minimal set of non-standard options.
+ * Defines should be named such that:
+ * CONFIG_<FOO>: Is defined or undefined suitable for use with ifdef and
+ * can be used with the build system's DIRS_FOO or OBJECTS_FOO. Any
+ * CONFIG_FOO added here must also have an entry in config_helper.c.
+ * CONFIG_ENABLE_FOO: Should be defined always and defined to a 1 or 0.
+ * This is suitble for use in if(CONFIG_ENABLE_FOO) and expected that
+ * a compiler will optimize away if(0)'s.
+ * CONFIG_LIMIT_FOO: Should prevent some default set of FOO defines
+ * from being included. For instance CONFIG_LIMIT_MODES prevents the
+ * long default list of default modes from being used and instead the
+ * platform's config.h must define the requested modes manually.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_CONFIG_DEFAULT_H
+#define _HAL_CONFIG_DEFAULT_H
+
+#include <igd_version.h>
+
+#ifndef CONFIG_MICRO
+#define CONFIG_FULL
+#endif
+
+#ifndef CONFIG_LIMIT_CORES
+#define CONFIG_PLB
+#define CONFIG_TNC
+#endif /* CONFIG_LIMIT_CORES */
+
+#ifdef CONFIG_DEPRECATED
+#if 0 /* WHT Modules need some updating */
+#define CONFIG_810
+#define CONFIG_810DC
+#define CONFIG_810E
+#define CONFIG_815
+#define CONFIG_830
+#define CONFIG_835
+#define CONFIG_845
+#define CONFIG_855
+#define CONFIG_865
+#define CONFIG_915GD
+#define CONFIG_915AL
+#define CONFIG_945G
+#define CONFIG_945GM
+#define CONFIG_945GME
+#define CONFIG_Q35
+#define CONFIG_965G
+#define CONFIG_965GM
+#define CONFIG_CTG
+#define CONFIG_Q45
+#define CONFIG_PNV
+#endif
+#endif
+
+#ifndef CONFIG_LIMIT_MODULES
+#define CONFIG_INIT
+#define CONFIG_REG
+#define CONFIG_POWER
+#define CONFIG_MODE
+#define CONFIG_DSP
+#define CONFIG_PI
+#define CONFIG_PD
+#define CONFIG_APPCONTEXT
+#define CONFIG_OVERLAY
+#endif /* CONFIG_LIMIT_MODULES */
+
+#ifndef CONFIG_LIMIT_PDS
+#define CONFIG_PD_ANALOG
+#define CONFIG_PD_LVDS
+#define CONFIG_PD_TV
+#define CONFIG_PD_HDMI
+#define CONFIG_PD_SDVO
+#define CONFIG_PD_SOFTPD
+#define CONFIG_PD_CH7036
+#endif
+
+#ifdef CONFIG_DEPRECATED
+#ifndef CONFIG_LIMIT_PDS
+#define CONFIG_PD_SII164
+#define CONFIG_PD_CH7009
+#define CONFIG_PD_TL955
+#define CONFIG_PD_RGBA
+#define CONFIG_PD_NS2501
+#define CONFIG_PD_TH164
+#define CONFIG_PD_FS454
+#define CONFIG_PD_NS387
+#define CONFIG_PD_CX873
+#define CONFIG_PD_FS460
+#define CONFIG_PD_CH7017
+#define CONFIG_PD_TI410
+#endif
+#endif
+
+#ifndef CONFIG_DEBUG_FLAGS
+#define CONFIG_DEBUG_FLAGS \
+ 0, /* Command Module */ \
+ 0, /* DSP Module */ \
+ 0, /* Mode Module */ \
+ 0, /* Init Module */ \
+ 0, /* Overlay Module */ \
+ 0, /* Power Module */ \
+ 0, /* 2D Module */ \
+ 0, /* Blend Module */ \
+ 0, /* State Module */ \
+ 0, /* GMM Module */ \
+ 0, /* Gart Module */ \
+ 0, /* OAL Module */ \
+ 0, /* Interrupt Module */ \
+ 0, /* Port Driver Module */ \
+ 0, /* Video Decode Module */ \
+ 0, /* PVR 3-Ptr Disp Drv */ \
+ 0, /* Buffer Class Module */ \
+\
+ 0, /* Global Tracing */ \
+ 0, /* Global Instructions */ \
+ 0, /* Global Debug */ \
+\
+ 0, /* Verbose Blend Stats */ \
+ 0, /* Verbose Overlay Dump */\
+ 0, /* Verbose Cmd Dump */ \
+ 0, /* Verbose GMM Dump */ \
+ 0 /* Verbose Shader Dump */
+
+#endif
+
+#ifndef CONFIG_DEBUG_IAL_FLAGS
+#define CONFIG_DEBUG_IAL_FLAGS 0
+#endif
+
+/* we ensure IAL's that do not support hw binning has this flag as '0' */
+#ifndef CONFIG_ENABLE_BINNING
+#define CONFIG_ENABLE_BINNING 0
+#endif
+
+#ifndef CONFIG_ENABLE_THREADS
+#define CONFIG_ENABLE_THREADS 0
+#endif
+
+
+
+/*
+ * These Meta-Defines should not be set in the config.h. They are enabled
+ * here based on more granular defines that come from config.h. For instance
+ * CONFIG_NAP should be enabled when any chips from the NAP family are enabled.
+ */
+#if defined(CONFIG_810) || defined(CONFIG_810DC) || defined(CONFIG_810E) ||\
+ defined(CONFIG_815)
+#define CONFIG_WHT
+#endif
+
+#if defined(CONFIG_830) || defined(CONFIG_835) || defined(CONFIG_845) ||\
+ defined(CONFIG_855) || defined(CONFIG_865)
+#define CONFIG_ALM
+#endif
+
+#if defined(CONFIG_915GD) || defined(CONFIG_915AL) || defined(CONFIG_945G) ||\
+ defined(CONFIG_945GM) || defined(CONFIG_945GME) || defined(CONFIG_Q35) ||\
+ defined(CONFIG_PNV)
+#define CONFIG_NAP
+#endif
+
+#if defined(CONFIG_965G) || defined(CONFIG_965GM) || \
+ defined(CONFIG_CTG) || defined(CONFIG_Q45)
+#define CONFIG_GN4
+#endif
+
+
+#endif /* _HAL_CONFIG_DEFAULT_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c b/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
new file mode 100644
index 0000000..d758648
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
@@ -0,0 +1,244 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config_helper.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+
+#include <config.h>
+
+int main(int argc, char **argv)
+{
+ char configs[] = ""
+#ifdef CONFIG_MICRO
+ "MICRO "
+#else
+ "FULL "
+#endif
+#ifdef CONFIG_WHT
+ "WHT "
+#endif
+#ifdef CONFIG_ALM
+ "ALM "
+#endif
+#ifdef CONFIG_NAP
+ "NAP "
+#endif
+#ifdef CONFIG_GN4
+ "GN4 "
+#endif
+#ifdef CONFIG_PLB
+ "PLB "
+#endif
+#ifdef CONFIG_TNC
+ "TNC "
+#endif
+#ifdef CONFIG_MODE
+ "MODE "
+#endif
+#ifdef CONFIG_DSP
+ "DSP "
+#endif
+#ifdef CONFIG_PI
+ "PI "
+#endif
+#ifdef CONFIG_PD
+ "PD "
+#endif
+#ifdef CONFIG_INIT
+ "INIT "
+#endif
+#ifdef CONFIG_INTERRUPT
+ "INTERRUPT "
+#endif
+#ifdef CONFIG_GART
+ "GART "
+#endif
+#ifdef CONFIG_REG
+ "REG "
+#endif
+#ifdef CONFIG_RESET
+ "RESET "
+#endif
+#ifdef CONFIG_POWER
+ "POWER "
+#endif
+#ifdef CONFIG_GMM
+ "GMM "
+#endif
+#ifdef CONFIG_MICRO_GMM
+ "MICRO_GMM "
+#endif
+#ifdef CONFIG_APPCONTEXT
+ "APPCONTEXT "
+#endif
+#ifdef CONFIG_CMD
+ "CMD "
+#endif
+#ifdef CONFIG_2D
+ "2D "
+#endif
+#ifdef CONFIG_BLEND
+ "BLEND "
+#endif
+#ifdef CONFIG_OVERLAY
+ "OVERLAY "
+#endif
+#ifdef CONFIG_DECODE
+ "DECODE "
+#endif
+ /*
+ * Port Driver Compile Options
+ */
+#ifdef CONFIG_PD_ANALOG
+ "PD_ANALOG "
+#endif
+#ifdef CONFIG_PD_SII164
+ "PD_SII164 "
+#endif
+#ifdef CONFIG_PD_CH7009
+ "PD_CH7009 "
+#endif
+#ifdef CONFIG_PD_TL955
+ "PD_TL955 "
+#endif
+#ifdef CONFIG_PD_RGBA
+ "PD_RGBA "
+#endif
+#ifdef CONFIG_PD_NS2501
+ "PD_NS2501 "
+#endif
+#ifdef CONFIG_PD_TH164
+ "PD_TH164 "
+#endif
+#ifdef CONFIG_PD_FS454
+ "PD_FS454 "
+#endif
+#ifdef CONFIG_PD_NS387
+ "PD_NS387 "
+#endif
+#ifdef CONFIG_PD_CX873
+ "PD_CX873 "
+#endif
+#ifdef CONFIG_PD_LVDS
+ "PD_LVDS "
+#endif
+#ifdef CONFIG_PD_FS460
+ "PD_FS460 "
+#endif
+#ifdef CONFIG_PD_CH7017
+ "PD_CH7017 "
+#endif
+#ifdef CONFIG_PD_TI410
+ "PD_TI410 "
+#endif
+#ifdef CONFIG_PD_TV
+ "PD_TV "
+#endif
+#ifdef CONFIG_PD_HDMI
+ "PD_HDMI "
+#endif
+#ifdef CONFIG_PD_SDVO
+ "PD_SDVO "
+#endif
+#ifdef CONFIG_PD_SOFTPD
+ "PD_SOFTPD "
+#endif
+#ifdef CONFIG_PD_CH7036
+ "PD_CH7036 "
+#endif
+ /*
+ * Port Driver Link Options
+ */
+#ifdef CONFIG_LINK_PD_ANALOG
+ "LINK_PD_ANALOG "
+#endif
+#ifdef CONFIG_LINK_PD_SII164
+ "LINK_PD_SII164 "
+#endif
+#ifdef CONFIG_LINK_PD_CH7009
+ "LINK_PD_CH7009 "
+#endif
+#ifdef CONFIG_LINK_PD_TL955
+ "LINK_PD_TL955 "
+#endif
+#ifdef CONFIG_LINK_PD_RGBA
+ "LINK_PD_RGBA "
+#endif
+#ifdef CONFIG_LINK_PD_NS2501
+ "LINK_PD_NS2501 "
+#endif
+#ifdef CONFIG_LINK_PD_TH164
+ "LINK_PD_TH164 "
+#endif
+#ifdef CONFIG_LINK_PD_FS454
+ "LINK_PD_FS454 "
+#endif
+#ifdef CONFIG_LINK_PD_NS387
+ "LINK_PD_NS387 "
+#endif
+#ifdef CONFIG_LINK_PD_CX873
+ "LINK_PD_CX873 "
+#endif
+#ifdef CONFIG_LINK_PD_LVDS
+ "LINK_PD_LVDS "
+#endif
+#ifdef CONFIG_LINK_PD_FS460
+ "LINK_PD_FS460 "
+#endif
+#ifdef CONFIG_LINK_PD_CH7017
+ "LINK_PD_CH7017 "
+#endif
+#ifdef CONFIG_LINK_PD_TI410
+ "LINK_PD_TI410 "
+#endif
+#ifdef CONFIG_LINK_PD_TV
+ "LINK_PD_TV "
+#endif
+#ifdef CONFIG_LINK_PD_HDMI
+ "LINK_PD_HDMI "
+#endif
+#ifdef CONFIG_LINK_PD_SDVO
+ "LINK_PD_SDVO "
+#endif
+#ifdef CONFIG_LINK_PD_SOFTPD
+ "LINK_PD_SOFTPD "
+#endif
+#ifdef CONFIG_LINK_PD_CH7036
+ "LINK_PD_CH7036 "
+#endif
+
+#ifdef CONFIG_COPP
+ "COPP "
+#endif
+ ;
+ printf("%s\n", configs);
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
new file mode 100644
index 0000000..52bc62e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
@@ -0,0 +1,34 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_global.c
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#include <config.h>
+#include <igd_debug.h>
+
+/* Global debug flag has been moved to egd_drm/emgd/drm/emgd_drv.c */
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
new file mode 100644
index 0000000..335a796
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
@@ -0,0 +1,918 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_init.c
+ * $Revision: 1.24 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the implementation of the core init module. It
+ * is responsible from initializing the HAL and the device and gathering
+ * all necessary general device information. This module is partially
+ * optional such that portions may be disabled to save code space.
+ * When CONFIG_MICRO is enabled:
+ * Firmware parameters are NOT read.
+ * Only the first device instance is queried and configured.
+ * Revision ID is NOT queried, it is assumed to be 0.
+ * MMIO regions are not discovered or mapped.
+ * FB memory is not discovered or mapped.
+ * Shutdown is a no-op.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memory.h>
+#include <memmap.h>
+
+#include <igd_init.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+#include <igd_mode.h>
+#include <igd_debug.h>
+
+#include <context.h>
+#include <cmd.h>
+#include <reset.h>
+#include <dsp.h>
+#include <utils.h>
+#include <general.h>
+#include <intelpci.h>
+#include <mode_access.h>
+#include <module_init.h>
+#include <mode.h>
+
+#include "init_dispatch.h"
+
+/* OAL header */
+#include <sched.h>
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+
+unsigned long _sgx_base, _msvdx_base, _topaz_base;
+
+/* Notes: If the bus is of value 0xFFFF, then the particular
+ * device is searched for in the whole PCI topology
+ */
+typedef struct _iegd_pci {
+ unsigned short vendor_id;
+ unsigned short device_id;
+ unsigned short bus;
+ unsigned short dev;
+ unsigned short func;
+} iegd_pci_t;
+
+static iegd_pci_t intel_pci_device_table[] = {
+#ifdef CONFIG_810
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810, 0, 2, 0},
+#endif
+#ifdef CONFIG_810DC
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810DC, 0, 2, 0},
+#endif
+#ifdef CONFIG_810E
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810E, 0, 2, 0},
+#endif
+#ifdef CONFIG_815
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_815, 0, 2, 0},
+#endif
+#ifdef CONFIG_855
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_855, 0, 2, 0},
+#endif
+#ifdef CONFIG_830
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_830M, 0, 2, 0},
+#endif
+#ifdef CONFIG_835
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_835, 0, 2, 0},
+#endif
+#ifdef CONFIG_845
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_845G, 0, 2, 0},
+#endif
+#ifdef CONFIG_865
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_865G, 0, 2, 0},
+#endif
+#ifdef CONFIG_915GD
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_915GD, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_910GL, 0, 2, 0},
+#endif
+#ifdef CONFIG_915AL
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_915AL, 0, 2, 0},
+#endif
+#ifdef CONFIG_945G
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945G, 0, 2, 0},
+#endif
+#ifdef CONFIG_945GM
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945GM, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945GME, 0, 2, 0},
+#endif
+#ifdef CONFIG_Q35
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q35, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q35A2, 0, 2, 0},
+#endif
+#ifdef CONFIG_965G
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_965G, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G965, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q965, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_946GZ, 0, 2, 0},
+#endif
+#ifdef CONFIG_965GM
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_GME965, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_GM965, 0, 2, 0},
+#endif
+#ifdef CONFIG_CTG
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_CTG, 0, 2, 0},
+#endif
+#ifdef CONFIG_PLB
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_PLB, 0, 2, 0},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_TNC, 0, 2, 0},
+#ifdef CONFIG_MSRT
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_TNC_A0, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_LNC, 0, 2, 0},
+#endif
+#endif
+#ifdef CONFIG_Q45
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_ELK, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q45, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G45, 0, 2, 0},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G41, 0, 2, 0},
+#endif
+
+};
+
+
+/*
+ * On platforms with multiple PCI devices (currently only Atom E6xx), we
+ * need to disable legacy VGA decoding on the second device, otherwise
+ * the VGA arbiter will prevent DRI from being used. Keep a list of
+ * devices we need to disable this on.
+ */
+static iegd_pci_t disabled_legacy_vga_list[] = {
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDVO_TNC, 0, 0, 0},
+};
+
+#define MAX_PCI_DEVICE_SUPPORTED \
+ (sizeof(intel_pci_device_table)/sizeof(intel_pci_device_table[0]))
+#define MAX_LEGACY_VGA_DISABLE \
+ (sizeof(disabled_legacy_vga_list)/sizeof(disabled_legacy_vga_list[0]))
+
+
+static dispatch_table_t init_dispatch_table[] = {
+
+ DISPATCH_PLB(&init_dispatch_plb)
+ DISPATCH_TNC(&init_dispatch_tnc)
+#ifdef CONFIG_MSRT
+ DISPATCH_TNC_A0(&init_dispatch_tnc_a0)
+ DISPATCH_LNC(&init_dispatch_lnc)
+#endif
+ DISPATCH_END
+};
+
+
+
+static init_dispatch_t *init_dispatch;
+
+
+/*---------------------------------------------------------------------------
+ * Optional Init Module Components
+ *--------------------------------------------------------------------------*/
+#ifndef CONFIG_MICRO
+
+/*!
+ * This function allows for calling the igd_get_param function with a
+ * display handle instead of a driver handle. This version is exported in
+ * the dispatch table.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return igd_get_param()
+ */
+static int _igd_get_param(igd_display_h display_handle,
+ unsigned long id,
+ unsigned long *value)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ return igd_get_param((igd_driver_h)display->context, id, value);
+}
+
+/*!
+ * This function allows for calling the igd_set_param function with a
+ * display handle instead of a driver handle. This version is exported in
+ * the dispatch table.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return igd_set_param()
+ */
+static int _igd_set_param(igd_display_h display_handle,
+ unsigned long id,
+ unsigned long value)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ return igd_set_param((igd_driver_h)display->context, id, value);
+}
+
+/*!
+ * This function should never be called directly. It comprises the optional
+ * portion of the igd_set_param function which should be used instead.
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return set_param()
+ * @return 0
+ */
+static int _init_set_param(igd_context_t *context,
+ unsigned long id,
+ unsigned long value)
+{
+
+ switch(id) {
+ case IGD_PARAM_DEBUG_MASK:
+ *((unsigned long *)emgd_debug) = value;
+ break;
+ default:
+ return init_dispatch->set_param(context, id, value);
+ }
+
+ return 0;
+}
+
+/*!
+ * This function should never be called directly. It comprises the optional
+ * portion of the igd_get_param function which should be used instead.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return set_param()
+ * @return 0
+ */
+static int _init_get_param(igd_display_h display_handle,
+ unsigned long id,
+ unsigned long *value)
+{
+ switch(id) {
+ case IGD_PARAM_DEBUG_MASK:
+ *value = *((unsigned long *)emgd_debug);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*!
+ * Hook up the dispatch pointers. These are only available when the
+ * full init module is compiled in.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void _init_dispatch(igd_context_t *context)
+{
+ /* Hook up top level dispatch table functions owner by init */
+ context->dispatch.get_param = _igd_get_param;
+ context->dispatch.set_param = _igd_set_param;
+ return;
+}
+
+/*!
+ * Shutdown all modules in the required order. Optional modules must
+ * only be called if they exist.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void shutdown_modules(igd_context_t *context)
+{
+ EMGD_TRACE_ENTER;
+
+ if(context->mod_dispatch.shutdown_2d) {
+ context->mod_dispatch.shutdown_2d(context);
+ }
+ if(context->mod_dispatch.blend_shutdown) {
+ context->mod_dispatch.blend_shutdown(context);
+ }
+ if(context->mod_dispatch.interrupt_shutdown) {
+ context->mod_dispatch.interrupt_shutdown(context);
+ }
+ if(context->mod_dispatch.appcontext_shutdown) {
+ context->mod_dispatch.appcontext_shutdown(context);
+ }
+ if(context->mod_dispatch.reset_shutdown) {
+ context->mod_dispatch.reset_shutdown(context);
+ }
+ if(context->mod_dispatch.mode_shutdown) {
+ context->mod_dispatch.mode_shutdown(context);
+ }
+ if(context->mod_dispatch.pwr_shutdown) {
+ context->mod_dispatch.pwr_shutdown(context);
+ }
+ if(context->mod_dispatch.overlay_shutdown) {
+ context->mod_dispatch.overlay_shutdown(context);
+ }
+ if(context->mod_dispatch.cmd_shutdown) {
+ context->mod_dispatch.cmd_shutdown(context);
+ }
+ /*
+ * GMM is not optional shutdown must exist.
+ */
+ gmm_shutdown(context);
+
+ /*
+ * Reg module must be last to restore the state of the device to the
+ * way it was before the driver started.
+ */
+ EMGD_DEBUG("post reg_shutdown: %p", context->mod_dispatch.reg_shutdown);
+ if(context->mod_dispatch.reg_shutdown) {
+ context->mod_dispatch.reg_shutdown(context);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+#endif
+
+/*!
+ * Empty idle function. This insures that anyone can call
+ * dispatch->idle() in any configuration. If there is a command
+ * module this will get replaced with a real idle function.
+ *
+ * @param driver_handle
+ *
+ * @return 0
+ */
+static int empty_idle(igd_driver_h driver_handle)
+{
+ return 0;
+}
+
+/*!
+ * Empty sync function. This insures that anyone can call
+ * dispatch->sync() in any configuration.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ * from a successful call to dispatch->alter_displays().
+ *
+ * @param priority The command queue to use. IGD_PRIORITY_NORMAL is
+ * correct for most circumstances.
+ *
+ * @param sync The sync identifier that will be populated and returned
+ * during the call. To insert a new sync, this should be passed
+ * containing 0 (A pointer to a zero). To check the status of an
+ * existing sync pass the value returned from a previous call to
+ * this function.
+ *
+ * @param flags Sync flags.
+ *
+ * @returns
+ * 0: On Success
+ * -IGD_ERROR_BUSY: When the sync is not yet complete
+ */
+static int empty_sync(igd_display_h display_handle, int priority,
+ unsigned long *sync, unsigned long flags)
+{
+ return 0;
+}
+
+/*!
+ * Non-Optional Init Module Components
+ *
+ * @param found_device
+ * @param pdev
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_NODEV on failure
+ */
+static int detect_device(iegd_pci_t **found_device,
+ os_pci_dev_t *pdev)
+{
+ int i;
+
+ /* Scan the PCI bus for supported device */
+ for(i = 0; i < MAX_PCI_DEVICE_SUPPORTED; i++) {
+
+ *pdev = OS_PCI_FIND_DEVICE(intel_pci_device_table[i].vendor_id,
+ intel_pci_device_table[i].device_id,
+ intel_pci_device_table[i].bus,
+ intel_pci_device_table[i].dev,
+ intel_pci_device_table[i].func,
+ (os_pci_dev_t)0);
+
+ if(*pdev) {
+ *found_device = &intel_pci_device_table[i];
+ break;
+ }
+ }
+ if(!*pdev) {
+ EMGD_ERROR("No supported VGA devices found.");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("VGA device found: 0x%x", (*found_device)->device_id);
+
+ return 0;
+}
+
+/* This is currently a global context, because the context is needed
+ * in io.c for vbios in OS_READx and OS_WRITEx functions. */
+igd_context_t *fixme_vbios_context;
+
+/* By declaring io_mapped and io_base as globals, we no longer need to
+ * include context.h in the vbios common io.c */
+
+/* Device 0:2:0 io_base */
+unsigned char io_mapped; /* True for io mapped MMIO space */
+unsigned short io_base;
+
+/* Device 0:2:0 [VGA device] io_base */
+unsigned char io_mapped_lvds; /* True for io mapped MMIO space */
+unsigned short io_base_lvds;
+
+/* Device 0:3:0 [SDVO device] io_base */
+unsigned char io_mapped_sdvo; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo;
+
+/* Device 0:31:0 [LPC device] io_base */
+unsigned char io_mapped_lpc; /* True for io mapped MMIO space */
+unsigned short io_base_lpc;
+
+/* Device 6:0:1 [STMicro SDVO device] io_base */
+unsigned char io_mapped_sdvo_st; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo_st;
+unsigned char io_mapped_sdvo_st_gpio; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo_st_gpio;
+
+
+/*!
+ * This function is directly exported.
+ *
+ * @param found_device
+ * @param pdev
+ *
+ * @return igd_driver_h
+ * @return NULL on failure
+ */
+igd_driver_h igd_driver_init( igd_init_info_t *init_info )
+{
+ igd_context_t *context;
+ os_pci_dev_t pdev = (os_pci_dev_t)NULL;
+ os_pci_dev_t vga_disable_dev;
+ iegd_pci_t *found_device;
+ int ret;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* Allocate a context */
+ context = (void *) OS_ALLOC(sizeof(igd_context_t));
+ fixme_vbios_context = context;
+ if(!context) {
+ EMGD_ERROR_EXIT("igd_driver_init failed to create context");
+ return NULL;
+ }
+ OS_MEMSET(context, 0, sizeof(igd_context_t));
+
+ /* Search VGA devices for a supported one */
+ ret = detect_device(&found_device, &pdev);
+ if(ret) {
+ OS_FREE(context);
+ return NULL;
+ }
+
+ /*
+ * Some platforms (currently only Atom E6xx) use two PCI devices (the
+ * second device being for SDVO) and this causes the VGA arbiter to get
+ * involved. Legacy VGA decoding must be disabled for all PCI devices
+ * except one, otherwise the VGA arbiter will prevent DRI usage in the
+ * X server.
+ */
+ for (i = 0; i < MAX_LEGACY_VGA_DISABLE; i++) {
+ vga_disable_dev = os_pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_SDVO_TNC, 0xFFFF, 0, 0, NULL);
+ if (vga_disable_dev) {
+ printk(KERN_INFO "VGA arbiter detected; disabling legacy VGA"
+ " decoding on SDVO device\n");
+ os_pci_disable_legacy_vga_decoding(vga_disable_dev);
+ os_pci_free_device(vga_disable_dev);
+ }
+ }
+
+ context->device_context.did = found_device->device_id;
+ init_dispatch = (init_dispatch_t *)dispatch_acquire(context,
+ init_dispatch_table);
+
+ if(!init_dispatch) {
+ EMGD_ERROR_EXIT("No dispatch found for listed device");
+ return NULL;
+ }
+
+ ret = init_dispatch->query(context, init_dispatch, pdev, &init_info->bus,
+ &init_info->slot, &init_info->func);
+ if(ret) {
+ OS_FREE(context);
+ EMGD_ERROR_EXIT("Device Dependent Query Failed");
+ return NULL;
+ }
+
+ /* init info */
+ init_info->vendor_id = found_device->vendor_id;
+ init_info->device_id = found_device->device_id;
+ init_info->name = init_dispatch->name;
+ init_info->chipset = init_dispatch->chipset;
+ init_info->default_pd_list = init_dispatch->default_pd_list;
+
+ EMGD_TRACE_EXIT;
+
+ return (igd_driver_h)context;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int igd_driver_config(igd_driver_h driver_handle)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(context, "Null context!", -IGD_ERROR_INVAL);
+
+ ret = init_dispatch->config(context, init_dispatch);
+ if(ret) {
+ EMGD_ERROR_EXIT("Device Dependent Config Failed");
+ return ret;
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Initialize modules in the required order. Optional modules must be called
+ * with their initalization macro to ensure that they are not called when
+ * their option is not enabled.
+ *
+ * @param params
+ * @param context
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+/* FIXME: All modules should get params from mod_dispatch */
+static int init_modules(igd_param_t *params, igd_context_t *context)
+{
+ unsigned int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Reg module must be first so that the state of the device can be
+ * saved before anything else is touched.
+ */
+ ret = REG_INIT(context, (params->preserve_regs)?IGD_DRIVER_SAVE_RESTORE:0);
+ if (ret) {
+ EMGD_DEBUG("Error initializing register module");
+ }
+
+ /*
+ * GMM is not optional. Its init function must exist.
+ */
+ ret = gmm_init(context, params->page_request, params->max_fb_size);
+ if(ret) {
+ EMGD_ERROR_EXIT("GMM Module Init Failed");
+ return ret;
+ }
+
+ ret = CMD_INIT(context);
+ if(ret) {
+ EMGD_ERROR_EXIT("Command Module Init Failed");
+ return ret;
+ }
+
+ /*
+ * Mode is not optional. Its init function must exist.
+ */
+ ret = mode_init(context);
+ if (ret) {
+ EMGD_ERROR_EXIT("Mode Module Init Failed");
+ return ret;
+ }
+
+ ret = APPCONTEXT_INIT(context);
+ if (ret) {
+ EMGD_ERROR_EXIT("Appcontext Module Init Failed");
+ return ret;
+ }
+
+ ret = OVERLAY_INIT(context, params);
+ if(ret) {
+ EMGD_ERROR_EXIT("Overlay Module Init Failed");
+ return ret;
+ }
+
+ ret = PWR_INIT(context);
+ if(ret) {
+ EMGD_DEBUG("Error initializing power module");
+ }
+
+ ret = RESET_INIT(context);
+ if(ret) {
+ EMGD_DEBUG("Error initializing reset module");
+ }
+
+ ret = OS_INIT_INTERRUPT(context->device_context.did,
+ context->device_context.virt_mmadr);
+ if(ret) {
+ EMGD_ERROR_EXIT("Interrupt Module Init Failed");
+ return ret;
+ }
+
+ ret = BLEND_INIT(context);
+ if(ret) {
+ EMGD_DEBUG("Error initializing blend module");
+ }
+
+ ret = INIT_2D(context);
+ if(ret) {
+ EMGD_DEBUG("Error initializing 2d module");
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ * @param dsp
+ * @param params
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int igd_module_init(igd_driver_h driver_handle,
+ igd_dispatch_t **dsp,
+ igd_param_t *params)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ device_context_t *device;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ device = &context->device_context;
+ context->device_context.power_state = IGD_POWERSTATE_D0;
+ context->mod_dispatch.init_params = params;
+ context->dispatch.idle = empty_idle;
+ context->dispatch.sync = empty_sync;
+ context->mod_dispatch.in_dih_clone_mode = 0;
+ context->mod_dispatch.dih_clone_display = 0;
+ context->mod_dispatch.fb_blend_ovl_override = 0;
+
+ /* Intialize IGD Modules */
+ ret = init_modules(params, context);
+ if (ret) {
+ EMGD_ERROR_EXIT("Init Modules Failed");
+ return ret;
+ }
+
+ OPT_MICRO_VOID_CALL(_init_dispatch(context));
+
+ *dsp = &context->dispatch;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ * @param info
+ *
+ * @return 0
+ */
+int igd_get_config_info(igd_driver_h driver_handle,
+ igd_config_info_t *config_info)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(context, "Null context!", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(config_info, "Null config_info!", -IGD_ERROR_INVAL);
+
+ OS_MEMSET(config_info, 0, sizeof(igd_config_info_t));
+
+ /* Config information already obtained from driver_config() */
+ config_info->mmio_base_phys = context->device_context.mmadr;
+ config_info->mmio_base_virt = context->device_context.virt_mmadr;
+ config_info->gtt_memory_base_phys = context->device_context.fb_adr;
+ /* config_info->gtt_memory_base_virt = context->device_context.virt_fb_adr; */
+ config_info->gtt_memory_size = context->device_context.mem_size;
+ config_info->revision_id = context->device_context.rid;
+ config_info->hw_status_offset = context->device_context.hw_status_offset;
+ config_info->stolen_memory_base_virt = 0; /* FIXME: remove this */
+
+ /* get the portions held in the dsp module */
+ if(context->mod_dispatch.dsp_get_config_info) {
+ context->mod_dispatch.dsp_get_config_info(context, config_info);
+ }
+ /* get the portions held in the pi module */
+ if(context->mod_dispatch.pi_get_config_info) {
+ context->mod_dispatch.pi_get_config_info(context, config_info);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is directly exported. When compiled without the init
+ * module the function calls the DD layer get_param function. When the
+ * full init module is included this function calls _init_get_param to
+ * first get the DI parameters then calls the DD layer.
+ *
+ * @param driver_handle
+ * @param id
+ * @param value
+ *
+ * @return get_param()
+ */
+int igd_get_param(igd_driver_h driver_handle,
+ unsigned long id,
+ unsigned long *value)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_ASSERT(context, "Null Driver Handle", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(value, "Null Value", -IGD_ERROR_INVAL);
+
+ OPT_MICRO_CALL(_init_get_param(driver_handle, id, value));
+
+ return init_dispatch->get_param(context, id, value);
+}
+
+/*!
+ * This function is directly exported. When compiled without the init
+ * module the function does nothing and returns 0. When the full init
+ * module is included this function calls _init_set_param and returns
+ * the result.
+ *
+ * @param driver_handle
+ * @param id
+ * @param value
+ *
+ * @return 0
+ */
+int igd_set_param(igd_driver_h driver_handle,
+ unsigned long id,
+ unsigned long value)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_ASSERT(context, "Null Driver Handle", -IGD_ERROR_INVAL);
+
+ OPT_MICRO_CALL(_init_set_param(context, id, value));
+ return 0;
+}
+
+/*!
+ * This function is exported directly. It will shutdown an instance
+ * of the HAL that was initialized with igd_driver_init.
+ *
+ * Since the symbol is exported as part of the documented API it must
+ * always exist, however it becomes an empty function when the init
+ * module is not fully included.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_driver_shutdown(igd_driver_h driver_handle)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(context, "Null Driver Handle", );
+
+
+ /* Shutdown the device context */
+ init_dispatch->shutdown(context);
+
+ /* release the driver's context */
+ if(context) {
+ EMGD_DEBUG("Freeing context");
+ OS_FREE(context);
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ * This function is exported. It will shutdown most of the display
+ * functions.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_driver_shutdown_hal(igd_driver_h driver_handle)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(context, "Null Driver Handle", );
+
+ if(context->device_context.power_state != IGD_POWERSTATE_D0) {
+ return;
+ }
+
+ /* Shutdown Modules */
+ shutdown_modules(context);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+/*!
+ * This function is exported directly. It will shutdown an instance
+ * of the HAL that was initialized with igd_driver_init.
+ *
+ * Since the symbol is exported as part of the documented API it must
+ * always exist, however it becomes an empty function when the init
+ * module is not fully included.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_query_2d_caps_hwhint(igd_driver_h driver_handle,
+ unsigned long caps_val,
+ unsigned long *status)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+
+ EMGD_TRACE_ENTER;
+
+ if (init_dispatch->query_2d_caps_hwint != NULL){
+ init_dispatch->
+ query_2d_caps_hwint(context, caps_val, status);
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+/*----------------------------------------------------------------------------
+ * File Revision History
+ * $Id: igd_init.c,v 1.24 2011/09/30 07:53:25 rlim Exp $
+ * $Source: /nfs/fm/proj/eia/cvsroot/koheo/linux/egd_drm/emgd/core/init/cmn/igd_init.c,v $
+ *----------------------------------------------------------------------------
+ */
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h b/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
new file mode 100644
index 0000000..7c58997
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _INIT_DISPATCH_H
+#define _INIT_DISPATCH_H
+
+#include <pci.h>
+
+#include <dispatch.h>
+
+/*
+ * Note: Platforms extend this data structure so the pointer can be used
+ * as either this DI dispatch or cast to the DD dipatch.
+ */
+typedef struct _init_dispatch {
+ char *name;
+ char *chipset;
+ char *default_pd_list;
+ int (*query)(igd_context_t *context, struct _init_dispatch *dispatch,
+ os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
+ unsigned int *func);
+ int (*config)(igd_context_t *context, struct _init_dispatch *dispatch);
+ int (*set_param)(igd_context_t *context, unsigned long id,
+ unsigned long value);
+ int (*get_param)(igd_context_t *context, unsigned long id,
+ unsigned long *value);
+ void (*shutdown)(igd_context_t *context);
+ int (*query_2d_caps_hwint) (igd_context_t *context,
+ unsigned long caps_val, unsigned long *status);
+} init_dispatch_t;
+
+extern init_dispatch_t init_dispatch_plb;
+extern init_dispatch_t init_dispatch_tnc;
+extern init_dispatch_t init_dispatch_tnc_a0;
+extern init_dispatch_t init_dispatch_lnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c b/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
new file mode 100644
index 0000000..d6a92ac
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
@@ -0,0 +1,458 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_plb.c
+ * $Revision: 1.19 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <gart.h>
+
+#include <memory.h>
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_gart.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/init_dispatch.h"
+#include "/usr/include/linux/pci_regs.h"
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+static int bus_master_enable_plb(platform_context_plb_t *platform_context);
+static int full_config_vga_plb(igd_context_t *context,
+ init_dispatch_t *dispatch);
+static int get_stolen_mem_plb(igd_context_t *context, unsigned long *pages);
+
+int full_get_param_plb(igd_context_t *context,
+ unsigned long id,
+ unsigned long *value);
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+int get_revision_id_plb(igd_context_t *context,
+ os_pci_dev_t vga_dev)
+{
+ EMGD_TRACE_ENTER;
+
+ /* Read RID */
+ if(OS_PCI_READ_CONFIG_8(vga_dev, PCI_RID,
+ (unsigned char *)&context->device_context.rid)) {
+ EMGD_ERROR_EXIT("Error occured reading RID");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG(" rid = 0x%lx", context->device_context.rid);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return 1 on failure
+ * @return 0 on success
+ */
+int full_config_plb(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ unsigned long /* FIXME - reserved_mem, */ graphics_frequency ;
+ platform_context_plb_t *platform_context;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ platform_context = (platform_context_plb_t *)context->platform_context;
+
+ _sgx_base = 0x40000;
+ _msvdx_base = 0x50000;
+
+ /*
+ * Enable bus mastering for platforms whose BIOS did not perform this
+ * task for us.
+ */
+ ret = bus_master_enable_plb(platform_context);
+ if(ret) {
+ EMGD_ERROR("Error: Enabling bus master");
+ }
+
+ /* Config VGA */
+ ret = full_config_vga_plb(context, dispatch);
+ if(ret) {
+ EMGD_ERROR_EXIT("Config VGA Failed");
+ return ret;
+ }
+
+ get_stolen_mem_plb(context, &context->device_context.reserved_mem);
+
+#if 0 /* FIXME - WHY IS THIS RETURNING 0 AND SETTING reserved_mem TO 0 ALSO? */
+ /* Get mem reservation param if it exists */
+ if(!full_get_param_plb(context, IGD_PARAM_MEM_RESERVATION,
+ &reserved_mem)) {
+ context->device_context.reserved_mem = reserved_mem;
+ }
+#endif
+
+ /* Get graphics frequency param if it exists */
+ if(!full_get_param_plb(context, IGD_PARAM_GFX_FREQ,
+ &graphics_frequency)) {
+ context->device_context.gfx_freq = (unsigned short)graphics_frequency;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param platform_context
+ *
+ * @return -1 on failure
+ * @return 0 on success
+ */
+static int bus_master_enable_plb(platform_context_plb_t *platform_context){
+ int ret;
+ unsigned char tmp;
+
+ EMGD_TRACE_ENTER;
+
+ ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, &tmp);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI read of bus master");
+ return -1;
+ }
+
+ /*
+ * Get Bit 2, 1, and 0 and see if it is == 1
+ * all 3 bits has to be enabled. This is to enable register read/write
+ * in the case of a PCI card being added
+ */
+ if((tmp & 0x7) != 0x7 ) {
+
+ tmp |= 0x7;
+ ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, tmp);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI write of bus master");
+ return -1;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int full_config_vga_plb(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ platform_context_plb_t *platform_context =
+ (platform_context_plb_t *)context->platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+ PLB_PCI_MMADR, (void*)&context->device_context.mmadr)) {
+ EMGD_ERROR_EXIT("Reading MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ context->device_context.mmadr &= 0xfffffff9;
+ context->device_context.virt_mmadr =
+ OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr, PLB_MMIO_SIZE);
+
+ if (!context->device_context.virt_mmadr) {
+ EMGD_ERROR_EXIT("Failed to map MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("mmadr mapped %dKB @ (phys):0x%lx (virt):%p",
+ PLB_MMIO_SIZE/1024,
+ context->device_context.mmadr,
+ context->device_context.virt_mmadr);
+
+ /* PCI Interrupt Line */
+ if(OS_PCI_READ_CONFIG_8(platform_context->pcidev0,
+ PCI_INTERRUPT_LINE, (void*)&platform_context->irq)) {
+ platform_context->irq = 0;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Get the # of pages used for video memory. This does not use information from
+ * the scratch register, since this is done later if it exists.
+ *
+ * @param context
+ * @param pages
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_stolen_mem_plb(igd_context_t *context, unsigned long *pages)
+{
+ platform_context_plb_t *platform_context;
+ os_pci_dev_t vga_dev;
+ unsigned short gmch_ctl;
+ unsigned long stolen_mem; /* in bytes */
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ platform_context = (platform_context_plb_t *)context->platform_context;
+ vga_dev = platform_context->pcidev0;
+
+ ret = OS_PCI_READ_CONFIG_16(vga_dev, PLB_PCI_GC, &gmch_ctl);
+ if (ret) {
+ EMGD_ERROR_EXIT("Unable to read PLB_PCI_GC");
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch (gmch_ctl & 0x70) {
+ case 0x00:
+ stolen_mem = 0;
+ break;
+ case 0x10:
+ /* 1M */
+ stolen_mem = 1*1024*1024;
+ break;
+ case 0x20:
+ /* 4M */
+ stolen_mem = 4*1024*1024;
+ break;
+ case 0x30:
+ /* 8M */
+ stolen_mem = 8*1024*1024;
+ break;
+ case 0x40:
+ /* 16M */
+ stolen_mem = 16*1024*1024;
+ break;
+ case 0x50:
+ /* 32M */
+ stolen_mem = 32*1024*1024;
+ break;
+ case 0x60:
+ /* 48M */
+ stolen_mem = 48*1024*1024;
+ case 0x70:
+ /* 64M */
+ stolen_mem = 64*1024*1024;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Unknown Stolen Memory Size");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (stolen_mem) {
+ /*
+ * Subtract off the size of the GTT which is
+ * (number of entries in DWORDS) * 4 to get it into bytes
+ */
+ stolen_mem -= context->device_context.gatt_pages*4;
+ /* Subtract off 1 page for the scratch page */
+ stolen_mem -= 4*1024;
+ }
+
+ /* Convert to the # of pages available for stolen memory */
+ *pages = stolen_mem / 4096;
+
+ EMGD_DEBUG("Stolen memory: 0x%lx pages", *pages);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int full_get_param_plb(igd_context_t *context,
+ unsigned long id,
+ unsigned long *value)
+{
+ int ret = 0;
+ unsigned char *mmio;
+ unsigned long control_reg;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("ID: 0x%lx", id);
+
+ /* Scratch registers used as below:
+ *
+ * 0x71410:
+ * --------
+ * Bits 31-16 - EID Firmware identifier 0xE1DF
+ * Bits 15-00 - Tell what data is present.
+ * Here are bits for what we are using know:
+ * Bit 0 - Panel id
+ * Bit 1 - List of ports for which displays are attached
+ * Bit 2 - Memory reservation
+ * If any of the above bits is set that mean data is followed
+ * in the next registers.
+ *
+ * 0x71414:
+ * --------
+ * Bits 07-00 - Panel Id
+ * Bits 11-08 - Port list
+ * Information for Port list: If any of the bit is set means,
+ * a display is attached to that port as follows:
+ * Bit 08 - CRT
+ * Bit 09 - DVOA/Internal LVDS
+ * Bit 10 - DVOB/RGBA
+ * Bit 11 - DVOC
+ *
+ * 0x71418:
+ * --------
+ * Bits 15-00 - Reserved Memory value in number of 4k size pages
+ */
+ mmio = context->device_context.virt_mmadr;
+ control_reg = EMGD_READ32(EMGD_MMIO(mmio) + 0x71410);
+ *value = 0;
+
+ switch(id) {
+ case IGD_PARAM_PANEL_ID:
+ /*
+ * Check for Embedded firmware
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * The panel id bit must be set in the control register
+ * to indicate valid panel (config) ID value.
+ */
+ if (control_reg & 0x1) {
+ *value = EMGD_READ32(EMGD_MMIO(mmio) + 0x71414) & 0xFF;
+ if(!(*value)) {
+ /* we cannot allow for config id = 0 */
+ ret = -IGD_ERROR_INVAL;
+ }
+ } else {
+ EMGD_DEBUG("Panel ID read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ case IGD_PARAM_MEM_RESERVATION:
+ /*
+ * Check for Embedded firmware
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * The mem reservation bit must be set in the control register
+ * to indicate valid mem reservation value.
+ */
+ if (control_reg & 0x4) {
+ *value = (EMGD_READ32(EMGD_MMIO(mmio) + 0x71418) & 0xFFFF);
+ } else {
+ EMGD_DEBUG("Mem Reservation read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ default:
+ ret = -IGD_ERROR_INVAL;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void full_shutdown_plb(igd_context_t *context)
+{
+ platform_context_plb_t *platform_context =
+ (platform_context_plb_t *)context->platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ /* unmap registers */
+ if(context->device_context.virt_mmadr) {
+ EMGD_DEBUG("Unmapping Gfx registers and GTT Table...");
+ OS_UNMAP_IO_FROM_MEM((void *) context->device_context.virt_mmadr,
+ PLB_MMIO_SIZE);
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gttadr,
+ context->device_context.gatt_pages * 4);
+ } else {
+ printk(KERN_ERR "Unmapping MMIO space failed.\n");
+ }
+
+ if (platform_context) {
+ OS_PCI_FREE_DEVICE(platform_context->pcidev0);
+ }
+ EMGD_TRACE_EXIT;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c b/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
new file mode 100644
index 0000000..c91adb6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
@@ -0,0 +1,631 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_init_plb.c
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memory.h>
+#include <asm/cacheflush.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "user_config.h"
+#include "../cmn/init_dispatch.h"
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+#define PFX "EMGD: "
+
+#define SCR1 0x71410 /* scratch register set by vbios indicating status*/
+#define SCR2 0x71418 /* scratch register set by vbios indicating amount of stolen memory */
+#define FW_ID 0xE1DF0000 /* firmware identifier */
+#define ST_BIT 0x00000004 /* bit2- stolen memory bit */
+#define PSB_GMCH_CTRL 0x52
+#define PSB_GMCH_ENABLED 0x04
+#define PSB_PGETBL_CTL 0x00002020
+#define PSB_PGETBL_ENABLED 0x00000001
+#define PSB_GATT_RESOURCE 2
+#define PSB_GTT_RESOURCE 3
+#define PSB_BSM 0x5c
+#define PSB_PTE_VALID 0x0001
+
+
+#ifdef CONFIG_PLB
+
+extern unsigned char io_mapped;
+extern unsigned short io_base;
+extern emgd_drm_config_t config_drm;
+
+extern int full_config_plb(igd_context_t *context,
+ init_dispatch_t *dispatch);
+extern int get_revision_id_plb(igd_context_t *context, os_pci_dev_t vga_dev);
+extern int full_get_param_plb(igd_context_t *context, unsigned long id,
+ unsigned long *value);
+extern void full_shutdown_plb(igd_context_t *context);
+
+static int query_plb(igd_context_t *context,init_dispatch_t *dispatch,
+ os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
+ unsigned int *func);
+static int config_plb(igd_context_t *context,
+ init_dispatch_t *dispatch);
+static int set_param_plb(igd_context_t *context, unsigned long id,
+ unsigned long value);
+static int get_param_plb(igd_context_t *context, unsigned long id,
+ unsigned long *value);
+static void shutdown_plb(igd_context_t *context);
+
+static void gtt_shutdown_plb(igd_context_t *context);
+static void gtt_init_plb(igd_context_t *context);
+
+
+static platform_context_plb_t platform_context_plb;
+
+/* Graphics frequency list. This is valid for pouslbo only. This value is obtained
+ * From the Cspec - SCH Message Network-Port 5*/
+static unsigned short plb_gfx_freq_list[] =
+{
+ 100, 133, 150, 178, 200, 266, 0, 0
+};
+
+init_dispatch_t init_dispatch_plb = {
+ "Intel SCH US15 Chipset",
+ "US15",
+ "lvds",
+ query_plb,
+ config_plb,
+ set_param_plb,
+ get_param_plb,
+ shutdown_plb,
+ NULL
+};
+
+
+
+/*
+ * GTT shutdown.
+ *
+ * Unmap the GTT mapping that was done during init time.
+ */
+static void gtt_shutdown_plb(igd_context_t *context)
+{
+ if (context->device_context.virt_gttadr) {
+ iounmap(context->device_context.virt_gttadr);
+
+ context->device_context.virt_gttadr = NULL;
+ }
+}
+
+
+/*
+ * Initialize the GTT.
+ * - Find the size of stolen memory
+ * - Add stolen memory to the GTT
+ * - Map the GTT and video memory
+ */
+
+static void gtt_init_plb(igd_context_t *context)
+{
+ struct drm_device *dev;
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long dvmt_mode = 0;
+ unsigned long gtt_pages = 0;
+ unsigned long stolen_mem_size = 0;
+ unsigned long scratch;
+ unsigned long base;
+ unsigned long pte;
+ unsigned short gmch_ctl;
+ unsigned long pge_ctl;
+ unsigned long gtt_phys_start;
+ unsigned long gatt_start;
+ unsigned long gatt_pages;
+ unsigned long gtt_start;
+ unsigned long gtt_order;
+ unsigned long stolen_mem_base;
+ unsigned long *gtt_table;
+ int gtt_enabled = FALSE;
+ struct page *gtt_table_page;
+ int i;
+
+ dev = (struct drm_device *)context->drm_dev;
+
+ /* Enable the GMCH */
+ OS_PCI_READ_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+ &gmch_ctl);
+ OS_PCI_WRITE_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+ (gmch_ctl | PSB_GMCH_ENABLED));
+ context->device_context.gmch_ctl = gmch_ctl;
+
+ /* Get the page table control register */
+ pge_ctl = readl(mmio + PSB_PGETBL_CTL);
+ gtt_phys_start = pge_ctl & PAGE_MASK;
+
+ gtt_enabled = pge_ctl & PSB_PGETBL_ENABLED;
+
+ /* Create a scratch page to initialize empty GTT entries */
+ context->device_context.scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+
+ /*
+ * Is pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); the same
+ * as pci_read_config_dword(dev->pdev, 0x1C, &value)?
+ *
+ * PSB_GATT_RESOURCE length is the amount of memory addressable
+ * by the GTT table.
+ */
+ gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+ gatt_pages = (pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT);
+ context->device_context.gatt_pages = gatt_pages;
+
+ /*
+ * The GTT wasn't set up by the vBios
+ */
+ if (!gtt_enabled) {
+ context->device_context.stolen_pages = 0;
+
+ gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+ gtt_order = get_order(gtt_pages << PAGE_SHIFT);
+ gtt_table = (unsigned long *)__get_free_pages(GFP_KERNEL, gtt_order);
+ /* Make sure allocation was successful */
+ if (NULL == gtt_table) {
+ EMGD_ERROR("Failed to allocate kernel pages for GTT");
+ return;
+ }
+ context->device_context.virt_gttadr = gtt_table;
+
+ for (i=0; i < (1 << gtt_order); i++) {
+ gtt_table_page = virt_to_page(gtt_table + (PAGE_SIZE * i));
+ EMGD_DEBUG("Setting reserved bit on %p", gtt_table_page);
+ set_bit(PG_reserved, >t_table_page->flags);
+ }
+
+ gtt_phys_start = virt_to_phys(gtt_table);
+
+ for (i = 0; i < gtt_pages; i++) {
+ gtt_table[i] = (unsigned long)context->device_context.scratch_page;
+ }
+
+ printk(KERN_INFO "Detected GTT was not enabled by firmware");
+ printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
+ gatt_start, (gatt_pages / 256));
+ printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
+ "actual RAM base 0x%08lx.\n",
+ (unsigned long)gtt_table, (gtt_pages * 4), gtt_phys_start);
+
+ /* Enable the newly created GTT */
+ EMGD_DEBUG("Enabling new GTT");
+ writel((gtt_phys_start|PSB_PGETBL_ENABLED), mmio + PSB_PGETBL_CTL);
+ pge_ctl = readl(mmio + PSB_PGETBL_CTL);
+
+ } else {
+
+ /*
+ * Get the start address of the GTT page table
+ *
+ * In full_config_vga, this is done differently. The address is read
+ * from pcidev0's pci config space, at TNC_PCI_GTTADR and the size comes
+ * from TNC_OFFSET_VGA_MSAC. The value read for size is a size id
+ * 1 = 128, 2 = 256, 3 = 512
+ * emgd_gtt->gtt_start = OS_PCI_READ_CONFIG_32(
+ * context->platform_context->pcidev0, TNC_PCI_GTTADDR)
+ * gtt_pages = OS_PCI_READ_CONFIG_8(context->platform_context->pcidev0,
+ * TNC_OFFSET_VGA_MSAC) * 1024;
+ *
+ * PSB_GTT_RESOURCE length is the size of the GTT table. Thus,
+ * gtt_pages is the number of pages that make up the table.
+ */
+ gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+ gtt_pages = (pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT);
+
+ /* Get stolen memory configuration. */
+ pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)&stolen_mem_base);
+ stolen_mem_size = gtt_phys_start - stolen_mem_base - PAGE_SIZE;
+
+ /* Display useful information in the kernel log */
+ printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
+ gatt_start, (gatt_pages / 256));
+ printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
+ "actual RAM base 0x%08lx.\n",
+ gtt_start, (gtt_pages * 4), gtt_phys_start);
+ printk(KERN_INFO "Stolen memory information \n");
+ printk(KERN_INFO " base in RAM: 0x%lx \n", stolen_mem_base);
+ printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - "
+ "(Stolen base)\n", (stolen_mem_size / 1024));
+ dvmt_mode = (gmch_ctl >> 4) & 0x7;
+ printk(KERN_INFO " size: %dM (dvmt mode=%ld)\n",
+ (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+ context->device_context.virt_gttadr =
+ ioremap_nocache(gtt_start, gtt_pages << PAGE_SHIFT);
+
+ if (!context->device_context.virt_gttadr) {
+ printk(KERN_ERR "Failed to map the GTT.\n");
+ /* TODO: Clean up somelthing here */
+ return;
+ }
+
+ /* Insert stolen memory pages into the beginning of GTT */
+ base = stolen_mem_base >> PAGE_SHIFT;
+ context->device_context.stolen_pages = stolen_mem_size >> PAGE_SHIFT;
+
+ printk(KERN_INFO "Set up %ld stolen pages starting at 0x%08lx, "
+ "GTT offset %dK\n", context->device_context.stolen_pages, base, 0);
+
+ for (i = 0; i < context->device_context.stolen_pages; i++) {
+ pte = ((base + i) << PAGE_SHIFT) | PSB_PTE_VALID;
+ writel(pte, context->device_context.virt_gttadr + i);
+ }
+
+ }
+
+ /* Update the scratch registers to say we have no stolen memory */
+ scratch = readl(mmio + SCR1);
+ if ((scratch & FW_ID) == FW_ID) {
+ /* if an EMGD vBios modify only the stolen memory bit */
+ scratch |= ST_BIT;
+ writel(scratch, mmio + SCR1);
+ } else {
+ /* Not an EMGD vBios so just set the entire register to a known value */
+ writel((FW_ID|ST_BIT), mmio + SCR1);
+ }
+
+ /*
+ * Report back that there is 0MB of stolen memory regardless of
+ * what was really in there. Fresh pages will be inserted over
+ * the top of the existing stolen memory.
+ */
+ writel(0, mmio + SCR2);
+
+ /*
+ * FIXME: Shouldn't this fill in all the GTT page table entries with
+ * the scratch page?
+ */
+
+ return;
+}
+
+
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ * @param bus
+ * @param slot
+ * @param func
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int query_plb(
+ igd_context_t *context,
+ init_dispatch_t *dispatch,
+ os_pci_dev_t vga_dev,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *func)
+{
+ platform_context_plb_t *platform_context = &platform_context_plb;
+
+ EMGD_TRACE_ENTER;
+
+ context->platform_context = (void *)&platform_context_plb;
+
+ OS_PTHREAD_MUTEX_INIT(&platform_context_plb.flip_mutex, NULL);
+
+ /*
+ * Current specs indicate that PLB has only one PCI function.
+ * If this changes then we need to make sure we have func 0
+ * here as in previous chips.
+ */
+ platform_context->pcidev0 = vga_dev;
+
+ OS_PCI_GET_SLOT_ADDRESS(vga_dev, bus, slot, func);
+
+ OPT_MICRO_CALL(get_revision_id_plb(context, vga_dev));
+
+ /*
+ * Read BSM.
+ * This must be in query so it is available early for the vBIOS.
+ */
+ if(OS_PCI_READ_CONFIG_32(vga_dev,
+ PLB_PCI_BSM, &context->device_context.fb_adr)) {
+ EMGD_ERROR_EXIT("Reading BSM");
+ return -IGD_ERROR_NODEV;
+ }
+ context->device_context.fb_adr &= 0xFFFFF000;
+
+ EMGD_DEBUG("BSM (High)@: 0x%lx, (Low) 0x%4lx", (context->device_context.fb_adr >> 16), context->device_context.fb_adr);
+
+ /*
+ * Read IO Base.
+ * This must be in query so it is available early for the vBIOS.
+ */
+ if(OS_PCI_READ_CONFIG_16(vga_dev, PLB_PCI_IOBAR, &io_base)) {
+ EMGD_ERROR_EXIT("Reading IO Base");
+ return -IGD_ERROR_NODEV;
+ }
+ io_base &= 0xfffe;
+ EMGD_DEBUG("io @: 0x%x", io_base);
+
+ /* Gen4 is always io_mapped */
+ io_mapped = 1;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int config_plb(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ unsigned long coreclk;
+ unsigned long graphics_frequency;
+
+ platform_context_plb_t *platform_context =
+ (platform_context_plb_t *)context->platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ OPT_MICRO_CALL(full_config_plb(context, dispatch));
+
+ /* If KMS is set, we need to unset it as KMS is not supported on PLB */
+ config_drm.kms = 0;
+
+ /* Set the Max Dclock */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+ INTEL_OFFSET_VGA_CORECLK, &coreclk)) {
+ EMGD_ERROR_EXIT("PCI Read of VGA Core Clock");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Get graphics frequency param if it exists */
+ if(!get_param_plb(context, IGD_PARAM_GFX_FREQ,
+ &graphics_frequency)) {
+ context->device_context.gfx_freq = (unsigned short)graphics_frequency;
+ }
+
+ /*
+ * FIXME:
+ * Coreclk register above is used to determine some clocking information
+ * there is also a fuse to limit the dclk. More research needed.
+ */
+ context->device_context.max_dclk = 762000;
+
+ gtt_init_plb(context);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_param_plb(igd_context_t *context, unsigned long id,
+ unsigned long *value)
+{
+ int ret = 0;
+ unsigned long control_reg;
+ os_pci_dev_t bridge_dev = (os_pci_dev_t)0;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("ID: 0x%lx", id);
+
+ /* Scratch registers used as below:
+ *
+ * 0x71410:
+ * --------
+ * Bits 31-16 - EID Firmware identifier 0xE1DF
+ * Bits 15-00 - Tell what data is present.
+ * Here are bits for what we are using know:
+ * Bit 0 - Panel id
+ * Bit 1 - List of ports for which displays are attached
+ * Bit 2 - Memory reservation
+ * If any of the above bits is set that mean data is followed
+ * in the next registers.
+ *
+ * 0x71414:
+ * --------
+ * Bits 07-00 - Panel Id
+ * Bits 11-08 - Port list
+ * Information for Port list: If any of the bit is set means,
+ * a display is attached to that port as follows:
+ * Bit 08 - CRT
+ * Bit 09 - DVOA/Internal LVDS
+ * Bit 10 - DVOB/RGBA
+ * Bit 11 - DVOC
+ *
+ * 0x71418:
+ * --------
+ * Bits 15-00 - Reserved Memory value in number of 4k size pages
+ */
+ *value = 0;
+
+ switch(id) {
+ case IGD_PARAM_PORT_LIST:
+
+ control_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) +
+ 0x71410);
+
+ /*
+ * Verify that the Embedded Firware is present.
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("Exit No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * If the port list bit is set in control register,
+ * read the port list
+ */
+ if (control_reg & 0x2) {
+ unsigned char temp;
+ int i = 0;
+
+ temp = (unsigned char)((EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x71414)>>8) & 0xFF);
+ EMGD_DEBUG("Connected Port Bits: 0x%x", temp);
+
+ /*
+ * The meanings of bits in temp were dictated by VBIOS
+ * and should not change due to backward compatibility
+ * with Legacy VBIOS
+ */
+ if (temp & 0x01) {
+ /* Analog port */
+ value[i++] = 5;
+ }
+ if (temp & 0x02) {
+ /* Internal LVDS port */
+ value[i++] = 4;
+ }
+ if (temp & 0x04) {
+ /* DVOB Port */
+ value[i++] = 2;
+ }
+ } else {
+ EMGD_DEBUG("Port List read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ case IGD_PARAM_GFX_FREQ:
+ /* Query register values from the bridge. This method uses the Poulsbo
+ * SCH Message Network. Setting offset 0xD0 in the host bridge config
+ * register sends an opcode to the Message Network. Reading register 0xD4
+ * from the host bridge config register will get the return value of the
+ * sent opcode.
+ *
+ * This feature is for Pouslbo Only */
+
+ bridge_dev = OS_PCI_FIND_DEVICE(
+ PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_BRIDGE_PLB,
+ 0xFFFF, /* Scan the whole PCI bus */
+ 0,
+ 0,
+ (os_pci_dev_t)0);
+
+ if(!bridge_dev) {
+ EMGD_ERROR_EXIT("Bridge device NOT found.");
+ return -IGD_ERROR_INVAL;
+ }
+ /* write into the Message Control Register (MCR)
+ * [INPUT] should contain the formatted opcode
+ * that needs to be sent into the MCR */
+ ret = OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD0,
+ (0xD0<<24)/*opcode*/|(5<<16)/*port*/|(3<<8)/*reg*/|(0xF<<4));
+ if(ret) {
+ EMGD_ERROR("Writing into the MCR Failed");
+ return -IGD_ERROR_INVAL;
+ }
+ /* read from the Message Data Register (MDR) */
+ if(OS_PCI_READ_CONFIG_32(bridge_dev, 0xD4,
+ (void*) &control_reg)) {
+ EMGD_ERROR_EXIT("Reading from MDR Failed");
+ return -IGD_ERROR_INVAL;
+ }
+ *value = plb_gfx_freq_list[control_reg & 0x7];
+ OS_PCI_FREE_DEVICE(bridge_dev);
+ break;
+ default:
+ /*
+ * If the param is not found here then it may only be in the
+ * full version.
+ */
+ OPT_MICRO_CALL_RET(ret, full_get_param_plb(context, id, value));
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ * No Settable Params for PLB
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL
+ */
+static int set_param_plb(igd_context_t *context, unsigned long id,
+ unsigned long value)
+{
+ return -IGD_ERROR_INVAL;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void shutdown_plb(igd_context_t *context)
+{
+ gtt_shutdown_plb(context);
+
+ OPT_MICRO_VOID_CALL(full_shutdown_plb(context));
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c b/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
new file mode 100644
index 0000000..c07d82d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
@@ -0,0 +1,621 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_tnc.c
+ * $Revision: 1.24 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <gart.h>
+
+#include <memory.h>
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_gart.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/igd_tnc_wa.h>
+
+#include "../cmn/init_dispatch.h"
+#include "/usr/include/linux/pci_regs.h"
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+static int bus_master_enable_tnc(platform_context_tnc_t *platform_context);
+static int full_config_vga_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch);
+static int get_stolen_mem_tnc(igd_context_t *context, unsigned long *pages);
+
+int full_get_param_tnc(igd_context_t *context,
+ unsigned long id,
+ unsigned long *value);
+
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return 1 on failure
+ * @return 0 on success
+ */
+int full_config_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ unsigned long reserved_mem;
+ platform_context_tnc_t *platform_context;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+
+ _sgx_base = 0x80000;
+ _msvdx_base = 0x90000;
+ _topaz_base = 0xA0000;
+
+ /*
+ * Enable bus mastering for platforms whose BIOS did not perform this
+ * task for us.
+ */
+ ret = bus_master_enable_tnc(platform_context);
+ if(ret) {
+ EMGD_ERROR("Error: Enabling bus master");
+ }
+
+ /* Config VGA */
+ ret = full_config_vga_tnc(context, dispatch);
+ if(ret) {
+ EMGD_ERROR_EXIT("Config VGA Failed");
+ return ret;
+ }
+
+ get_stolen_mem_tnc(context, &context->device_context.reserved_mem);
+
+ /* Get mem reservation param if it exists */
+ if(!full_get_param_tnc(context, IGD_PARAM_MEM_RESERVATION,
+ &reserved_mem)) {
+ context->device_context.reserved_mem = reserved_mem;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param platform_context
+ *
+ * @return -1 on failure
+ * @return 0 on success
+ */
+/*
+ */
+static int bus_master_enable_tnc(platform_context_tnc_t *platform_context){
+ int ret;
+ unsigned char tmp, tmp_sdvo;
+
+ EMGD_TRACE_ENTER;
+
+ ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, &tmp);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI read of bus master");
+ return -1;
+ }
+
+ /*
+ * Get Bit 2, 1, and 0 and see if it is == 1
+ * all 3 bits has to be enabled. This is to enable register read/write
+ * in the case of a PCI card being added
+ */
+ if((tmp & 0x7) != 0x7 ) {
+
+ tmp |= 0x7;
+ ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev0,PCI_COMMAND_MASTER, tmp);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI write of bus master");
+ return -1;
+ }
+ }
+
+
+ if (platform_context->pcidev1) {
+ ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev1,PCI_COMMAND_MASTER, &tmp_sdvo);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI read of bus master");
+ return -1;
+ }
+
+ if((tmp_sdvo & 0x7) != 0x7 ) {
+ tmp_sdvo |= 0x7;
+ ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev1,
+ PCI_COMMAND_MASTER,tmp_sdvo);
+ if(ret) {
+ EMGD_ERROR_EXIT("PCI write of bus master");
+ return -1;
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int full_config_vga_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ platform_context_tnc_t *platform_context =
+ (platform_context_tnc_t *)context->platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Map the Device 2 MMIO register. These registers are similar to LNC
+ * and is located in the Atom E6xx Hard Macro
+ */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+ TNC_PCI_MMADR, (void*)&context->device_context.mmadr)) {
+ EMGD_ERROR_EXIT("Reading MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ context->device_context.mmadr &= 0xfffffff9;
+ context->device_context.virt_mmadr =
+ OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr, TNC_D2_MMIO_SIZE);
+
+ if (!context->device_context.virt_mmadr) {
+ EMGD_ERROR_EXIT("Failed to map MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("mmadr mapped %dKB @ (phys):0x%lx (virt):%p",
+ TNC_D2_MMIO_SIZE/1024,
+ context->device_context.mmadr,
+ context->device_context.virt_mmadr);
+
+
+ /*
+ * Map the device 3 MMIO registers. These are Atom E6xx specific registers
+ * located in the Atom E6xx Overlay. On LNC, these registers are part of
+ * the IOH (Langwell)
+ */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev1,
+ TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo)) {
+ EMGD_ERROR_EXIT("Reading MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ context->device_context.mmadr_sdvo &= 0xfffffff9;
+ context->device_context.virt_mmadr_sdvo =
+ OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo,
+ TNC_D3_MMIO_SIZE);
+
+ if (!context->device_context.virt_mmadr_sdvo) {
+ EMGD_ERROR_EXIT("Failed to map MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("sdvo mmadr mapped %dKB @ (phys):0x%lx (virt):%p",
+ TNC_D3_MMIO_SIZE/1024,
+ context->device_context.mmadr_sdvo,
+ context->device_context.virt_mmadr_sdvo);
+
+ /* Map the STMicro SDVO registers. */
+ if(platform_context->stbridgedev) {
+ if(OS_PCI_READ_CONFIG_32(platform_context->stbridgedev,
+ TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo_st)) {
+ EMGD_ERROR_EXIT("Reading MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ context->device_context.mmadr_sdvo_st &= 0xfffffff9;
+ context->device_context.virt_mmadr_sdvo_st =
+ OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo_st,
+ TNC_ST_SDVO_MMIO_SIZE);
+
+ if (!context->device_context.virt_mmadr_sdvo_st) {
+ EMGD_ERROR_EXIT("Failed to map MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("STMicro sdvo mmadr mapped %dKB @ (phys):0x%lx (virt):%p",
+ TNC_ST_SDVO_MMIO_SIZE/1024,
+ context->device_context.mmadr_sdvo_st,
+ context->device_context.virt_mmadr_sdvo_st);
+
+ /* Map the STMicro GPIO registers. */
+ if(OS_PCI_READ_CONFIG_32(platform_context->stgpiodev,
+ TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo_st_gpio)) {
+ EMGD_ERROR_EXIT("Reading MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ context->device_context.mmadr_sdvo_st_gpio &= 0xfffffff9;
+ context->device_context.virt_mmadr_sdvo_st_gpio =
+ OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo_st_gpio,
+ TNC_ST_SDVO_MMIO_SIZE);
+
+ if (!context->device_context.virt_mmadr_sdvo_st_gpio) {
+ EMGD_ERROR_EXIT("Failed to map MMADR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("STMicro sdvo gpio mmadr mapped %dKB @ (phys):0x%lx (virt):%p",
+ TNC_ST_SDVO_MMIO_SIZE/1024,
+ context->device_context.mmadr_sdvo_st_gpio,
+ context->device_context.virt_mmadr_sdvo_st_gpio);
+ }
+
+ /* Map the GPIO BAR. Provides the 64 bytes of I/O space for GPIO
+ * BAR is defined by bits 15:6 */
+
+ if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
+ TNC_PCI_GBA, (void*)&context->device_context.gpio_bar)) {
+
+ }
+ context->device_context.gpio_bar |= (1L<<31);
+ /* Enable the decode of IO Range ppointed to by the BA */
+ if(OS_PCI_WRITE_CONFIG_32(platform_context->lpc_dev,
+ TNC_PCI_GBA, context->device_context.gpio_bar)) {
+ EMGD_ERROR_EXIT("Writing LPC GPIO BAR Enable");
+ }
+
+ /* read the GPIO BAR (OFFSET 44:47) */
+ if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
+ TNC_PCI_GBA, (void*)&context->device_context.gpio_bar)) {
+ EMGD_ERROR_EXIT("Reading LPC GPIO BAR");
+ /* We cannot read the GPIO BAR. It is a problem but we can go on with init
+ * return with NO ERROR*/
+ return 0;
+ }
+
+ context->device_context.gpio_bar &= 0xffc0;
+
+ context->device_context.virt_gpio_bar =
+ OS_MAP_IO_TO_MEM_NOCACHE(
+ context->device_context.gpio_bar, 64);
+
+ if (!context->device_context.virt_gpio_bar) {
+ EMGD_ERROR_EXIT("Failed to map LPC GPIO BAR");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG("GPIO mapped %dKB @ (phys):0x%lx (virt):%p",
+ 64,
+ context->device_context.gpio_bar,
+ context->device_context.virt_gpio_bar);
+
+ /* PCI Interrupt Line */
+ if(OS_PCI_READ_CONFIG_8(platform_context->pcidev0,
+ PCI_INTERRUPT_LINE, (void*)&platform_context->irq)) {
+ platform_context->irq = 0;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Get the # of pages used for video memory. This does not use information from
+ * the scratch register, since this is done later if it exists.
+ *
+ * @param context
+ * @param pages
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_stolen_mem_tnc(igd_context_t *context, unsigned long *pages)
+{
+ platform_context_tnc_t *platform_context;
+ os_pci_dev_t vga_dev;
+ unsigned short gmch_ctl;
+ unsigned long stolen_mem; /* in bytes */
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+ vga_dev = platform_context->pcidev0;
+
+ ret = OS_PCI_READ_CONFIG_16(vga_dev, TNC_PCI_GC, &gmch_ctl);
+ if (ret) {
+ EMGD_ERROR_EXIT("Unable to read TNC_PCI_GC");
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch (gmch_ctl & 0x70) {
+ case 0x00:
+ stolen_mem = 0;
+ break;
+ case 0x10:
+ /* 1M */
+ stolen_mem = 1*1024*1024;
+ break;
+ case 0x20:
+ /* 4M */
+ stolen_mem = 4*1024*1024;
+ break;
+ case 0x30:
+ /* 8M */
+ stolen_mem = 8*1024*1024;
+ break;
+ case 0x40:
+ /* 16M */
+ stolen_mem = 16*1024*1024;
+ break;
+ case 0x50:
+ /* 32M */
+ stolen_mem = 32*1024*1024;
+ break;
+ case 0x60:
+ /* 48M */
+ stolen_mem = 48*1024*1024;
+ case 0x70:
+ /* 64M */
+ stolen_mem = 64*1024*1024;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Unknown Stolen Memory Size");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (stolen_mem) {
+ /*
+ * Subtract off the size of the GTT which is
+ * (number of entries in DWORDS) * 4 to get it into bytes
+ */
+ stolen_mem -= context->device_context.gatt_pages*4;
+ /* Subtract off 1 page for the scratch page */
+ stolen_mem -= 4*1024;
+ }
+
+ /* Convert to the # of pages available for stolen memory */
+ *pages = stolen_mem / 4096;
+
+ EMGD_DEBUG("Stolen memory: 0x%lx pages", *pages);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int full_get_param_tnc(igd_context_t *context,
+ unsigned long id,
+ unsigned long *value)
+{
+ int ret = 0;
+ unsigned char *mmio;
+ unsigned long control_reg;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("ID: 0x%lx", id);
+
+ /* Scratch registers used as below:
+ *
+ * 0x71410:
+ * --------
+ * Bits 31-16 - EID Firmware identifier 0xE1DF
+ * Bits 15-00 - Tell what data is present.
+ * Here are bits for what we are using know:
+ * Bit 0 - Panel id
+ * Bit 1 - List of ports for which displays are attached
+ * Bit 2 - Memory reservation
+ * If any of the above bits is set that mean data is followed
+ * in the next registers.
+ *
+ * 0x71414:
+ * --------
+ * Bits 07-00 - Panel Id
+ * Bits 11-08 - Port list
+ * Information for Port list: If any of the bit is set means,
+ * a display is attached to that port as follows:
+ * Bit 08 - CRT
+ * Bit 09 - DVOA/Internal LVDS
+ * Bit 10 - DVOB/RGBA
+ * Bit 11 - DVOC
+ *
+ * 0x71418:
+ * --------
+ * Bits 15-00 - Reserved Memory value in number of 4k size pages
+ */
+ mmio = context->device_context.virt_mmadr;
+ control_reg = EMGD_READ32(EMGD_MMIO(mmio) + 0x71410);
+ *value = 0;
+
+ switch(id) {
+ case IGD_PARAM_PANEL_ID:
+ /*
+ * Check for Embedded firmware
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * The panel id bit must be set in the control register
+ * to indicate valid panel (config) ID value.
+ */
+ if (control_reg & 0x1) {
+ *value = EMGD_READ32(EMGD_MMIO(mmio) + 0x71414) & 0xFF;
+ if(!(*value)) {
+ /* we cannot allow for config id = 0 */
+ ret = -IGD_ERROR_INVAL;
+ }
+ } else {
+ EMGD_DEBUG("Panel ID read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ case IGD_PARAM_MEM_RESERVATION:
+ /*
+ * Check for Embedded firmware
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * The mem reservation bit must be set in the control register
+ * to indicate valid mem reservation value.
+ */
+ if (control_reg & 0x4) {
+ *value = (EMGD_READ32(EMGD_MMIO(mmio) + 0x71418) & 0xFFFF);
+ } else {
+ EMGD_DEBUG("Mem Reservation read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ default:
+ ret = -IGD_ERROR_INVAL;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void full_shutdown_tnc(igd_context_t *context)
+{
+ platform_context_tnc_t *platform_context =
+ (platform_context_tnc_t *)context->platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ /* unmap registers */
+ if(context->device_context.virt_mmadr) {
+ EMGD_DEBUG("Unmapping Gfx registers and GTT Table...");
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr,
+ TNC_D2_MMIO_SIZE);
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo,
+ TNC_D3_MMIO_SIZE);
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo_st,
+ TNC_ST_SDVO_MMIO_SIZE);
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo_st_gpio,
+ TNC_ST_SDVO_MMIO_SIZE);
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gpio_bar, 64);
+
+ OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gttadr,
+ context->device_context.gatt_pages * 4);
+ } else {
+ printk(KERN_ERR "Unmapping MMIO space failed.\n");
+ }
+
+ if (platform_context) {
+ OS_PCI_FREE_DEVICE(platform_context->pcidev0);
+ OS_PCI_FREE_DEVICE(platform_context->pcidev1);
+ OS_PCI_FREE_DEVICE(platform_context->bridgedev);
+ if (platform_context->lpc_dev) {
+ OS_PCI_FREE_DEVICE(platform_context->lpc_dev);
+ }
+ }
+ EMGD_TRACE_EXIT;
+}
+
+
+ int query_2d_caps_hwhint_tnc(
+ igd_context_t *context,
+ unsigned long caps_val,
+ unsigned long *status)
+{
+ platform_context_tnc_t *platform_context;
+
+ EMGD_TRACE_ENTER;
+
+
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+
+ /*
+ * Only 2D BLT capability query is currently implemented.
+ * This is required by TNC B0 flickering workaround.
+ * Query for other 2D capability can be implemented
+ * in the future if neeeded.
+ */
+ switch (caps_val) {
+ case IGD_2D_CAPS_BLT:
+ if((context->device_context.did == PCI_DEVICE_ID_VGA_TNC) &&
+ (context->device_context.rid == TNC_B0_RID) &&
+ (platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID)) {
+ *status = IGD_2D_HW_DISABLE;
+ /* disable 2d blt hardware acceleration for TNC B0 */
+ } else {
+ *status = IGD_2D_HW_ENABLE;
+ /* enable 2d blt hardware acceleration */
+ }
+ break;
+
+ default:
+ *status = IGD_2D_CAPS_UNKNOWN;
+ /* Unknown 2d capability to query */
+ EMGD_ERROR("2D caps to query is unknown!");
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c b/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
new file mode 100644
index 0000000..005a00d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
@@ -0,0 +1,1025 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_init_tnc.c
+ * $Revision: 1.26 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memory.h>
+#include <asm/cacheflush.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <linux/pci_ids.h>
+
+#include "../cmn/init_dispatch.h"
+
+#define PFX "EMGD: "
+
+#define SCR1 0x71410 /* scratch register set by vbios indicating status*/
+#define SCR2 0x71418 /* scratch register set by vbios indicating amount of stolen memory */
+#define FW_ID 0xE1DF0000 /* firmware identifier */
+#define ST_BIT 0x00000004 /* bit2- stolen memory bit */
+#define PSB_GMCH_CTRL 0x52
+#define PSB_GMCH_ENABLED 0x04
+#define PSB_PGETBL_CTL 0x00002020
+#define PSB_GATT_RESOURCE 2
+#define PSB_GTT_RESOURCE 3
+#define PSB_BSM 0x5c
+#define PSB_PTE_VALID 0x0001
+
+
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+#ifdef CONFIG_TNC
+
+extern unsigned char io_mapped;
+extern unsigned short io_base;
+
+/* For dev2 [0:2:0] */
+extern unsigned char io_mapped_lvds;
+extern unsigned short io_base_lvds;
+
+/* For dev3 [0:3:0] */
+extern unsigned char io_mapped_sdvo;
+extern unsigned short io_base_sdvo;
+
+/* For dev31 [0:31:0] */
+extern unsigned char io_mapped_lpc;
+extern unsigned short io_base_lpc;
+
+/* For STMicro SDVO [6:0:1] */
+extern unsigned char io_mapped_sdvo_st;
+extern unsigned short io_base_sdvo_st;
+extern unsigned char io_mapped_sdvo_st_gpio;
+extern unsigned short io_base_sdvo_st_gpio;
+
+extern int full_config_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch);
+extern int get_revision_id_tnc(igd_context_t *context, os_pci_dev_t vga_dev, os_pci_dev_t sdvo_dev);
+extern int full_get_param_tnc(igd_context_t *context, unsigned long id,
+ unsigned long *value);
+extern void full_shutdown_tnc(igd_context_t *context);
+
+extern int query_2d_caps_hwhint_tnc(
+ igd_context_t *context,
+ unsigned long caps_val,
+ unsigned long *status);
+
+static int query_tnc(igd_context_t *context,init_dispatch_t *dispatch,
+ os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
+ unsigned int *func);
+static int config_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch);
+static int set_param_tnc(igd_context_t *context, unsigned long id,
+ unsigned long value);
+static int get_param_tnc(igd_context_t *context, unsigned long id,
+ unsigned long *value);
+static void shutdown_tnc(igd_context_t *context);
+
+static void gtt_shutdown_tnc(igd_context_t *context);
+static void gtt_init_tnc(igd_context_t *context);
+
+/* Helper Functions */
+static int query_sch_message(unsigned long reg, unsigned long* value);
+static int dump_fuse_values(void);
+
+static platform_context_tnc_t platform_context_tnc;
+
+os_pci_dev_t bridge_dev;
+
+init_dispatch_t init_dispatch_tnc = {
+ "Intel Atom E6xx Processor",
+ "Atom_E6xx",
+ "lvds",
+ query_tnc,
+ config_tnc,
+ set_param_tnc,
+ get_param_tnc,
+ shutdown_tnc,
+ query_2d_caps_hwhint_tnc
+};
+
+/* Array to keep the Bridge ID. Atom E6xx ULP uses a different bridge ID */
+static unsigned short bridge_id[] =
+{
+ PCI_DEVICE_ID_BRIDGE_TNC,
+ PCI_DEVICE_ID_BRIDGE_TNC_ULP,
+ 0
+};
+
+#define SKU_NO 3
+#define RATIO_NO 8
+/*
+ * Atom E6xx GFX frequencies
+ * The gfx clock frequencies depends on the board SKU and ratio
+ * The table of frequencies can be found in Atom E6xx EAS
+ * Chapter: Clocks and Reset Unit
+ */
+static unsigned short tnc_gfx_freq_list[RATIO_NO][SKU_NO] =
+{
+ /* rows represent the gfx clock ratio,
+ * columns the sku */
+
+ /* sku_100 sku_100L sku_83 */
+ {200, 100, 166}, /*1:1*/
+ {266, 133, 222}, /*4:3*/
+ {320, 160, 266}, /*8:5*/
+ {400, 200, 333}, /*2:1 DEFAULT*/
+ {0, 0, 0 }, /*16:7 RSVD*/
+ {533, 266, 444}, /*8:3*/
+ {640, 320, 553}, /*16:5*/
+ {800, 400, 666} /*4:1 RSVD*/
+};
+
+static unsigned short tnc_core_freq_list[SKU_NO] =
+{
+/* sku_100 sku_100L sku_83 */
+ 200, 100, 166
+};
+
+/* MCR define */
+#define READ_FUS_EFF0 0xD08106F0
+#define READ_FUS_EFF1 0xD08107F0
+#define READ_FUS_EFF2 0xD08108F0
+#define READ_FUS_EFF3 0xD08109F0
+#define READ_FUS_EFF4 0xD0810AF0
+#define READ_FUS_EFF5 0xD0810BF0
+
+
+
+/*
+ * GTT shutdown.
+ *
+ * Unmap the GTT mapping that was done during init time.
+ */
+static void gtt_shutdown_tnc(igd_context_t *context)
+{
+ if (context->device_context.virt_gttadr) {
+ iounmap(context->device_context.virt_gttadr);
+
+ context->device_context.virt_gttadr = NULL;
+ }
+ if(context->device_context.scratch_page){
+ __free_page(context->device_context.scratch_page);
+ context->device_context.scratch_page = NULL;
+ }
+}
+
+
+/*
+ * Initialize the GTT.
+ * - Find the size of stolen memory
+ * - Add stolen memory to the GTT
+ * - Map the GTT and video memory
+ */
+
+static void gtt_init_tnc(igd_context_t *context)
+{
+ struct drm_device *dev;
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long dvmt_mode = 0;
+ unsigned long gtt_pages = 0;
+ unsigned long stolen_mem_size = 0;
+ unsigned long scratch;
+ unsigned long base;
+ unsigned long pte;
+ unsigned short gmch_ctl;
+ unsigned long pge_ctl;
+ unsigned long gtt_phys_start;
+ unsigned long gatt_start;
+ unsigned long gatt_pages;
+ unsigned long gtt_start;
+ unsigned long gtt_order;
+ unsigned long stolen_mem_base;
+ unsigned long *gtt_table;
+ struct page *gtt_table_page;
+ int i;
+
+ dev = (struct drm_device *)context->drm_dev;
+
+ /* Enable the GMCH */
+ OS_PCI_READ_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+ &gmch_ctl);
+ OS_PCI_WRITE_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+ (gmch_ctl | PSB_GMCH_ENABLED));
+ context->device_context.gmch_ctl = gmch_ctl;
+
+ /* Get the page table control register */
+ pge_ctl = readl(mmio + PSB_PGETBL_CTL);
+ gtt_phys_start = pge_ctl & PAGE_MASK;
+
+ /* Create a scratch page to initialize empty GTT entries */
+ if(NULL == context->device_context.scratch_page){
+ context->device_context.scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+ }
+
+ /*
+ * Is pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); the same
+ * as pci_read_config_dword(dev->pdev, 0x1C, &value)?
+ *
+ * PSB_GATT_RESOURCE length is the amount of memory addressable
+ * by the GTT table.
+ */
+ gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+ gatt_pages = (pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT);
+ context->device_context.gatt_pages = gatt_pages;
+
+ /*
+ * The GTT wasn't set up by the vBios
+ */
+ if (!pge_ctl) {
+ context->device_context.stolen_pages = 0;
+
+ gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+ gtt_order = get_order(gtt_pages << PAGE_SHIFT);
+ gtt_table = (unsigned long *)__get_free_pages(GFP_KERNEL, gtt_order);
+ /* Make sure allocation was successful */
+ if (NULL == gtt_table) {
+ EMGD_ERROR("Failed to allocate kernel pages for GTT");
+ return;
+ }
+ context->device_context.virt_gttadr = gtt_table;
+
+ for (i=0; i < (1 << gtt_order); i++) {
+ gtt_table_page = virt_to_page(gtt_table + (PAGE_SIZE * i));
+ EMGD_DEBUG("Setting reserved bit on %p", gtt_table_page);
+ set_bit(PG_reserved, >t_table_page->flags);
+ }
+
+ gtt_phys_start = virt_to_phys(gtt_table);
+
+ for (i = 0; i < gtt_pages; i++) {
+ gtt_table[i] = (unsigned long)context->device_context.scratch_page;
+ }
+
+ printk(KERN_INFO "Detected GTT was not enabled by firmware");
+ printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
+ gatt_start, (gatt_pages / 256));
+ printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
+ "actual RAM base 0x%08lx.\n",
+ (unsigned long)gtt_table, (gtt_pages * 4), gtt_phys_start);
+
+ /* Enable the newly created GTT */
+ EMGD_DEBUG("Enabling new GTT");
+ writel(gtt_phys_start, mmio + PSB_PGETBL_CTL);
+ pge_ctl = readl(mmio + PSB_PGETBL_CTL);
+
+ } else {
+
+ /*
+ * Get the start address of the GTT page table
+ *
+ * In full_config_vga, this is done differently. The address is read
+ * from pcidev0's pci config space, at TNC_PCI_GTTADR and the size comes
+ * from TNC_OFFSET_VGA_MSAC. The value read for size is a size id
+ * 1 = 128, 2 = 256, 3 = 512
+ * emgd_gtt->gtt_start = OS_PCI_READ_CONFIG_32(
+ * context->platform_context->pcidev0, TNC_PCI_GTTADDR)
+ * gtt_pages = OS_PCI_READ_CONFIG_8(context->platform_context->pcidev0,
+ * TNC_OFFSET_VGA_MSAC) * 1024;
+ *
+ * PSB_GTT_RESOURCE length is the size of the GTT table. Thus,
+ * gtt_pages is the number of pages that make up the table.
+ */
+ gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+ gtt_pages = (pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT);
+
+ /* Get stolen memory configuration. */
+ pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)&stolen_mem_base);
+ stolen_mem_size = gtt_phys_start - stolen_mem_base - PAGE_SIZE;
+
+ /* Display useful information in the kernel log */
+ printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
+ gatt_start, (gatt_pages / 256));
+ printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
+ "actual RAM base 0x%08lx.\n",
+ gtt_start, (gtt_pages * 4), gtt_phys_start);
+ printk(KERN_INFO "Stolen memory information \n");
+ printk(KERN_INFO " base in RAM: 0x%lx \n", stolen_mem_base);
+ printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - "
+ "(Stolen base)\n", (stolen_mem_size / 1024));
+ dvmt_mode = (gmch_ctl >> 4) & 0x7;
+ printk(KERN_INFO " size: %dM (dvmt mode=%ld)\n",
+ (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+ context->device_context.virt_gttadr =
+ ioremap_nocache(gtt_start, gtt_pages << PAGE_SHIFT);
+
+ if (!context->device_context.virt_gttadr) {
+ printk(KERN_ERR "Failed to map the GTT.\n");
+ /* TODO: Clean up somelthing here */
+ return;
+ }
+
+ /* Insert stolen memory pages into the beginning of GTT */
+ base = stolen_mem_base >> PAGE_SHIFT;
+ context->device_context.stolen_pages = stolen_mem_size >> PAGE_SHIFT;
+
+ printk(KERN_INFO "Set up %ld stolen pages starting at 0x%08lx, "
+ "GTT offset %dK\n", context->device_context.stolen_pages, base, 0);
+
+ for (i = 0; i < context->device_context.stolen_pages; i++) {
+ pte = ((base + i) << PAGE_SHIFT) | PSB_PTE_VALID;
+ writel(pte, context->device_context.virt_gttadr + i);
+ }
+
+ }
+
+ /* Update the scratch registers to say we have no stolen memory */
+ scratch = readl(mmio + SCR1);
+ if ((scratch & FW_ID) == FW_ID) {
+ /* if an EMGD vBios modify only the stolen memory bit */
+ scratch |= ST_BIT;
+ writel(scratch, mmio + SCR1);
+ } else {
+ /* Not an EMGD vBios so just set the entire register to a known value */
+ writel((FW_ID|ST_BIT), mmio + SCR1);
+ }
+
+ /*
+ * Report back that there is 0MB of stolen memory regardless of
+ * what was really in there. Fresh pages will be inserted over
+ * the top of the existing stolen memory.
+ */
+ writel(0, mmio + SCR2);
+
+ /*
+ * FIXME: Shouldn't this fill in all the GTT page table entries with
+ * the scratch page?
+ */
+
+ return;
+}
+
+
+/*!
+ * Helper function to query MCR registers
+ * @param reg
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on error
+ * @return 0 on success
+ */
+static int query_sch_message(unsigned long reg, unsigned long* value){
+
+ platform_context_tnc_t *platform_context = &platform_context_tnc;
+
+ /* Send the opcode into the MCR */
+ if(OS_PCI_WRITE_CONFIG_32(platform_context->bridgedev,
+ 0xD0, reg)){
+ EMGD_ERROR_EXIT("Writing into the MCR Failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(OS_PCI_READ_CONFIG_32(platform_context->bridgedev,
+ 0xD4, value)) {
+
+ EMGD_ERROR_EXIT("Writing to MDR Failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ * @param bus
+ * @param slot
+ * @param func
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int query_tnc(
+ igd_context_t *context,
+ init_dispatch_t *dispatch,
+ os_pci_dev_t vga_dev,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *func)
+{
+ platform_context_tnc_t *platform_context = &platform_context_tnc;
+
+ int i = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+
+ /* So we don't have to pollute our function tables with multiple
+ * entries for every variant of TNC, update the device ID if one
+ * of the other SKUs is found
+ */
+ context->device_context.did = PCI_DEVICE_ID_VGA_TNC;
+
+ platform_context->did = context->device_context.did;
+ context->platform_context = (void *)&platform_context_tnc;
+
+ OS_PTHREAD_MUTEX_INIT(&platform_context_tnc.flip_mutex, NULL);
+
+ /* find and store the bridge dev since we will be using it a lot
+ * in the init modules */
+ while(bridge_id[i] != 0){
+ platform_context->bridgedev = OS_PCI_FIND_DEVICE(
+ PCI_VENDOR_ID_INTEL,
+ bridge_id[i],
+ 0xFFFF, /* Scan the whole PCI bus */
+ 0,
+ 0,
+ (os_pci_dev_t)0);
+ if(platform_context->bridgedev){
+ bridge_dev = platform_context->bridgedev;
+ context->device_context.bid = bridge_id[i];
+ break;
+ }
+ i++;
+ }
+ /*
+ * Current specs indicate that Atom E6xx has only one PCI function.
+ * If this changes then we need to make sure we have func 0
+ * here as in previous chips.
+ */
+ platform_context->pcidev0 = vga_dev;
+
+ /* find device 3 */
+ platform_context->pcidev1 = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_SDVO_TNC,
+ 0,
+ 3,
+ 0,
+ (os_pci_dev_t)0);
+
+ platform_context->stbridgedev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
+ PCI_DEVICE_ID_SDVO_TNC_ST,
+ 6,
+ 0,
+ 1,
+ (os_pci_dev_t)0);
+
+ if (platform_context->stbridgedev) {
+ platform_context->stgpiodev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
+ PCI_DEVICE_ID_SDVO_TNC_ST_GPIO,
+ 3,
+ 0,
+ 0,
+ (os_pci_dev_t)0);
+
+ if (!platform_context->stgpiodev) {
+ platform_context->stgpiodev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
+ PCI_DEVICE_ID_SDVO_TNC_ST_GPIO,
+ 4,
+ 0,
+ 5,
+ (os_pci_dev_t)0);
+ if (!platform_context->stgpiodev) {
+ printk("Using STM device, but is not CUT1 or CUT2\n");
+ EMGD_ERROR_EXIT("Using STM device, but is not Cut1 or Cut2");
+ return -IGD_ERROR_NODEV;
+ }
+ }
+ }
+
+ /* Set to NULL, so full_shutdown_tnc() knows whether it was initialized: */
+ platform_context->lpc_dev = NULL;
+
+ /*
+ * finds the bus, device, func to be returned. Do this for D2:F0 only.
+ * the OS does not need to know the existence of D3:F0
+ */
+ OS_PCI_GET_SLOT_ADDRESS(vga_dev, bus, slot, func);
+
+ get_revision_id_tnc(context, vga_dev, platform_context->pcidev1);
+
+ /*
+ * Read BSM.
+ * This must be in query so it is available early for the vBIOS.
+ */
+ if(OS_PCI_READ_CONFIG_32(vga_dev,
+ TNC_PCI_BSM, &context->device_context.fb_adr)) {
+ EMGD_ERROR_EXIT("Reading BSM");
+ return -IGD_ERROR_NODEV;
+ }
+ context->device_context.fb_adr &= 0xFFFFF000;
+
+ EMGD_DEBUG("BSM (High)@: 0x%lx, (Low) 0x%4lx",
+ (context->device_context.fb_adr >> 16), context->device_context.fb_adr);
+
+ /*
+ * Read IO Base.
+ * This must be in query so it is available early for the vBIOS.
+ */
+ if(OS_PCI_READ_CONFIG_16(vga_dev, TNC_PCI_IOBAR, &io_base)) {
+ EMGD_ERROR_EXIT("Reading IO Base");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Base Address is defined in Bits 15:3*/
+ io_base_lvds = io_base &= 0xfff8;
+ EMGD_DEBUG("io @: 0x%x", io_base);
+
+ /* Gen4 is always io_mapped */
+ io_mapped_lvds = io_mapped = 1;
+
+ /* Set dev3 iobase. */
+ if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->pcidev1,
+ TNC_PCI_IOBAR, &io_base_sdvo)) {
+
+ EMGD_ERROR_EXIT("Reading SDVO IO Base");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Base Address is defined in Bits 15:3*/
+ io_base_sdvo &= 0xfff8;
+
+ io_mapped_sdvo = 1;
+ EMGD_DEBUG("sdvo io @: 0x%x", io_base_sdvo);
+
+ /* Set stmicro sdvo iobase. */
+ if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->stbridgedev,
+ TNC_PCI_IOBAR, &io_base_sdvo_st)) {
+
+ EMGD_ERROR_EXIT("Reading SDVO IO Base");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Base Address is defined in Bits 15:3*/
+ io_base_sdvo_st &= 0xfff8;
+
+ io_mapped_sdvo_st = 1;
+ EMGD_DEBUG("STMicro's sdvo io @: 0x%x", io_base_sdvo_st);
+
+ /* Set stmicro gpio sdvo iobase. */
+ if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->stgpiodev,
+ TNC_PCI_IOBAR, &io_base_sdvo_st_gpio)) {
+
+ EMGD_ERROR_EXIT("Reading SDVO IO Base");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Base Address is defined in Bits 15:3*/
+ io_base_sdvo_st_gpio &= 0xfff8;
+
+ io_mapped_sdvo_st_gpio = 1;
+ EMGD_DEBUG("STMicro's gpio io @: 0x%x", io_base_sdvo_st_gpio);
+
+ /* ---------------------------------------------------
+ * Initialize Device 31 : LPC Interface
+ * --------------------------------------------------*/
+ /*
+ * Map the LPC Interface Configuration [D31:F0]GPIO_BAR.
+ * The Atom E6xx LVDS pins are connected to GPIO pins,
+ * accessible using LPC Interface GPIO_BAR. These registers
+ * will later be used to "bit bash" the LVDS DDC signals
+ * SDVO does not need these registers.
+ * VBIOS may need access to these registers
+ */
+
+ platform_context->lpc_dev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_LPC_TNC,
+ 0,
+ 31, /* LPC[D31:F0] */
+ 0,
+ (os_pci_dev_t)0);
+
+ if(!platform_context->lpc_dev){
+ /*
+ * We could not detect the LPC interface in the PCI Bus. This will
+ * be a problem. Sound the alarm, return with NO ERROR so that we do
+ * not go and map the GPIO_BAR
+ */
+ EMGD_ERROR_EXIT("Reading GPIO BAR");
+ return 0;
+ }
+
+ /* Set dev31 iobase */
+
+ /* Do not enable LPC device as System BIOS owns and does this */
+
+ /* read the GPIO BAR (OFFSET 44:47) */
+ if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
+ TNC_PCI_GBA, &io_base_lpc)) {
+ EMGD_ERROR_EXIT("Reading LPC GPIO BAR");
+ /* We cannot read the GPIO BAR. It is a problem but we can go on with init
+ * return with NO ERROR*/
+ return 0;
+ }
+
+ io_base_lpc &= 0xffc0;
+
+ io_mapped_lpc = 1;
+ EMGD_DEBUG("lpc io @: 0x%x", io_base_lpc);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int config_tnc(igd_context_t *context,
+ init_dispatch_t *dispatch)
+{
+ unsigned long freq[2];
+ platform_context_tnc_t *platform_context = &platform_context_tnc;
+ unsigned long lbb;
+#ifndef CONFIG_MICRO
+ unsigned int lp_ctrl_reg;
+ unsigned int hp_ctrl_reg;
+ unsigned int ved_cg_dis_reg;
+#endif
+
+ EMGD_TRACE_ENTER;
+
+ OPT_MICRO_CALL(full_config_tnc(context, dispatch));
+
+ /* Get graphics and core frequency param if it exists */
+ if(!get_param_tnc(context, IGD_PARAM_GFX_FREQ,
+ freq)) {
+ context->device_context.gfx_freq = (unsigned short)freq[0];
+ context->device_context.core_freq = (unsigned short)freq[1];
+ }
+
+ /*
+ * FIXME:
+ * Coreclk register above is used to determine some clocking information
+ * there is also a fuse to limit the dclk. More research needed.
+ */
+ /* From KT: Atom E6xx LVDS min and max dot clocks are 19.75 MHz to 79.5 MHz,
+ * Atom E6xx SDVO min and max dot clocks are 25 MHz to 165 MHz */
+ context->device_context.max_dclk = 79500; /* in KHz */
+
+#ifndef CONFIG_MICRO
+ /* This breaks VBIOS LVDS display. If this is truly a workaround for
+ * system BIOS then we need to understand what the system BIOS is going
+ * to do and make sure it doesn't re-break VBIOS. The hp_ctrl_reg write
+ * is the write that actually breaks LVDS display. Tested with BIOS34
+ * which has the P-Unit workaround and LVDS still works.
+ */
+
+ /* This is just a workaround.
+ * GVD.G_LP_Control register is set to default mode for BIT0~BIT3.
+ * GVD.H_HP Control register's BIT1 is set 1.
+ * TODO: Removed this after this is fix in system BIOS.
+ */
+ lp_ctrl_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f4);
+ lp_ctrl_reg |= BIT1;
+ lp_ctrl_reg &= ~(BIT2 | BIT3);
+ EMGD_WRITE32(lp_ctrl_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f4);
+
+ hp_ctrl_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f8);
+ hp_ctrl_reg |= BIT1;
+ EMGD_WRITE32(hp_ctrl_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f8);
+
+ /* This is just a workaround.
+ * GVD.VED_CG_DIS register is set to disable clock gating for BIT16, BIT0~BIT8.
+ * Tested with Punit B0_500309_CFG2 and Punit C0_060510_CFG2 in BIOS39 and
+ * BIOS41 or above.
+ */
+ ved_cg_dis_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x2064);
+ ved_cg_dis_reg |= (BIT16 | BIT8 | 0xFF);
+ EMGD_WRITE32(ved_cg_dis_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x2064);
+
+ /* read out the fuse values */
+ dump_fuse_values( );
+#endif
+
+ gtt_init_tnc(context);
+
+ /*
+ * Setting the LBB to 0xFF if it is 0.
+ * This register is used to dynamic LVDS backlight control. By default,
+ * the register will reset to 0x0, this will cause the LVDS to be "off" when
+ * PD_ATTR_ID_BLM_LEGACY_MODE attribute is set. Customers could write
+ * application to set this register.
+ *
+ * TODO: The right way to fix this is to check for the attribute in lvds.c
+ * then set the register through pd. But this will add more code to VBIOS
+ * (as we need to add dispatch functions in pd)
+ */
+
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0, 0xF4, &lbb)) {
+ EMGD_DEBUG("Reading Legacy Backlight Brightness");
+ return -IGD_ERROR_NODEV;
+ }
+ if(!(lbb & 0xFF)){
+ if(OS_PCI_WRITE_CONFIG_32(platform_context->pcidev0,
+ 0xF4, (lbb | 0xFF))){
+ EMGD_DEBUG("Writing into Legacy Backlight Brightness");
+ return -IGD_ERROR_INVAL;
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_param_tnc(igd_context_t *context, unsigned long id,
+ unsigned long *value)
+{
+#define FB_SKU_MASK (BIT12|BIT13|BIT14)
+#define FB_SKU_SHIFT 12
+#define FB_GFX_CLOCK_DIVIDE_MASK (BIT20|BIT21|BIT22)
+#define FB_GFX_CLOCK_DIVIDE_SHIFT 20
+
+ int ret = 0;
+ unsigned long control_reg;
+ unsigned short sku;
+ unsigned short ratio;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("ID: 0x%lx", id);
+
+ /* Scratch registers used as below:
+ *
+ * 0x71410:
+ * --------
+ * Bits 31-16 - EID Firmware identifier 0xE1DF
+ * Bits 15-00 - Tell what data is present.
+ * Here are bits for what we are using know:
+ * Bit 0 - Panel id
+ * Bit 1 - List of ports for which displays are attached
+ * Bit 2 - Memory reservation
+ * If any of the above bits is set that mean data is followed
+ * in the next registers.
+ *
+ * 0x71414:
+ * --------
+ * Bits 07-00 - Panel Id
+ * Bits 11-08 - Port list
+ * Information for Port list: If any of the bit is set means,
+ * a display is attached to that port as follows:
+ * Bit 08 - CRT
+ * Bit 09 - DVOA/Internal LVDS
+ * Bit 10 - DVOB/RGBA
+ * Bit 11 - DVOC
+ *
+ * 0x71418:
+ * --------
+ * Bits 15-00 - Reserved Memory value in number of 4k size pages
+ */
+ *value = 0;
+
+ switch(id) {
+ case IGD_PARAM_PORT_LIST:
+
+ control_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) +
+ 0x71410);
+
+ /*
+ * Verify that the Embedded Firware is present.
+ */
+ if ((control_reg>>16) != 0xE1DF) {
+ EMGD_DEBUG("Exit No Embedded vBIOS found");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * If the port list bit is set in control register,
+ * read the port list
+ */
+ if (control_reg & 0x2) {
+ unsigned char temp;
+ int i = 0;
+
+ temp = (unsigned char)((EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x71414)>>8) & 0xFF);
+ EMGD_DEBUG("Connected Port Bits: 0x%x", temp);
+
+ /*
+ * The meanings of bits in temp were dictated by VBIOS
+ * and should not change due to backward compatibility
+ * with Legacy VBIOS
+ */
+ if (temp & 0x02) {
+ /* Internal LVDS port */
+ value[i++] = 4;
+ }
+ if (temp & 0x04) {
+ /* DVOB Port */
+ value[i++] = 2;
+ }
+ } else {
+ EMGD_DEBUG("Port List read failed: Incorrect Operation");
+ ret = -IGD_ERROR_INVAL;
+ }
+ break;
+ case IGD_PARAM_GFX_FREQ:
+
+ /* Read the fuse value */
+ if(query_sch_message(READ_FUS_EFF3, &control_reg)){
+ EMGD_ERROR("Cannot read GFX clock");
+ }
+ EMGD_DEBUG("SKU [reg 0x%x] value = 0x%lx", READ_FUS_EFF3, control_reg);
+
+ /*
+ * Sku and Ratio bits determine the gfx clock speed
+ * sku - 0:sku_100 1:sku_100L 2:sku_83
+ * ratio - 0-1:1 1-4:3 2-8:5 3-2:1 4-16:7(rsvd) 5-8:3 6-16:5 7:4:1(rsvd)
+ */
+ sku = (unsigned short)((control_reg & FB_SKU_MASK) >> FB_SKU_SHIFT) & 0x3;
+ ratio = (unsigned short)((control_reg & FB_GFX_CLOCK_DIVIDE_MASK) >> FB_GFX_CLOCK_DIVIDE_SHIFT) & 0x7;
+
+ EMGD_DEBUG("sku = 0x%x Ratio = 0x%x", sku, ratio);
+
+ if(sku < SKU_NO && ratio < RATIO_NO){
+ /* get the graphics clock speed from the sku-ratio array */
+ value[0] = tnc_gfx_freq_list[ratio][sku];
+ value[1] = tnc_core_freq_list[sku];
+ } else {
+ EMGD_ERROR("tnc_gfx_freq_list ARRAY OUT OF RANGE");
+ /* set to the lowest default value */
+ value[0] = 333;
+ value[1] = 166;
+ }
+
+ EMGD_DEBUG("TNC GFX core frequency = %lu MHz", value[0]);
+ EMGD_DEBUG("TNC Core clock frequency = %lu MHz", value[1]);
+
+ break;
+
+ default:
+ /* If the param is not found here then it may only be in the
+ * full version.
+ */
+ OPT_MICRO_CALL_RET(ret, full_get_param_tnc(context, id, value));
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL
+ */
+static int set_param_tnc(igd_context_t *context, unsigned long id,
+ unsigned long value)
+{
+ return 0;
+}
+
+/*!
+ * Functions reads all the fuse values and dumps out the value
+ * @return -IGD_ERROR_INVAL
+ */
+#ifndef CONFIG_MICRO
+static int dump_fuse_values(void)
+{
+ unsigned long value = 0;
+
+ if(query_sch_message(READ_FUS_EFF0, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF0 [%lx]", value);
+
+ if(query_sch_message(READ_FUS_EFF1, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF1 [%lx]", value);
+
+ if(query_sch_message(READ_FUS_EFF2, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF2 [%lx]", value);
+
+ if(query_sch_message(READ_FUS_EFF3, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF3 [%lx]", value);
+
+ if(query_sch_message(READ_FUS_EFF4, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF4 [%lx]", value);
+
+ if(query_sch_message(READ_FUS_EFF5, &value)){
+ EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+ }
+ EMGD_DEBUG("READ_FUS_EFF5 [%lx]", value);
+
+ return 0;
+}
+#endif
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void shutdown_tnc(igd_context_t *context)
+{
+ gtt_shutdown_tnc(context);
+
+ OPT_MICRO_VOID_CALL(full_shutdown_tnc(context));
+}
+
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+int get_revision_id_tnc(igd_context_t *context,
+ os_pci_dev_t vga_dev,
+ os_pci_dev_t sdvo_dev)
+{
+ platform_context_tnc_t *platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+
+ /* Read RID */
+ if(OS_PCI_READ_CONFIG_8(vga_dev, PCI_RID,
+ (unsigned char *)&context->device_context.rid)) {
+ EMGD_ERROR_EXIT("Error occured reading RID");
+ return -IGD_ERROR_NODEV;
+ }
+
+ if(OS_PCI_READ_CONFIG_8(sdvo_dev, PCI_RID,
+ &platform_context->tnc_dev3_rid)) {
+ EMGD_ERROR_EXIT("Error occured reading TNC SDVO RID");
+ return -IGD_ERROR_NODEV;
+ }
+
+ EMGD_DEBUG(" rid = 0x%lx", context->device_context.rid);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
new file mode 100755
index 0000000..38641fc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
@@ -0,0 +1,2368 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp.c
+ * $Revision: 1.27 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains all the necessary functions for display resource
+ * manager. This module abstracts all hardware resources and manages them.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dsp
+
+#include <config.h>
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_errno.h>
+#include <igd_gmm.h>
+
+#include <context.h>
+#include <utils.h>
+#include <intelpci.h>
+#include <dsp.h>
+#include <debug.h>
+#include <dispatch.h>
+#include <pd.h>
+#include <mode.h>
+#include <pd_init.h>
+#include <gart.h>
+
+#include "dsp_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+static dispatch_table_t dsp_dispatch_list[] = {
+
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &dsp_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &dsp_dispatch_tnc},
+#endif
+ {0, NULL}
+};
+
+static int dsp_full_init(igd_context_t *context);
+static int dsp_init_cursor(igd_context_t *context, igd_cursor_t *cursor);
+static igd_display_port_t *dsp_get_next_port(igd_context_t *context,
+ igd_display_port_t *last, int reverse);
+
+/*
+ * This simple structure wraps the display configuration list so that
+ * it is easier to manipulate.
+ * count is the current number of items in the list.
+ * size is the maximum number of items the list can hold
+ * dc_list is a pointer to the array of DC's
+ */
+typedef struct _dsp_dc_list_t {
+ int count;
+ int size;
+ unsigned long *dc_list;
+} dsp_dc_list_t;
+
+typedef struct _dsp_context {
+
+ dsp_dispatch_t *dispatch;
+ igd_context_t *context;
+ unsigned long num_dsp_planes;
+ unsigned long num_dsp_pipes;
+ unsigned long display_flags;
+
+ unsigned long current_dc;
+ unsigned long fw_dc; /* The DC programmed by the EFI or VBIOS */
+ igd_display_context_t display_list[MAX_DISPLAYS];
+ dsp_dc_list_t dsp_dc_list;
+ /* holds pointer to port based on port numbers (1 based not zero based) */
+ igd_display_port_t *port_list[IGD_MAX_PORTS + 1];
+
+ /* holds pointer to display context based on port numbers
+ * (1 based not zero based) */
+ igd_display_context_t *display_ptr_list[IGD_MAX_PORTS + 1];
+} dsp_context_t;
+
+static dsp_context_t dsp_context;
+
+
+#ifndef CONFIG_MICRO
+#define FREE_PIPE(x) free_pipe(x)
+
+
+/*
+ * This macro is used to check the validity of a clone/extended DC. It
+ * makes sure that the ports are capable of using both pipes. p1 and
+ * p2 need to be on unique pipes, if they both require the same pipe,
+ * this check returns false.
+ *
+ * Note that this is only enabled for the driver since it does add some
+ * code and currently we have no hardware that could be configured like
+ * this.
+ */
+#define DSP_PIPE_OK(p1, p2) ( \
+ ((p1->port_features & IGD_PORT_USE_PIPE_MASK) | \
+ (p2->port_features & IGD_PORT_USE_PIPE_MASK)) == \
+ (IGD_PORT_USE_PIPEA | IGD_PORT_USE_PIPEB))
+
+#else
+#define FREE_PIPE(x)
+#define DSP_PIPE_OK(p1, p2) 1
+#endif
+
+/*
+ * Static framebuffer structures used for all chipsets.
+ */
+igd_framebuffer_info_t fb_info_cmn[2] = {
+ {0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/* Design Notes:
+ *
+ * 1. The heart of display resources is the display configuration list.
+ * During initialization, the list display configuration list is
+ * created with all valid pipe/plane/port combinations. Allocations
+ * are limited to combinations specified on the list.
+ *
+ * 2. Two display handles are maintaine corresponding to the two
+ * display pipes. To support hardware with more than two pipes,
+ * the DC value will need to expand beyond the current 32 bit value
+ * and the number of display handles increased appropriately.
+ */
+
+#ifndef CONFIG_MICRO /* This is N/A for VBIOS */
+
+/*!
+ * Re-construct the DC ( Display Configuration ) that the Gfx hardware
+ * was programmed by Video BIOS or EFI Video Driver.
+ *
+ * TODO: This function does not handle three-display scenario.
+ *
+ * @param context
+ *
+ * @return fw_dc
+ */
+static unsigned long dsp_get_fw_dc(igd_context_t *context)
+{
+ igd_display_port_t *p = NULL;
+ int pipeb_allocated = 0, pipea_allocated = 0;
+ int port1 = 0, port2 = 0, mode = 0;
+ int port_allocated = 0;
+ unsigned long port_value;
+ unsigned long fw_dc = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Go through the port table */
+ while ((p = dsp_get_next_port(context, p, 0)) != NULL) {
+
+ port_value = dsp_context.context->mod_dispatch.get_port_control(p->port_number, p->port_reg);
+ EMGD_DEBUG("port number = %lx, port reg = %lx, value = %lx", p->port_number, p->port_reg, port_value);
+ if(port_value & BIT(31)) { /* is the port ON? */
+
+ if(port1) {
+ port2 = p->port_number;
+ } else {
+ port1 = p->port_number;
+ }
+ port_allocated++;
+
+ if (port_value & BIT(30)) {
+ pipeb_allocated++;
+ } else {
+ pipea_allocated++;
+ }
+ }
+ } /* while */
+
+ if( pipea_allocated > 1 || pipeb_allocated > 1) {
+ /* Twin Mode */
+ EMGD_DEBUG("Twin mode");
+ mode = IGD_DISPLAY_CONFIG_TWIN;
+
+ /* Re-construct the DC back */
+ fw_dc = (port2 & 0x0F)<< 8 | (port1 & 0x0F)<< 4 | (mode & 0x0F);
+
+ EMGD_DEBUG("fw_dc in Twin Mode: 0x%08lx", fw_dc);
+
+ /* Check the fw_dc is in the list */
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("check the fw_dc again in the DC list");
+
+ /* If the assumed dc doesn't match reverse the order and
+ * and check again
+ */
+ fw_dc = (port1 & 0x0F)<< 8 | (port2 & 0x0F)<< 4 | (mode & 0x0F);
+ EMGD_DEBUG("hw_dc: 0x%08lx", fw_dc);
+
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("FW DC doesnt match dc list!!");
+ fw_dc = 0L;
+ }
+ }
+
+ } else if(port_allocated == 1) {
+
+ EMGD_DEBUG("Single Configuration");
+ mode = IGD_DISPLAY_CONFIG_SINGLE;
+ /* Single Mode */
+ fw_dc = (port2 & 0x0F)<< 20 |(port1 & 0x0F)<<4 |(mode & 0x0F);
+
+ EMGD_DEBUG("fw_dc in Single Config = 0x%08lx", fw_dc);
+
+ /* Checking the assumed dc with the dc list */
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("check again");
+
+ /* If the assumed dc doesn't match reverse the order and
+ * and check again
+ */
+ fw_dc = (port1 & 0x0F)<< 20 |(port2 & 0x0F)<<4 |(mode & 0x0F);
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("FW DC doesnt match dc list!!!");
+ fw_dc = 0L;
+ }
+ }
+
+ } else {
+
+ /* VBIOS does not support extended. So i'ts most
+ * likely clone.
+ */
+ EMGD_DEBUG("Extended/Clone");
+ mode = IGD_DISPLAY_CONFIG_CLONE;
+
+ /* Re-construct the DC back */
+ fw_dc = (port2 & 0x0F) << 20 | (port1 & 0x0F) << 4 | (mode & 0x0F);
+
+ EMGD_DEBUG("fw_dc in Clone Mode:a 0x%08lx", fw_dc);
+
+ /* Check the fw_dc is in the list */
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("Check again. This time reverse primary and secondary");
+
+ /* if the assumed dc doesn't match reverse the order and
+ * check again
+ */
+ fw_dc = (port1 & 0x0F) << 20 | (port2 & 0x0F) << 4 | (mode & 0x0F);
+ if(!dsp_valid_dc(fw_dc, 0)) {
+ EMGD_DEBUG("FW DC doesnot match dc list!!!");
+ fw_dc = 0L;
+ }
+ }
+ } /* else */
+
+ EMGD_DEBUG("DC programmed by the firmware = 0x%08lx", fw_dc);
+ EMGD_TRACE_EXIT;
+ //*dc_list=¤t_dc;
+ return fw_dc;
+
+} /* end of dsp_get_fw_dc */
+
+#endif /* ifndef CONFIG_MICRO */
+
+/*!
+ * This function gets the next value in a plane, pipe, or port table. The
+ * caller provides a pointer to the last entry retrieved or NULL to get
+ * the first entry.
+ *
+ * @param list
+ * @param last
+ * @param reverse
+ *
+ * @return void
+ */
+static void *dsp_get_next(void **list, void *last, int reverse)
+
+{
+ void **list_end = list;
+ void **list_start = list;
+ void **last_p = NULL;
+ int off = 1;
+
+ while(*list_end) {
+ if(*list_end == last) {
+ last_p = list_end;
+ }
+ list_end++;
+ }
+ list_end--;
+
+ if(reverse) {
+ list_start = list_end;
+ list_end = list;
+ off = -1;
+ }
+ if(!last) {
+ return *list_start;
+ }
+ if((last == *list_end) || !last_p) {
+ return NULL;
+ }
+ return last_p[off];
+}
+
+/*!
+ * This function allows the caller to loop through the (port | plane | pipe)
+ * table list and get each entry in turn. The call must provide a pointer
+ * to the last entry retrieved (or NULL to get the first port).
+ *
+ * These functions are called from many places, including some functions
+ * external to the DSP module.
+ *
+ * @param context pointer to the current driver context.
+ * @param last pointer to the last entry retrieved.
+ * @param reverse
+ *
+ * @return igd_display_port_t pointer to the next entry or NULL if no more ports available.
+ */
+static igd_display_port_t *dsp_get_next_port(igd_context_t *context,
+ igd_display_port_t *last, int reverse)
+{
+ /*EMGD_DEBUG("Entry, dsp_get_next_port");*/
+
+ return (igd_display_port_t *)dsp_get_next(
+ (void **)dsp_context.dispatch->ports, (void *)last, reverse);
+}
+
+static igd_plane_t *dsp_get_next_plane(igd_context_t *context,
+ igd_plane_t *last, int reverse)
+{
+ EMGD_DEBUG("Entry, dsp_get_next_plane");
+
+ return (igd_plane_t *)dsp_get_next(
+ (void **)dsp_context.dispatch->planes, (void *)last, reverse);
+}
+
+static igd_display_pipe_t *dsp_get_next_pipe(igd_context_t *context,
+ igd_display_pipe_t *last, int reverse)
+{
+ EMGD_DEBUG("Entry, dsp_get_next_pipe");
+
+ return (igd_display_pipe_t *)dsp_get_next(
+ (void **)dsp_context.dispatch->pipes, (void *)last, reverse);
+}
+
+/*!
+ * Check the DC to see if it is in the list.
+ *
+ * Flags:
+ * IGD_DC_EXACT_MATCH
+ * IGD_DC_CLOSEST_MATCH
+ *
+ * Flags are currently ignored.
+ *
+ * @param dc
+ * @param flags
+ *
+ * @return DC
+ * @return 0 if no match
+ */
+unsigned long dsp_valid_dc(unsigned long dc, unsigned long flags)
+{
+ int i;
+
+ for (i = 0; i < dsp_context.dsp_dc_list.count; i++) {
+ if (dc == dsp_context.dsp_dc_list.dc_list[i]) {
+ return dsp_context.dsp_dc_list.dc_list[i];
+ }
+ }
+
+ /* Need to define how a closest match is determined */
+
+ return 0;
+}
+
+/*!
+ * Convert a DC value into to bitmasks, one for each pipe.
+ *
+ * @param dc
+ * @param pipe1
+ * @param pipe2
+ *
+ * @return void
+ */
+static void dsp_dc_to_masks(unsigned long dc,
+ unsigned char *pipe1,
+ unsigned char *pipe2)
+{
+ int i;
+ int pn;
+
+ *pipe1 = 0;
+ *pipe2 = 0;
+
+ for (i = 1; i < 8; i++) {
+ if ((pn = DC_PORT_NUMBER(dc, i)) > 0) {
+ if ((i < 5)) {
+ *pipe1 |= (1 << pn);
+ } else {
+ *pipe2 |= (1 << pn);
+ }
+ }
+ }
+}
+
+/*!
+ *
+ * @param context
+ * @param port
+ *
+ * @return 1 if connected
+ * @return 0 if not connected
+ */
+int dsp_display_connected(igd_context_t *context,
+ igd_display_port_t *port)
+{
+ unsigned long port_list[IGD_MAX_PORTS];
+ unsigned long connected_ports;
+ int ret;
+ pd_port_status_t port_status;
+
+ /* Display detection -
+ * First, check if the VBIOS has provided the "connected_bits"
+ * information. If it has, then check if the passed in port is in
+ * the list. Of course, this is only valid in the driver, vBIOS
+ * can't check vBIOS bits.
+ *
+ * If there isn't any "connected_bits" info, then have the port
+ * driver try and detect the display. If the display is detected
+ * or if the port driver is incapabile of doing display detection,
+ * then return connected.
+ */
+ OS_MEMSET(port_list, 0, sizeof(unsigned long) * IGD_MAX_PORTS);
+ connected_ports = 0;
+ if (igd_get_param((igd_driver_h)context, IGD_PARAM_PORT_LIST,
+ port_list) == 0) {
+ while ((connected_ports < IGD_MAX_PORTS) &&
+ port_list[connected_ports]) {
+ if(port_list[connected_ports] == port->port_number) {
+ return 1;
+ }
+ connected_ports++;
+ }
+ return 0;
+ }
+
+ /* No vBIOS info, so do runtime detection if possible. */
+ if (port->pd_context == NULL) {
+ return 0;
+ }
+
+ ret = port->pd_driver->pd_get_port_status(port->pd_context, &port_status);
+ if ((ret != PD_SUCCESS) ||
+ (port_status.connected == PD_DISP_STATUS_DETACHED)) {
+ return 0;
+ }
+
+ /* Port is connected (as far as we can tell) and OK to use */
+ return 1;
+}
+
+/*!
+ * Checks a given port to make sure it is ok to use it in a
+ * display configuration. Two things can make a port unusable.
+ * First it can be marked inuse, which means it isn't listed in
+ * the current port_order.
+ * Second, if display detect is enabled and no display is detected.
+ *
+ * @param context
+ * @param port
+ * @param display_detect
+ *
+ * @return 0 if not ok to use
+ * @return 1 if ok to use
+ */
+static int dsp_port_is_ok(igd_context_t *context,
+ igd_display_port_t *port,
+ int display_detect)
+{
+ /*
+ * The port->inuse value is used in two different ways. This is
+ * causing a conflict now.
+ *
+ * - It is set if the port doesn't show up in the port order.
+ * - It is set if the port is allocated by dsp_alloc()
+ *
+ * This is ok if this function is called prior to any dsp_alloc's
+ *
+ * Maybe what is really needed here is a check to see if the port
+ * shows up in the port order.
+ */
+
+ /* If it is inuse, then it isn't currently ok to use */
+ if (port->inuse == 0x80) {
+ EMGD_DEBUG("port_ok? Port is marked unsable");
+ return 0;
+ }
+
+ /* Does port have a port driver? */
+ if (port->pd_driver == NULL) {
+ EMGD_DEBUG("port %ld has no port driver", port->port_number);
+ return 0;
+ }
+
+ /* If display detect, then check to make sure display is present */
+ if (display_detect) {
+ return dsp_display_connected(context, port);
+ }
+ return 1;
+}
+
+/*!
+ * Add a new DC to the end of the list. Checks to make sure there is
+ * space in the allocated list first.
+ *
+ * @param dc_list
+ * @param dc
+ * @param ext
+ *
+ * @return void
+ */
+void dsp_add_to_dc_list(dsp_dc_list_t *dc_list, unsigned long dc,
+ unsigned long ext)
+{
+ unsigned char pipe1, pipe2;
+ unsigned char p1, p2;
+ int d;
+ int ok = 1;
+
+ /* Check for duplicate DC first */
+ if ((dc_list->count != 0) && (dc != 0)) {
+ dsp_dc_to_masks(dc, &pipe1, &pipe2);
+ for (d = 0; d < dc_list->count; d++) {
+ /* build a bitmap of port used by DC under test */
+ dsp_dc_to_masks(dc_list->dc_list[d], &p1, &p2);
+
+ /*
+ * Compare the bitmaps.
+ *
+ * There are two bitmaps, one for each pipe. This is needed so
+ * 0x00500232 and 0x00200532 aren't flaged as duplicate.
+ */
+ if ((pipe1 == p1) && (pipe2 == p2)) {
+ ok = 0; /* duplicate */
+ }
+ if ((pipe1 == p2) && (pipe2 == p1)) {
+ ok = 0; /* a pipe reversed duplicate DC */
+ }
+ }
+ }
+
+ if (ok) {
+ if (dc_list->count < dc_list->size) {
+ dc_list->dc_list[dc_list->count] = dc;
+ dc_list->count++;
+ }
+ if (ext && (dc_list->count < dc_list->size)) {
+ dc = (dc & 0xfffffff0) | 8;
+ dc_list->dc_list[dc_list->count] = dc;
+ dc_list->count++;
+ }
+ }
+}
+
+/*!
+ * Given a port number, find which display context currently controls
+ * that port.
+ *
+ * @param port_number
+ * @param display
+ * @param port
+ * @param display_detect
+ *
+ * @return void
+ */
+static void dsp_get_display(unsigned short port_number,
+ igd_display_context_t **display,
+ igd_display_port_t **_port,
+ int display_detect)
+{
+ igd_display_port_t *port = NULL;
+
+ if(_port) {
+ while ((port = dsp_get_next_port(dsp_context.context, port, 0))) {
+ if (port->port_number == port_number) {
+ *_port = port;
+ if (display_detect &&
+ (dsp_display_connected(dsp_context.context, port) != 1)) {
+ EMGD_DEBUG("Usable but unattached port found");
+ *_port = NULL;
+ }
+ break;
+ }
+ }
+ }
+ if(display) {
+ *display = dsp_context.display_ptr_list[port_number];
+ }
+ return;
+}
+
+/*!
+ *
+ * @param dc
+ * @param primary
+ * @param secondary
+ *
+ * @return void
+ */
+static void dsp_get_dc(unsigned long *dc,
+ igd_display_context_t **primary,
+ igd_display_context_t **secondary)
+{
+ /*EMGD_TRACE_ENTER;*/
+ if(dc) {
+ *dc = dsp_context.current_dc;
+ }
+ if(primary) {
+ *primary =
+ dsp_context.display_ptr_list[
+ IGD_DC_PRIMARY(dsp_context.current_dc)];
+ }
+ if(secondary) {
+ *secondary =
+ dsp_context.display_ptr_list[
+ IGD_DC_SECONDARY(dsp_context.current_dc)];
+ }
+ /*EMGD_TRACE_EXIT;*/
+}
+
+/*!
+ *
+ * @param primary_display_plane
+ * @param secondary_display_plane
+ * @param primary_pipe
+ * @param secondary_pipe
+ *
+ * @return void
+ */
+static void dsp_get_planes_pipes(igd_plane_t **primary_display_plane,
+ igd_plane_t **secondary_display_plane,
+ igd_display_pipe_t **primary_pipe,
+ igd_display_pipe_t **secondary_pipe)
+{
+ igd_plane_t **plane;
+ igd_display_pipe_t **pipe;
+ int is_primary = 1;
+
+ EMGD_TRACE_ENTER;
+
+ if(!primary_display_plane || !secondary_display_plane ||
+ !primary_pipe || !secondary_pipe) {
+
+ EMGD_ERROR("Invalid parameters");
+ } else {
+
+ plane = dsp_context.dispatch->planes;
+
+ while (*plane) {
+ if ((*plane)->plane_features & IGD_PLANE_DISPLAY) {
+
+ if(is_primary) {
+ *primary_display_plane = *plane;
+ is_primary = 0;
+ } else {
+ *secondary_display_plane = *plane;
+ break;
+ }
+ }
+ plane++;
+ }
+
+ pipe = dsp_context.dispatch->pipes;
+ is_primary = 1;
+
+ while (*pipe) {
+ if(is_primary) {
+ *primary_pipe = *pipe;
+ is_primary = 0;
+ } else {
+ *secondary_pipe = *pipe;
+ break;
+ }
+ pipe++;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+static void dsp_control_plane_format(int enable, int display_plane, igd_plane_t *plane_override)
+{
+ EMGD_TRACE_ENTER;
+
+ dsp_context.dispatch->dsp_control_plane_format(dsp_context.context,
+ enable, display_plane, plane_override);
+
+ dsp_context.context->mod_dispatch.fb_blend_ovl_override = 1;
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * Check port features of multiple ports to see if they can share a pipe.
+ * Ports that are passed in as NULL are not considered. There must be
+ * at least two ports.
+ *
+ * Sort the ports so that any port that must be pipe master is listed
+ * first. Return the sorted port order in a format that can be easily
+ * merged into a full DC value.
+ *
+ * @param m
+ * @param p1
+ * @param p2
+ * @param p3
+ *
+ * @return 0 if error
+ * @return DC
+ */
+unsigned long dsp_shareable(igd_display_port_t *m,
+ igd_display_port_t *p1,
+ igd_display_port_t *p2,
+ igd_display_port_t *p3)
+{
+ unsigned long features;
+ unsigned long shareable;
+ unsigned long dc;
+
+ if (m == NULL) {
+ /* Error checking */
+ EMGD_ERROR("dsp_shareable: port pointer is NULL.");
+ return 0;
+ }
+
+ if (p1 == NULL) {
+ dc = m->port_number;
+ return dc;
+ }
+
+ /*
+ * OR all the port secondary port type bits together.
+ * If ANDing this with the primary port's feature bits changes
+ * the value, then all the ports are not shareable.
+ *
+ * This does assume that if port A can share with port B,
+ * then port B can share with port A.
+ */
+ features = m->port_features & IGD_PORT_SHARE_MASK;
+ shareable = (p1->port_type & IGD_PORT_SHARE_MASK);
+ if (p2 != NULL) {
+ shareable |= (p2->port_type & IGD_PORT_SHARE_MASK);
+ if (p3 != NULL) {
+ shareable |= (p3->port_type & IGD_PORT_SHARE_MASK);
+ }
+ }
+
+ /* make features a true/false type value */
+ features = ((features & shareable) == shareable);
+
+ /*
+ * This section re-arranges the order of the ports so that the
+ * port that needs to be the pipe master is always listed first.
+ *
+ * FIXME:
+ * This doesn't support the case where more than one port must
+ * be pipe master.
+ *
+ * FIXME:
+ * Not sure if this is handling CLOCK_MASTER correctly. CLOCK_MASTER
+ * can share a pipe with other ports but wants the PLL to be programmed
+ * with its clock.
+ */
+ if (features) {
+ dc = m->port_number;
+ if (p1->pd_flags & PD_FLAG_PIPE_MASTER) {
+ dc = (dc << 4) | p1->port_number;
+ } else if (p1->pd_flags & PD_FLAG_CLOCK_MASTER) {
+ dc = (dc << 4) | p1->port_number;
+ } else {
+ dc = dc | (p1->port_number << 4);
+ }
+ if (p2 != NULL) {
+ if (p2->pd_flags & PD_FLAG_PIPE_MASTER) {
+ dc = (dc << 4) | p2->port_number;
+ } else if (p2->pd_flags & PD_FLAG_CLOCK_MASTER) {
+ dc = (dc << 4) | p2->port_number;
+ } else {
+ dc = dc | (p2->port_number << 8);
+ }
+ }
+ if (p3 != NULL) {
+ if (p3->pd_flags & PD_FLAG_PIPE_MASTER) {
+ dc = (dc << 4) | p3->port_number;
+ } else if (p3->pd_flags & PD_FLAG_CLOCK_MASTER) {
+ dc = (dc << 4) | p3->port_number;
+ } else {
+ dc = dc | (p3->port_number << 12);
+ }
+ }
+ return dc;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * Given a group of ports and some basic infomation like how many pipes
+ * are available, construct a set of valid display configurations. The
+ * number of ports passed in is variable so that if a port doesn't exist
+ * it should be passed in as a NULL. At least one port must be passed
+ * in. Also, NULL ports should be at the end of the list. Don't pass in
+ * NULL, NULL, NULL, vaid_port because it will break this function.
+ *
+ * The flags value is used to enabled dual pipe support and extended
+ * support. If neither are set, only TWIN configurations will be returned.
+ *
+ * @param m
+ * @param t1
+ * @param t2
+ * @param t3
+ * @param flags
+ * @param dc_list
+ *
+ * @return void
+ */
+void dsp_build_display_configs(igd_display_port_t *m,
+ igd_display_port_t *t1,
+ igd_display_port_t *t2,
+ igd_display_port_t *t3,
+ unsigned long flags, dsp_dc_list_t *dc_list)
+{
+
+ unsigned long dc, dc2;
+
+ /* If two pipes, do all clone/extended configurations first */
+ if ((flags & 0x0f) > 1) {
+ /* first two ports on different pipes, all remaining ports on pipe 2 */
+ /* can port 0 share with port1 and port 2 */
+ if ((dc = dsp_shareable(t1, t2, t3, NULL)) && DSP_PIPE_OK(m, t1)) {
+ dc = (dc << 20) | 2 | ((m->port_number & 0x0f) << 4);
+ dsp_add_to_dc_list(dc_list, dc, (flags & IGD_PLANE_DIH));
+ }
+ /* first two ports on different pipes, all remaining ports on pipe 1 */
+ if ((dc = dsp_shareable(m, t2, t3, NULL)) && DSP_PIPE_OK(m, t1)) {
+ dc = (dc << 4) | 2 | ((t1->port_number & 0x0f) << 20);
+ dsp_add_to_dc_list(dc_list, dc, (flags & IGD_PLANE_DIH));
+ }
+
+ /* first two ports on different pipes, remianing ports split */
+ if ((dc = dsp_shareable(m, t2, NULL, NULL)) &&
+ (dc2 = dsp_shareable(t1, t3, NULL, NULL)) &&
+ DSP_PIPE_OK(m, t1)) {
+ dc = (dc << 4) | 2 | (dc2 << 20);
+ dsp_add_to_dc_list(dc_list, dc, (flags & IGD_PLANE_DIH));
+ }
+
+ /* first two ports on different pipes, remianing ports split */
+ if ((dc = dsp_shareable(m, t3, NULL, NULL)) &&
+ (dc2 = dsp_shareable(t1, t2, NULL, NULL)) &&
+ DSP_PIPE_OK(m, t1)) {
+ dc = (dc << 4) | 2 | (dc2 << 20);
+ dsp_add_to_dc_list(dc_list, dc, (flags & IGD_PLANE_DIH));
+ }
+ }
+
+ /* Twinned type configurations, all ports on first pipe */
+ if ((dc = dsp_shareable(m, t1, t2, t3))) {
+ dc = (dc << 4) | 4;
+ dsp_add_to_dc_list(dc_list, dc, 0);
+ }
+}
+
+/*!
+ * This routine puts the port table entries as per user (via IAL) mentioned
+ * port order & firmware settings.
+ *
+ * @param context
+ * @param port_order
+ *
+ * @return void
+ */
+void do_port_order(igd_context_t *context, unsigned long *port_order)
+{
+ igd_display_port_t **port_table;
+ igd_display_port_t *p;
+ unsigned long i, j, k, num_ports;
+ unsigned long num_ports1;
+
+ /* Adjust port detect/allocation order with user/caller preference */
+ port_table = dsp_context.dispatch->ports;
+ num_ports = 0;
+ while (port_table[num_ports]) {
+ /* Build a port number to port array */
+ dsp_context.port_list[port_table[num_ports]->port_number] =
+ port_table[num_ports];
+ num_ports++;
+ }
+
+#if 0
+ EMGD_DEBUG("Initial port table = ");
+ for (i = 0; i < num_ports; i++) {
+ EMGD_DEBUG("\t%ld, inuse=%d", port_table[i]->port_number,
+ port_table[i]->inuse);
+ }
+#endif
+
+ num_ports1 = 0;
+ while ((num_ports1 < IGD_MAX_PORTS) && port_order[num_ports1]) {
+ num_ports1++;
+ }
+
+ /*
+ * If port order is specified, then the ports that are not present in the
+ * port order list should not be allowed to be allocated. Since it is not
+ * possible to remove ports from port_table, mark ports that cannot be
+ * allocated as inuse with 0x80. Ports marked in-use by the display
+ * allocation function will set this to 0x01. This is used in the
+ * dsp_dc_init() function to detmine what ports are usable.
+ */
+ if (num_ports1 != 0) {
+ for (i = 0; i < num_ports; i++) {
+ port_table[i]->inuse = 0x80;
+ }
+ } else {
+#ifndef CONFIG_MICRO
+ /* Copying back the port order to the mode_context's port order */
+ for (i = 0; i < num_ports; i++) {
+ port_order[i] = port_table[i]->port_number;
+ }
+#endif
+ return;
+ }
+
+ /* Arrange port_table list to match IAL provided port_order list.
+ * Dont forget to unmark its in-use flag to ensure it's allowed
+ * for usage. */
+ k = 0;
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ /* Find the port for given port number */
+ for (j = k; j < num_ports; j++) {
+ if (port_table[j]->port_number == port_order[i]) {
+ port_table[j]->inuse = 0;
+ p = port_table[k];
+ port_table[k] = port_table[j];
+ port_table[j] = p;
+ k++;
+ break;
+ }
+ }
+ }
+ return;
+} /* end do_port_order() */
+
+/*!
+ *
+ * @param context
+ * @param config_info
+ *
+ * @return 0
+ */
+static int dsp_get_config_info(igd_context_t *context,
+ igd_config_info_t *config_info)
+{
+ EMGD_ASSERT(context, "Null context", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(config_info, "Null config_info", -IGD_ERROR_INVAL);
+
+ config_info->num_dsp_planes = dsp_context.num_dsp_planes;
+ config_info->num_dsp_pipes = dsp_context.num_dsp_pipes;
+ config_info->fb_caps = dsp_context.dispatch->caps;
+
+ return 0;
+}
+
+
+#if 0
+/*!
+ * Print out the DC list for debug purposes
+ *
+ * @param void
+ *
+ * @return void
+ */
+void debug_print_dc_list( void )
+{
+ int i = 0;
+ unsigned long mask;
+ int x, c, d;
+ int port;
+ char tstr[50];
+ char *pname[6];
+
+ pname[0] = "Unused";
+ pname[1] = "TV";
+ pname[2] = "DVOB";
+ pname[3] = "DVOC";
+ pname[4] = "LVDS";
+ pname[5] = "CRT";
+
+ for (d = 0; d < dsp_context.dsp_dc_list.count; d++) {
+ sprintf(tstr, "%3d: ", i);
+ mask = 0x0000000f;
+ c = 0;
+ for (x = 0; x < 7; x++) {
+ mask = mask << 4;
+ port = (dsp_context.dsp_dc_list.dc_list[d] & mask) >> (4 * (x+1));
+ if ((x == 4) && (port != 0)) {
+ strcat(tstr, " + ");
+ c = 0;
+ }
+ if (port != 0) {
+ if (c) {
+ strcat(tstr, ",");
+ }
+ strcat(tstr, pname[port]);
+ c = 1;
+ }
+ }
+ if ((dsp_context.dsp_dc_list.dc_list[d] & 0x0000000f) == 8) {
+ strcat(tstr, "/e");
+ }
+ EMGD_ERROR("%-20s 0x%08lx", tstr, dsp_context.dsp_dc_list.dc_list[d]);
+ i++;
+ }
+}
+#endif
+
+/*!
+ * Build a list of valid display configurations (DC) and store for later
+ * use by the driver.
+ *
+ * @param context
+ *
+ * @return void
+ */
+void dsp_dc_init(igd_context_t *context)
+{
+ igd_display_port_t *p0 = NULL, *p1 = NULL, *p2 = NULL, *p3 = NULL;
+ unsigned long dc_flags;
+ int num_ports;
+ igd_display_port_t **port_table;
+ igd_plane_t **plane;
+ unsigned long display_detect;
+
+ /* Build the display configuration list */
+ dc_flags = dsp_context.num_dsp_pipes & 0x0f;
+
+ /* Check plane features to see if DIH is possible (IGD_PLANE_DIH) */
+ plane = dsp_context.dispatch->planes;
+ if (*plane) {
+ if ((*plane)->plane_features & IGD_PLANE_DIH) {
+ dc_flags |= IGD_PLANE_DIH;
+ }
+ }
+
+ display_detect = (dsp_context.display_flags & IGD_DISPLAY_DETECT)?1:0;
+
+ /*
+ * Given the number of ports and number of pipes can the max number
+ * of DC's be calculated?
+ *
+ * Number of ports squared.
+ * If clone double.
+ * If DIH, double again.
+ */
+
+ /* Find the number of ports */
+ port_table = dsp_context.dispatch->ports;
+ num_ports = 0;
+ while (port_table[num_ports]) {
+ num_ports++;
+ }
+ EMGD_DEBUG("ports = %d, pipes = %ld", num_ports,
+ dsp_context.num_dsp_pipes);
+
+
+ /* If this is the first time called, then allocate memory for the list */
+ if (dsp_context.dsp_dc_list.dc_list == NULL) {
+ dsp_context.dsp_dc_list.size = num_ports * num_ports;
+ if (dsp_context.num_dsp_pipes > 1) {
+ dsp_context.dsp_dc_list.size *= 2;
+ if (dc_flags & IGD_PLANE_DIH) { /* extended modes */
+ dsp_context.dsp_dc_list.size *= 2;
+ }
+ }
+
+ /* Need to allocate memory for list */
+ dsp_context.dsp_dc_list.dc_list =
+ OS_ALLOC(sizeof(unsigned long) * dsp_context.dsp_dc_list.size);
+ }
+ dsp_context.dsp_dc_list.count = 0;
+
+ if (dsp_context.dsp_dc_list.dc_list == NULL) {
+ EMGD_DEBUG("Memory allocation error, can't allocate DC list");
+ return;
+ }
+
+#if 0
+ /* Get all possible one display configs */
+ while ((p0 = dsp_get_next_port(context, p0)) != NULL) {
+ if (dsp_port_is_ok(context, p0, display_detect)) {
+ dsp_add_to_dc_list(&dsp_context.dsp_dc_list,
+ (1 | ((p0->port_number & 0x0f) << 4)), 0);
+ }
+ }
+
+ /* Get all possible two display configs */
+ p0 = NULL;
+ while ((p0 = dsp_get_next_port(context, p0)) != NULL) {
+ p1 = NULL;
+ if (!dsp_port_is_ok(context, p0, display_detect)) {
+ continue; /* skip ports that are inuse (not to be used) */
+ }
+ while ((p1 = dsp_get_next_port(context, p1)) != NULL) {
+ if (!dsp_port_is_ok(context, p1, display_detect) || (p1 == p0)) {
+ continue; /* can't use the same port twice! */
+ }
+ dsp_build_display_configs(p0, p1, NULL, NULL, dc_flags,
+ &dsp_context.dsp_dc_list);
+ }
+ }
+
+ /* Get all possible three display configs */
+ p0 = NULL;
+ while ((p0 = dsp_get_next_port(context, p0)) != NULL) {
+ if (!dsp_port_is_ok(context, p0, display_detect)) {
+ continue; /* skip ports that are inuse (not to be used) */
+ }
+ p1 = NULL;
+ while ((p1 = dsp_get_next_port(context, p1)) != NULL) {
+ if (!dsp_port_is_ok(context, p1, display_detect) || (p1 == p0)) {
+ continue; /* can't use the same port twice! */
+ }
+ p2 = NULL;
+ while ((p2 = dsp_get_next_port(context, p2)) != NULL) {
+ if (!dsp_port_is_ok(context, p2, display_detect) ||
+ (p2 == p0) || (p2 == p1)) {
+ continue; /* can't use the same port multiple times! */
+ }
+ dsp_build_display_configs(p0, p1, p2, NULL, dc_flags,
+ &dsp_dc_list);
+ }
+ }
+ }
+
+ /* Get all possible four display configs */
+ p0 = NULL;
+ while ((p0 = dsp_get_next_port(context, p0)) != NULL) {
+ if (!dsp_port_is_ok(context, p0, display_detect)) {
+ continue; /* skip ports that are inuse (not to be used) */
+ }
+ p1 = NULL;
+ while ((p1 = dsp_get_next_port(context, p1)) != NULL) {
+ if (!dsp_port_is_ok(context, p1, display_detect) || (p1 == p0)) {
+ continue; /* can't use the same port twice! */
+ }
+ p2 = NULL;
+ while ((p2 = dsp_get_next_port(context, p2)) != NULL) {
+ if (!dsp_port_is_ok(context, p2, display_detect) ||
+ (p2 == p0) || (p2 == p1)) {
+ continue; /* can't use the same port multiple times! */
+ }
+ while ((p3 = dsp_get_next_port(context, p3)) != NULL) {
+ if (!dsp_port_is_ok(context, p3, display_detect) ||
+ (p3 == p0) || (p3 == p2) || (p3 == p1)) {
+ continue; /* can't use the same port multiple times! */
+ }
+ dsp_build_display_configs(p0, p1, p2, p3, dc_flags,
+ &dsp_dc_list);
+ }
+ }
+ }
+ }
+#else
+
+ /*
+ * This code is much smaller than above but doesn't sort the list
+ * in the same way. It saves over 300 bytes.
+ */
+ p0 = NULL;
+ while ((p0 = dsp_get_next_port(context, p0, 0)) != NULL) {
+ if (dsp_port_is_ok(context, p0, display_detect)) {
+ dsp_add_to_dc_list(&dsp_context.dsp_dc_list,
+ (1 | ((p0->port_number & 0x0f) << 4)), 0);
+ p1 = NULL;
+ while ((p1 = dsp_get_next_port(context, p1, 0)) != NULL) {
+ if ((p1 != p0) && dsp_port_is_ok(context, p1, display_detect)) {
+ dsp_build_display_configs(p0, p1, NULL, NULL, dc_flags,
+ &dsp_context.dsp_dc_list);
+ p2 = NULL;
+ while ((p2 = dsp_get_next_port(context, p2, 0)) != NULL) {
+ if ((p2 != p0) && (p2 != p1) &&
+ dsp_port_is_ok(context, p2, display_detect)) {
+ dsp_build_display_configs(p0, p1, p2, NULL,
+ dc_flags, &dsp_context.dsp_dc_list);
+ while ((p3 = dsp_get_next_port(context, p3, 0)) !=
+ NULL) {
+ if ((p3 != p0) && (p3 != p2) && (p3 != p1) &&
+ dsp_port_is_ok(context, p3, display_detect)) {
+ dsp_build_display_configs(p0, p1, p2, p3,
+ dc_flags, &dsp_context.dsp_dc_list);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ /* zero terminate the list */
+ dsp_add_to_dc_list(&dsp_context.dsp_dc_list, 0L, 0L);
+
+ /*If quickboot, get the dc that was programmed by the firware
+ * i.e. Video BIOS or EFI Video Driver
+ */
+
+#ifndef CONFIG_MICRO /* We don't need this in firmware code */
+ dsp_context.fw_dc = dsp_get_fw_dc(context);
+ dsp_context.context->mod_dispatch.dsp_fw_dc = dsp_context.fw_dc;
+
+#endif
+
+ /*OPT_DEBUG_VOID_CALL(debug_print_dc_list());*/
+
+} /* end dsp_dc_init() */
+
+
+/*!
+ * Return the list of valid display configurations. The list returned is
+ * currently the "live" list. The IAL should not modify it in any way.
+ *
+ * For the driver, this will re-initialize the DC list every time it's
+ * called so that the list will reflect displays that have been attached
+ * or detached since the last call. If the list is empty (i.e. no
+ * displays attached and/or no port drivers loaded), then fall back to
+ * the following default behavior:
+ * 1. Make sure analog port is marked as available
+ * 2. Turn off the display detect option.
+ * 3. Re-initialize the DC list.
+ * This guarentees that we'll always have at least one valid display (CRT)
+ * on the list.
+ *
+ * @param driver_handle
+ *
+ * @param request - The requested display mode. The first DC in the list
+ * with a matching display mode is returned when the IGD_QUERY_DC_INIT
+ * flag is set.
+ *
+ * @param dc_list - The returned DC list. This will point to the live list
+ * and as such, should not be freed or altered.
+ *
+ * @param flags - Determines what portion of the list is returned.
+ *
+ * @return 0: success.
+ * @return -IGD_ERROR_INVAL: No valid DC list can be returned.
+ */
+int igd_query_dc(igd_driver_h driver_handle,
+ unsigned long request,
+ unsigned long **dc_list,
+ unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ int d;
+
+ EMGD_DEBUG ("Enter igd_query_dc");
+
+#ifndef CONIFG_MICRO
+ dsp_dc_init(context);
+ /*
+ * If the list is empty at this point, add single/analog so that
+ * the driver can run. Under normal conditions, this shouldn't
+ * happen. In this case, turn off display detect too?
+ */
+ if (dsp_context.dsp_dc_list.count == 1) {
+
+ EMGD_ERROR("No displays detected or available:");
+
+ /* If display detect is on, turn it off and try again */
+ if (dsp_context.display_flags & IGD_DISPLAY_DETECT) {
+
+ dsp_context.display_flags &= ~IGD_DISPLAY_DETECT;
+
+ /* Turn off display detect */
+ EMGD_ERROR(" Disabling display detect.");
+ dsp_dc_init(context);
+ }
+
+#if 0
+ /* Now, analog port driver also loads dynamically, so there is
+ * no fallback case to analog */
+ if (dsp_context.dsp_dc_list.count == 1) {
+ igd_display_port_t *port = NULL;
+ void *handle = NULL;
+
+ EMGD_ERROR(" Defaulting to CRT only.");
+ dsp_get_display(5, NULL, &port, 0);
+ if (port == NULL) {
+ EMGD_ERROR("No analog port available, this is bad!");
+ } else {
+ if (port->inuse == 0x80) {
+ /* port was never initialized, so better do that! */
+ ANALOG_INIT(handle);
+ }
+ port->inuse = 0; /* Mark as available */
+ }
+
+ /* Resetting DC list */
+ dsp_context.dsp_dc_list.count = 0;
+ dsp_add_to_dc_list(&dsp_context.dsp_dc_list, 0x00000051L, 0L);
+ dsp_add_to_dc_list(&dsp_context.dsp_dc_list, 0L, 0L);
+ }
+#endif
+ }
+#endif
+
+ if (flags == IGD_QUERY_DC_ALL) {
+ *dc_list = dsp_context.dsp_dc_list.dc_list;
+ return 0;
+ } else if (flags == IGD_QUERY_DC_PREFERRED) {
+ /*
+ * FIXME:
+ * This case is not yet implemented. No IAL currently uses this
+ * capability.
+ *
+ * Somehow this needs to build a new smaller list and return
+ * that. The caller would then be responsibile for freeing the
+ * memory?
+ *
+ * For now, this returns the full list so that if an IAL tries
+ * to use it, it doesn't break.
+ */
+ *dc_list = dsp_context.dsp_dc_list.dc_list;
+ return 0;
+ } else if (flags == IGD_QUERY_DC_INIT) {
+ /* what is the current display config? */
+ for(d = 0; d < dsp_context.dsp_dc_list.count; d++) {
+ if (dsp_context.dsp_dc_list.dc_list[d] == request) {
+ *dc_list = &dsp_context.dsp_dc_list.dc_list[d];
+ return 0;
+ }
+ }
+
+ /* Find first match of same type */
+ for(d = 0; d < dsp_context.dsp_dc_list.count; d++) {
+ if (dsp_context.dsp_dc_list.dc_list[d] & (request & 0x0f)) {
+ *dc_list = &dsp_context.dsp_dc_list.dc_list[d];
+ return 0;
+ }
+ }
+ } else if (flags == IGD_QUERY_DC_EXISTING) {
+ *dc_list = &dsp_context.fw_dc;
+ return 0;
+ }
+ EMGD_ERROR ("igd_query_dc found no match for requested dc = %ld", request);
+ *dc_list = NULL;
+ return -IGD_ERROR_INVAL;
+}
+
+/*!
+ * Mark a plane as available. If there are surfaces allocated to the
+ * plane, free them.
+ *
+ * @param context
+ * @param plane
+ *
+ * @return void
+ */
+void free_plane(igd_context_t *context, igd_plane_t *plane)
+{
+ igd_cursor_info_t *ci;
+ igd_framebuffer_info_t *fb;
+
+ EMGD_DEBUG("free_plane Entry");
+
+ if(!plane) {
+ EMGD_ERROR("Attempt to free NULL plane");
+ return;
+ }
+
+ /* If a framebuffer was allocated for this plane, free it */
+ if (!plane->mirror && (plane->plane_info != NULL)) {
+ if ((IGD_PLANE_CURSOR & plane->plane_features) == IGD_PLANE_CURSOR){
+ ci = (igd_cursor_info_t *)plane->plane_info;
+ EMGD_DEBUG("Freeing cursor image @ 0x%08lx", ci->xor_offset);
+ context->dispatch.gmm_free(ci->xor_offset);
+ EMGD_DEBUG("Freeing cursor image @ 0x%08lx", ci->argb_offset);
+ context->dispatch.gmm_free(ci->argb_offset);
+ /* Free plane info */
+ OS_FREE(plane->plane_info);
+ plane->plane_info = NULL;
+ } else {
+ fb = (igd_framebuffer_info_t *)plane->plane_info;
+ EMGD_DEBUG("Freeing framebuffer @ 0x%08lx", fb->fb_base_offset);
+ if(fb->allocated) {
+ context->dispatch.gmm_free(fb->fb_base_offset);
+ }
+ /* Must retain the offset because it is our reservation */
+ fb->allocated = 0;
+ /* The FB Info is static, don't free it */
+ }
+ } else {
+ /* If this is mirrored (for clone displays), break the mirror */
+ plane->mirror->mirror = NULL;
+ plane->mirror = NULL;
+ /* Note: The following fixes a kernel Oops when the DRM module
+ * initializes the display when it's loaded, and then the X driver uses
+ * a different port order in its DC (and a dsp_shutdown() frees this,
+ * followed by an dsp_alloc() which needs to allocate a new cursor).
+ * That's because the primary and secondary ports/planes switch, and
+ * plane->plane_info in this context becomes cursor->cursor_info in
+ * dsp_alloc(), and it must be NULL so that a new cursor is allocated
+ * (otherwise the old memory location is re-used, even though the
+ * memory was freed and reallocated for another purpose):
+ */
+ if ((IGD_PLANE_CURSOR & plane->plane_features) == IGD_PLANE_CURSOR){
+ plane->plane_info = NULL;
+ }
+ }
+
+ EMGD_DEBUG("De-allocating plane 0x%lx", plane->plane_reg);
+ plane->inuse = 0;
+} /* end free_plane() */
+
+/*!
+ * Take a DC and configure the primary and secondary display handles.
+ * The two display handles are returned to the caller.
+ *
+ * It should be valid to use the 0/1 indexes for pipes & planes here
+ * because we should never get a DC that isn't valid. So if the hardware
+ * can't support extended, and extended DC will never show up.
+ *
+ * @param context
+ * @param dc
+ * @param flags
+ *
+ * @return 0: success.
+ * @return -IGD_INVAL: No valid DC list can be returned.
+ */
+int dsp_alloc(igd_context_t *context,
+ unsigned long dc,
+ unsigned long flags)
+{
+ igd_plane_t *plane = NULL, *plane2 = NULL, *temp = NULL;
+ igd_plane_t **plane_tbl;
+ igd_cursor_t *cursor = NULL, *cursor2 = NULL;
+ igd_cursor_t *cursora = NULL, *cursorb = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_display_port_t *port = NULL;
+ unsigned short port_number;
+ int i, swap_plane = 0;
+ int secondary_pipe = 1;
+
+
+ EMGD_TRACE_ENTER;
+
+#ifndef CONFIG_MICRO
+ /*
+ * Surfaces in the surface cache have a display handle associated with
+ * them. To be safe we need to flush everyone out of the cache before
+ * freeing a handle.
+ */
+ if(context->dispatch.gmm_flush_cache) {
+ if(dsp_context.display_list[0].allocated ||
+ dsp_context.display_list[1].allocated) {
+ context->dispatch.gmm_flush_cache();
+ }
+ }
+#endif
+
+ /* Clear all the port assignments */
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ dsp_context.display_list[0].port[i] = NULL;
+ dsp_context.display_list[1].port[i] = NULL;
+ }
+
+ /* Clear display ptr assignments */
+ OS_MEMSET(dsp_context.display_ptr_list, 0,
+ sizeof(dsp_context.display_ptr_list));
+
+ /* Free any allocated pipes */
+ if (dsp_context.display_list[0].pipe) {
+ PIPE(&dsp_context.display_list[0])->inuse = 0;
+ }
+ if (dsp_context.display_list[1].pipe) {
+ PIPE(&dsp_context.display_list[1])->inuse = 0;
+ }
+
+ /* Set up planes... */
+ plane_tbl = dsp_context.dispatch->planes;
+ while(*plane_tbl) {
+ (*plane_tbl)->inuse = 0;
+
+ if ((IGD_PLANE_CURSOR & (*plane_tbl)->plane_features) ==
+ IGD_PLANE_CURSOR) {
+ if ((cursora == NULL) &&
+ (IGD_CURSOR_USE_PIPEA & (*plane_tbl)->plane_features)) {
+ cursora = (igd_cursor_t *)(*plane_tbl);
+ cursor = cursora;
+ } else if (cursorb == NULL) {
+ cursorb = (igd_cursor_t *)(*plane_tbl);
+ cursor2 = cursorb;
+ }
+ } else {
+ if (plane == NULL) {
+ plane = *plane_tbl;
+ /* plane->mirror = NULL; */
+ } else if (plane2 == NULL) {
+ plane2 = *plane_tbl;
+ /* plane2->mirror = NULL; */
+ }
+ }
+ plane_tbl++;
+ }
+
+
+ /*
+ * Get the first port from the DC and hook it up as master.
+ * FIXME:
+ * If this fails becaue the display isn't attached, and there
+ * are more choices, this should move on and try the other
+ * choices, maybe?
+ */
+ OS_MEMSET(&dsp_context.display_list[0], 0, sizeof(igd_display_context_t));
+
+ port_number = (unsigned short)((dc & 0x000000f0) >> 4);
+ dsp_get_display(port_number, NULL, &port, 0);
+
+ if (port) {
+ /*
+ * Allocate a pipe for this display. Depending on the port
+ * requirements this could be either pipe.
+ */
+ if (port->port_features & IGD_PORT_USE_PIPEA) {
+ pipe = dsp_context.dispatch->pipes[0];
+ cursor = cursora;
+ cursor2 = cursorb;
+ secondary_pipe = 1;
+ if(plane->plane_features & IGD_PLANE_USE_PIPEB){
+ swap_plane = 1;
+ }
+ } else if (port->port_features & IGD_PORT_USE_PIPEB) {
+ pipe = dsp_context.dispatch->pipes[1];
+ cursor2 = cursora;
+ cursor = cursorb;
+ secondary_pipe = 0;
+ if(plane->plane_features & IGD_PLANE_USE_PIPEA){
+ swap_plane = 1;
+ }
+ } else {
+ EMGD_ERROR("Error, master port can't use either pipeA or pipeB!");
+ return -IGD_INVAL;
+ }
+
+ if(swap_plane){
+ temp = plane;
+ plane = plane2;
+ plane2 = temp;
+ }
+ pipe->inuse = 0;
+
+
+ /* set up the display handle */
+ dsp_context.display_list[0].plane = (void *)plane;
+ dsp_context.display_list[0].cursor = (void *)cursor;
+ dsp_context.display_list[0].pipe = (void *)pipe;
+ dsp_context.display_list[0].port[port_number-1] = (void *)port;
+ dsp_context.display_list[0].context = context;
+ dsp_context.display_list[0].port_number = port_number;
+ dsp_context.display_list[0].allocated = 1;
+ dsp_context.display_ptr_list[port_number]= &dsp_context.display_list[0];
+ pipe->inuse = 1;
+
+#ifndef CONFIG_MICRO
+ if (cursor) {
+ pipe->cursor = cursor;
+ cursor->inuse = 1;
+ if (cursor->cursor_info == NULL) {
+ cursor->cursor_info = OS_ALLOC(sizeof(igd_cursor_info_t));
+ if(!cursor->cursor_info) {
+ EMGD_ERROR("Error, memory allocation for cursor_info "
+ "failed.");
+ pipe->cursor = NULL;
+ cursor->inuse = 0;
+ } else {
+ if (dsp_init_cursor(context, cursor) != 0) {
+ pipe->cursor = NULL;
+ cursor->inuse = 0;
+ }
+ }
+ }
+ }
+#endif
+
+ } /* else {
+ EMGD_ERROR("Failed to set up primary: port = %p, pipe = %p, plane = %p",
+ port, pipe, plane);
+ }
+ */
+
+
+ /* Set up secondary. How it is set up depends on the display config */
+ switch (dc & 0x0000000f) {
+ case IGD_DISPLAY_CONFIG_SINGLE:
+ case IGD_DISPLAY_CONFIG_TWIN:
+ case 0:
+ /*
+ * If display 1 was previouslly allocated, then we were in either
+ * clone or extended. In either case, we just want to make sure
+ * the display is no longer allocated and any clone mirror links
+ * are removed.
+ *
+ * Note: This doesn't reduce any reference counts or free any
+ * resources allocated to display 1.
+ */
+ if (dsp_context.display_list[1].allocated) {
+ dsp_context.display_list[1].allocated = 0;
+ dsp_context.display_list[1].plane = NULL;
+ dsp_context.display_list[1].cursor = NULL;
+ dsp_context.display_list[1].pipe = NULL;
+
+ /* If the cursor and/or fb were cloned, break the clone */
+ if (cursor->mirror != NULL) {
+ cursor->mirror = NULL;
+ cursor2->mirror = NULL;
+ cursor2->cursor_info = NULL;
+ }
+
+ /* break plane mirror??? */
+ if (plane->mirror != NULL) {
+ plane->mirror = NULL;
+ plane2->mirror = NULL;
+ }
+ }
+ break;
+ case IGD_DISPLAY_CONFIG_CLONE:
+ /*
+ * When switching to clone we need to free any resources allocated
+ * to the second display. This can happen if we were ever in
+ * extended mode prior to this.
+ *
+ * NOTE:
+ * This then needs to fall through to the extended branch because
+ * the rest of the set up is the same. DO NOT ADD A BREAK STATEMENT!
+ */
+
+ /*
+ * If display_list[1].plane->plane_info exist and the plane_info
+ * reference count is 1, then this was allocated as an independent
+ * plane. The surface must be freed and the plane_info record reset.
+ *
+ * The same logic applies to the secondary cursor info. Does this
+ * imply that the display_list needs to have a cursor pointer too?
+ * What about moving the cursor from the pipe to the display?
+ */
+ if (dsp_context.display_list[1].plane && !plane2->mirror) {
+ free_plane(context, dsp_context.display_list[1].plane);
+ }
+ if (dsp_context.display_list[1].cursor && !cursor2->mirror) {
+ free_plane(context, (igd_plane_t *)cursor2);
+ }
+
+ /* Mirror the cursor and framebuffer to the second display */
+ plane->mirror = plane2;
+ plane2->mirror = plane;
+ /*
+ * Note: plane_info points to a static data structure so we have
+ * to get the original pointer back when going into extended.
+ */
+ plane2->plane_info = plane->plane_info;
+
+ /*
+ * WinCE VEXT uses clone mode, but needs indpendent cursors. Thus,
+ * we don't want to do this mirroring in this one specific case.
+ */
+ cursor->mirror = cursor2;
+ cursor2->mirror = cursor;
+ cursor2->cursor_info = cursor->cursor_info;
+
+ case IGD_DISPLAY_CONFIG_EXTENDED:
+
+ if (plane2) {
+ /* Need to check here because the last case, CLONE, falls
+ * through to this one */
+ if (!(dc & IGD_DISPLAY_CONFIG_CLONE)) {
+ /* If this is really extended and not clone, break mirrors */
+ plane->mirror = NULL;
+ plane2->mirror = NULL;
+ if (plane2->plane_info == plane->plane_info) {
+ /*
+ * Get back the original static pointer by guessing
+ * and switching it if it is the same as plane 1.
+ */
+ plane2->plane_info = &fb_info_cmn[1];
+ if (plane2->plane_info == plane->plane_info) {
+ plane2->plane_info = &fb_info_cmn[0];
+ }
+ }
+ cursor->mirror = NULL;
+ cursor2->mirror = NULL;
+ if (cursor2->cursor_info == cursor->cursor_info) {
+ cursor2->cursor_info = NULL;
+ }
+ }
+
+ port_number = IGD_DC_SECONDARY(dc);
+ dsp_context.display_list[1].plane = (void *)plane2;
+ dsp_context.display_list[1].context = context;
+ dsp_context.display_list[1].cursor = (void *)cursor2;
+
+ /* Allocate which ever pipe wasn't used above */
+ pipe = dsp_context.dispatch->pipes[secondary_pipe];
+
+ if (pipe) {
+ dsp_context.display_list[1].allocated = 1;
+ pipe->inuse = 1;
+ dsp_context.display_list[1].pipe = (void *)pipe;
+
+ dsp_get_display(port_number, NULL, &port, 0);
+ if (port) {
+ dsp_context.display_list[1].port[port_number-1] =
+ (void *)port;
+ dsp_context.display_list[1].port_number = port_number;
+ dsp_context.display_ptr_list[port_number] =
+ &dsp_context.display_list[1];
+ } else {
+ EMGD_ERROR("Failed to get port %d", port_number);
+ }
+
+#ifndef CONFIG_MICRO
+ if (cursor2) {
+ pipe->cursor = cursor2;
+ cursor2->inuse = 1;
+ if (cursor2->cursor_info == NULL) {
+ cursor2->cursor_info =
+ OS_ALLOC(sizeof(igd_cursor_info_t));
+ if(!cursor2->cursor_info) {
+ EMGD_ERROR("Error, memory allocation for cursor_info "
+ "failed.");
+ pipe->cursor = NULL;
+ cursor2->inuse = 0;
+ } else {
+ if (dsp_init_cursor(context, cursor2) != 0) {
+ pipe->cursor = NULL;
+ cursor2->inuse = 0;
+ }
+ }
+ }
+ }
+#endif
+ } else {
+ EMGD_ERROR("Failed to get pipe #1");
+ }
+ } else {
+ EMGD_ERROR("Plane #1 not available");
+ }
+ break;
+ default:
+ EMGD_DEBUG("DC has an invalid display config! 0x%08lx", dc);
+ break;
+ }
+
+ /* Assign all twin'd ports to the proper displays */
+ for (i = 7; i > 1; i--) {
+ port_number = DC_PORT_NUMBER(dc, i);
+ if ((port_number) && (i != 5)) { /* Skip Owner ports */
+ dsp_get_display(port_number, NULL, &port, 0);
+ if (port) {
+ if (i > 5) {
+ dsp_context.display_list[1].port[port_number-1] =
+ (void *)port;
+ dsp_context.display_ptr_list[port_number] =
+ &(dsp_context.display_list[1]);
+ } else {
+ dsp_context.display_list[0].port[port_number-1] =
+ (void *)port;
+ dsp_context.display_ptr_list[port_number] =
+ &(dsp_context.display_list[0]);
+ }
+ }
+ }
+ }
+
+ dsp_context.current_dc = dc;
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Does the initialization of dsp module including initializing
+ * unset values in the plane, pipe and port tables.
+ *
+ * @param context
+ *
+ * @return 0: success.
+ * @return -IGD_ERROR_NODEV
+ */
+int dsp_init(igd_context_t *context)
+{
+ igd_display_params_t *display_params;
+ igd_plane_t **plane;
+ igd_display_pipe_t **pipe;
+ unsigned long i, num_gpio, *gpio_reg;
+ unsigned long hal_attr_index, init_attr_index;
+ igd_param_t *params = context->mod_dispatch.init_params;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ OS_MEMSET(&dsp_context, 0, sizeof(dsp_context));
+
+ /* Hook up plane, pipe, port, cursor lists here */
+ dsp_context.dispatch = (dsp_dispatch_t *)dispatch_acquire(context,
+ dsp_dispatch_list);
+ if(!dsp_context.dispatch) {
+ return -IGD_ERROR_NODEV;
+ }
+
+ dsp_context.context = context;
+
+ if(dsp_context.dispatch->dsp_init) {
+ ret = dsp_context.dispatch->dsp_init(context);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ /* Hook up top-level dispatch functions */
+ context->dispatch.query_dc = igd_query_dc;
+
+ /* Hook up inter-module dispatch functions */
+ context->mod_dispatch.dsp_get_config_info = dsp_get_config_info;
+ context->mod_dispatch.dsp_get_next_plane = dsp_get_next_plane;
+ context->mod_dispatch.dsp_get_next_pipe = dsp_get_next_pipe;
+ context->mod_dispatch.dsp_get_next_port = dsp_get_next_port;
+ context->mod_dispatch.dsp_get_dc = dsp_get_dc;
+ context->mod_dispatch.dsp_get_display = dsp_get_display;
+ context->mod_dispatch.dsp_get_planes_pipes = dsp_get_planes_pipes;
+ context->mod_dispatch.dsp_alloc = dsp_alloc;
+ context->mod_dispatch.dsp_control_plane_format = dsp_control_plane_format;
+
+ /* Dsp data members in inter module dispatch. This is done to make
+ * these data members available for vBIOS after init when dsp is
+ * discarded. */
+ context->mod_dispatch.dsp_current_dc = &dsp_context.current_dc;
+ context->mod_dispatch.dsp_port_list = dsp_context.port_list;
+ context->mod_dispatch.dsp_display_list = dsp_context.display_ptr_list;
+
+ /* Call the full init if we are not micro */
+ OPT_MICRO_CALL(dsp_full_init(context));
+
+ dsp_context.display_flags = params->display_flags;
+
+ /* Fill the number of planes and number of pipes in mode_context */
+ plane = dsp_context.dispatch->planes;
+ pipe = dsp_context.dispatch->pipes;
+
+ i=0;
+ while (*plane) {
+ if ((*plane)->plane_features & IGD_PLANE_DISPLAY) {
+ /*
+ * Initialize the offsets of the frame buffer to zero.
+ */
+ (*(igd_display_plane_t **)plane)->fb_info->fb_base_offset = 0;
+ (*(igd_display_plane_t **)plane)->fb_info->visible_offset = 0;
+ (*(igd_display_plane_t **)plane)->fb_info->saved_offset = 0;
+ (*(igd_display_plane_t **)plane)->fb_info->lock = FALSE;
+ dsp_context.num_dsp_planes++;
+ }
+ plane++;
+ }
+
+ while (*pipe) {
+ dsp_context.num_dsp_pipes++;
+ pipe++;
+ }
+
+ dsp_context.dsp_dc_list.dc_list = NULL;
+
+ /* Initialize port table with user specified display parameters. */
+ do_port_order(context, params->port_order);
+
+ /* Now set the other parameters in port table */
+ num_gpio = context->mod_dispatch.mode_get_gpio_sets(&gpio_reg);
+
+ for (i = 1, display_params = params->display_params; i <= 5; i++,
+ display_params++) {
+ unsigned long temp;
+ igd_display_port_t *port = NULL;
+
+ dsp_get_display((unsigned short)display_params->port_number,
+ NULL, &port, 0);
+ if (!port) {
+ /* If the port number is unknown/undefined,
+ * then skip this parameter */
+ continue;
+ }
+
+ /* process present_params flags */
+ if (IGD_PARAM_DDC_GPIO & display_params->present_params) {
+ temp = display_params->ddc_gpio;
+ if (temp >= num_gpio) {
+ EMGD_DEBUG("Invalid GPIO pin pair %ld specified for DDC.",
+ temp);
+ } else {
+ port->ddc_reg = gpio_reg[temp];
+ }
+ }
+ if (IGD_PARAM_DDC_SPEED & display_params->present_params) {
+ temp = display_params->ddc_speed;
+ if (temp > 400 || temp < 10) {
+ EMGD_DEBUG("DDC speed %ld is outside [10-400KHz] range.",
+ temp);
+ } else {
+ port->ddc_speed = temp;
+ }
+ }
+ if (IGD_PARAM_DDC_DAB & display_params->present_params) {
+ port->ddc_dab = display_params->ddc_dab;
+ }
+ if (IGD_PARAM_I2C_GPIO & display_params->present_params) {
+ temp = display_params->i2c_gpio;
+ if (temp >= num_gpio) {
+ EMGD_DEBUG("Invalid GPIO pin pair %ld specified for I2C.",
+ temp);
+ } else {
+ port->i2c_reg = gpio_reg[temp];
+ }
+ }
+ if (IGD_PARAM_I2C_SPEED & display_params->present_params) {
+ temp = display_params->i2c_speed;
+ if (temp > 400 || temp < 10) {
+ EMGD_DEBUG("I2C speed %ld is outside [10-400KHz] range.",
+ temp);
+ } else {
+ port->i2c_speed = temp;
+ }
+ }
+ if (IGD_PARAM_DAB & display_params->present_params) {
+ port->dab = display_params->i2c_dab;
+ }
+ if (IGD_PARAM_FP_INFO & display_params->present_params) {
+ port->fp_info = (igd_param_fp_info_t *)
+ OS_ALLOC(sizeof(igd_param_fp_info_t));
+ if (NULL != port->fp_info) {
+ OS_MEMCPY(port->fp_info, &display_params->fp_info,
+ sizeof(igd_param_fp_info_t));
+ EMGD_DEBUG("IGD_PARAM_FP_INFO: FP width %ld height %ld",
+ port->fp_info->fp_width, port->fp_info->fp_height);
+ } else {
+ EMGD_DEBUG("IGD_PARAM_FP_INFO: allocation of igd_param_fp_info_t "
+ "struct failed");
+ }
+ }
+ if (IGD_PARAM_DTD_LIST & display_params->present_params) {
+ port->dtd_list = OS_ALLOC(sizeof(igd_param_dtd_list_t));
+ if (NULL != port->dtd_list) {
+ OS_MEMCPY(port->dtd_list, &display_params->dtd_list,
+ sizeof(*port->dtd_list));
+ } else {
+ EMGD_DEBUG("IGD_PARAM_DTD_LIST: allocation of "
+ "igd_param_dtd_list_t struct failed");
+ }
+ }
+ if (IGD_PARAM_ATTR_LIST & display_params->present_params) {
+ port->attr_list = OS_ALLOC(sizeof(igd_param_attr_list_t));
+ if (NULL != port->attr_list) {
+ OS_MEMCPY(port->attr_list, &display_params->attr_list,
+ sizeof(*port->attr_list));
+ /* Now allocate memory for attributes */
+ port->attr_list->attr = OS_ALLOC(sizeof(igd_param_attr_t) *
+ port->attr_list->num_attrs);
+ if (NULL != port->attr_list->attr) {
+ OS_MEMCPY(port->attr_list->attr,
+ display_params->attr_list.attr,
+ sizeof(igd_param_attr_t) * port->attr_list->num_attrs);
+ }
+ }
+
+ /* Initialize HAL's attributes */
+ for( init_attr_index = 0;
+ init_attr_index < port->attr_list->num_attrs;
+ init_attr_index++ ) {
+
+ hal_attr_index = 0;
+
+ while (PD_ATTR_LIST_END != port->attributes[hal_attr_index].id) {
+ if (port->attributes[hal_attr_index].id ==
+ port->attr_list->attr[init_attr_index].id) {
+ port->attributes[hal_attr_index].current_value =
+ port->attr_list->attr[init_attr_index].value;
+ }
+
+ hal_attr_index++;
+ }
+ } /* for: initialize HAL's attributes */
+
+ }
+ }
+
+ /*
+ * Build the list of valid display configurations.
+ */
+ /* dsp_dc_init(context); */
+ EMGD_TRACE_EXIT;
+
+ return 0;
+} /* end dsp_init() */
+
+#ifndef CONFIG_MICRO
+
+/*!
+ * This function returns the list of available pixel formats for the
+ * framebuffer and cursor if the pointers are not NULL.
+ *
+ * @param display_handle A igd_display_h type returned from a previous
+ * igd_alloc_display call.
+ * @param fb_list_pfs Returns the list of pixel formats for framebuffer.
+ * @param cu_list_pfs Returns the list of pixel formats for the cursor.
+ * Both of the above lists ends with 0. Dframebuffer and cursor if the
+ * pointers are not NULL.
+ * @param overlay_pfs
+ * @param render_pfs
+ * @param texture_pfs
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_get_pixelformats(igd_display_h display_handle,
+ unsigned long **fb_list_pfs, unsigned long **cu_list_pfs,
+ unsigned long **overlay_pfs, unsigned long **render_pfs,
+ unsigned long **texture_pfs)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+
+
+ if (!display || !PLANE(display) || !PIPE(display)) {
+ return -IGD_INVAL;
+ }
+
+ if (fb_list_pfs) {
+ *fb_list_pfs = PLANE(display)->pixel_formats;
+ }
+ if (cu_list_pfs) {
+ *cu_list_pfs = PIPE(display)->cursor->pixel_formats;
+ }
+ if (overlay_pfs) {
+ *overlay_pfs = dsp_context.dispatch->overlay_pfs;
+ }
+ if (render_pfs) {
+ *render_pfs = dsp_context.dispatch->render_pfs;
+ }
+ if (texture_pfs) {
+ *texture_pfs = dsp_context.dispatch->texture_pfs;
+ }
+
+ return 0;
+
+} /* end igd_get_pixelformats() */
+
+/*!
+ * Given a newly allocated cursor_info record, allocate the
+ * surfaces needed for both the xor and argb cursor images. Also
+ * fill in the cursor_info as much as possible.
+ *
+ * @param context
+ * @param cursor
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_NOMEM on failure
+ */
+static int dsp_init_cursor(igd_context_t *context, igd_cursor_t *cursor)
+{
+ unsigned long buffer;
+ unsigned long buffer_phys = 0;
+ void* cursor_mem;
+ unsigned int width = 64;
+ unsigned int height = 64;
+ unsigned int pitch = 0;
+ unsigned long size = 0;
+ unsigned long flags = IGD_SURFACE_CURSOR;
+ int ret;
+ int has_rgb32 = 0;
+ unsigned long *tmp;
+
+ tmp = (unsigned long *)cursor->pixel_formats;
+ while (*tmp) {
+ if (*tmp == IGD_PF_ARGB32) {
+ has_rgb32 = 1;
+ break;
+ }
+ tmp++;
+ }
+
+ OS_MEMSET(cursor->cursor_info, 0, sizeof(igd_cursor_info_t));
+
+ if (has_rgb32) {
+ /* ARGB32 is used for any 32bit format. */
+ GMM_SET_DEBUG_NAME("ARGB Cursor");
+ ret = context->dispatch.gmm_alloc_surface(&buffer,
+ IGD_PF_ARGB32,
+ &width, &height, &pitch, &size,
+ IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
+ if (ret) {
+ EMGD_ERROR("ERROR: No memory for ARGB cursor!");
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /* Get the register update physical address in RAM */
+ if (context->dispatch.gmm_virt_to_phys(buffer, &buffer_phys)) {
+printk(KERN_ALERT "[EGD] dsp_init_cursor(): Virtual to Physical Address "
+"translation failed\n");
+ EMGD_ERROR_EXIT("Virtual to Physical Address translation failed");
+ return -IGD_ERROR_NOMEM;
+ }
+
+ cursor_mem = phys_to_virt(buffer_phys);
+ if(cursor_mem){
+ OS_MEMSET(cursor_mem, 0, size);
+ }
+ EMGD_DEBUG("Allocating cursor surface @ 0x%08lx", buffer);
+ cursor->cursor_info->argb_offset = buffer;
+ cursor->cursor_info->argb_pitch = pitch;
+ }
+ flags = IGD_SURFACE_CURSOR;
+
+ GMM_SET_DEBUG_NAME("XOR Cursor");
+ ret = context->dispatch.gmm_alloc_surface(&buffer,
+ IGD_PF_RGB_2,
+ &width, &height, &pitch, &size,
+ IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
+ if (ret) {
+ if(has_rgb32) {
+ context->dispatch.gmm_free(cursor->cursor_info->argb_offset);
+ cursor->cursor_info->argb_offset = 0;
+ }
+ EMGD_ERROR("ERROR: No memory for XOR cursor!");
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /* Get the register update physical address in RAM */
+ if (context->dispatch.gmm_virt_to_phys(buffer, &buffer_phys)) {
+ EMGD_ERROR_EXIT("Virtual to Physical Address translation failed");
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /*
+ * TODO: Verify that phys_to_virt returns a valid address for
+ * agp memory
+ */
+ cursor_mem = phys_to_virt(buffer_phys);
+ if(cursor_mem){
+ OS_MEMSET(cursor_mem, 0, size);
+ }
+ EMGD_DEBUG("Allocating cursor surface @ 0x%08lx", buffer);
+ cursor->cursor_info->xor_offset = buffer;
+ cursor->cursor_info->xor_pitch = pitch;
+
+ /* Set the dsp cursor resource table */
+ cursor->cursor_info->width = width;
+ cursor->cursor_info->height = height;
+ cursor->cursor_info->pixel_format =
+ (has_rgb32)?IGD_PF_ARGB32:IGD_PF_RGB_2;
+
+ return 0;
+}
+
+/*!
+ * Wait for all instructions on the ringbuffer to complete. This needs to be
+ * done before changing the framebuffer or the display. If we do not wait
+ * for the ringbuffer to empty, the hardware may lockup. It would be nice,
+ * if once the timeout occurs, to disable the ringbuffer, and continue with
+ * the mode changed, but this does not seem to be possible.
+ *
+ * @param context
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+/* FIXME: Move this to rb module */
+int dsp_wait_rb(igd_context_t *context)
+{
+ int p;
+ int wait_time = 15;
+ int ret;
+ unsigned long sync_val;
+ os_alarm_t timeout;
+
+ if (context->dispatch.sync) {
+ for (p = 0; p < 2; p++) {
+ if (dsp_context.display_list[p].allocated) {
+ /* Sync the Normal Ring. */
+ sync_val = 0;
+ timeout = OS_SET_ALARM(wait_time * 1000);
+ do {
+ ret = context->dispatch.sync(
+ &dsp_context.display_list[p],
+ IGD_PRIORITY_NORMAL, &sync_val, IGD_SYNC_BLOCK);
+ OS_SCHEDULE();
+ } while ((ret == -IGD_ERROR_BUSY) && (!OS_TEST_ALARM(timeout)));
+
+ if (ret == -IGD_ERROR_BUSY) {
+ EMGD_ERROR("Timeout waiting for sync");
+ return (-IGD_INVAL);
+ }
+
+ if(PIPE(&dsp_context.display_list[p])->queue[IGD_PRIORITY_BIN]) {
+ /* Sync the Binner also. */
+ sync_val = 0;
+ timeout = OS_SET_ALARM(wait_time * 1000);
+ do {
+ ret = context->dispatch.sync(
+ &dsp_context.display_list[p],
+ IGD_PRIORITY_BIN, &sync_val,
+ IGD_SYNC_BLOCK | IGD_SYNC_NOFLUSH_PIPE);
+ OS_SCHEDULE();
+ } while ((ret == -IGD_ERROR_BUSY) && (!OS_TEST_ALARM(timeout)));
+
+ if (ret == -IGD_ERROR_BUSY) {
+ EMGD_ERROR("Timeout waiting for Binner sync");
+ return (-IGD_INVAL);
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ * Browse through the list of displays and frees the display.
+ *
+ * @param context
+ *
+ * @return void
+ */
+void dsp_shutdown(igd_context_t *context)
+{
+ int i;
+ igd_display_port_t *port = NULL;
+ igd_plane_t *plane = NULL;
+ igd_display_pipe_t *temp_pipe = NULL;
+ unsigned int hal_attr_index = 0;
+
+ EMGD_DEBUG("dsp_shutdown Entry");
+
+ context->mod_dispatch.fb_blend_ovl_override = 0;
+
+ /*
+ * Free all the ports pt_info's. Need to add this here because there
+ * is no longer a 1-to-1 relationship between displays and ports.
+ */
+ while ((port = dsp_get_next_port(context, port, 0)) != NULL) {
+ if (port->pt_info != NULL) {
+ OS_FREE(port->pt_info);
+ port->pt_info = NULL;
+ }
+ if (port->dtd_list != NULL) {
+ OS_FREE(port->dtd_list);
+ port->dtd_list = NULL;
+ }
+ if (port->attr_list != NULL) {
+ if (port->attr_list->attr != NULL) {
+ OS_FREE(port->attr_list->attr);
+ }
+ OS_FREE(port->attr_list);
+ port->attr_list = NULL;
+ }
+
+ /* We should restore the gamma, brightness and contrast attributes
+ * to their defaults when the HAL is shutting down or else they
+ * would retain their previous values.
+ */
+ hal_attr_index = 0;
+ while (PD_ATTR_LIST_END != port->attributes[hal_attr_index].id) {
+ port->attributes[hal_attr_index].current_value =
+ port->attributes[hal_attr_index].default_value;
+
+ hal_attr_index++;
+ }
+ }
+
+
+ /* Free pipes, cursors, and any allocated command queues */
+ while ((temp_pipe = dsp_get_next_pipe(context, temp_pipe, 0)) != NULL) {
+
+ /* probably not needed since shutting down */
+ temp_pipe->inuse = 0;
+ temp_pipe->plane = NULL;
+ temp_pipe->timing = NULL;
+ temp_pipe->owner = NULL;
+ }
+
+ /* Free planes */
+ while ((plane = dsp_get_next_plane(context, plane, 0)) != NULL) {
+ if (plane->plane_info) {
+ free_plane(context, plane);
+ }
+ }
+
+ /* Clear display list */
+ for(i=0; i<MAX_DISPLAYS; i++) {
+ if(dsp_context.display_list[i].allocated) {
+ OS_MEMSET(&dsp_context.display_list[i], 0,
+ sizeof(igd_display_context_t));
+ }
+ }
+
+ /* Clear display ptr assignments */
+ OS_MEMSET(dsp_context.display_ptr_list, 0,
+ sizeof(dsp_context.display_ptr_list));
+
+ if (dsp_context.dsp_dc_list.dc_list != NULL) {
+ OS_FREE(dsp_context.dsp_dc_list.dc_list);
+ }
+
+ return;
+} /* end dsp_shutdown() */
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+static int dsp_full_init(igd_context_t *context)
+{
+ /* Optional Top level Entry Points */
+ context->dispatch.get_pixelformats = igd_get_pixelformats;
+
+ /* Hook up inter-module dispatch functions */
+ context->mod_dispatch.dsp_shutdown = dsp_shutdown;
+
+ return 0;
+}
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
new file mode 100644
index 0000000..8431df4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
@@ -0,0 +1,64 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DSP_DISPATCH_H
+#define _DSP_DISPATCH_H
+
+#include <igd.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+
+#include <mode.h>
+
+/*
+ * FIXME: This belong to PI, remove the defaults and let PI set
+ * them as it does for i2c.
+ */
+#define DDC_DEFAULT_SPEED 10 /* Default DDC bus speed in KHz */
+
+typedef struct _dsp_dispatch {
+ igd_plane_t **planes;
+ igd_display_pipe_t **pipes;
+ igd_display_port_t **ports;
+ igd_fb_caps_t *caps;
+ unsigned long *overlay_pfs;
+ unsigned long *render_pfs;
+ unsigned long *texture_pfs;
+ int (*dsp_init)(igd_context_t *context);
+ void (*dsp_control_plane_format)(igd_context_t *context,
+ int enable, int display_plane,
+ igd_plane_t *plane_override);
+} dsp_dispatch_t;
+
+extern dsp_dispatch_t dsp_dispatch_plb;
+extern dsp_dispatch_t dsp_dispatch_tnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c b/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
new file mode 100644
index 0000000..62e6582
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
@@ -0,0 +1,709 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_plb.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+
+#include <mode.h>
+#include <utils.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/dsp_dispatch.h"
+
+#ifdef CONFIG_PLB
+
+extern igd_framebuffer_info_t fb_info_cmn[];
+
+/*
+ * NOTE: Some of these format lists are shared with GMM. For this reason
+ * they cannot be static.
+ */
+unsigned long fb_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_ARGB8_INDEXED,
+ 0
+};
+
+unsigned long vga_pixel_formats_plb[] = {
+ IGD_PF_ARGB8_INDEXED,
+ 0
+};
+
+#ifndef CONFIG_MICRO
+unsigned long sprite_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ 0
+};
+
+unsigned long render_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ 0
+};
+
+unsigned long texture_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_xBGR32,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_DVDU_88,
+ IGD_PF_LDVDU_655,
+ IGD_PF_xLDVDU_8888,
+ IGD_PF_DXT1,
+ IGD_PF_DXT2,
+ IGD_PF_DXT3,
+ IGD_PF_DXT4,
+ IGD_PF_DXT5,
+ IGD_PF_L8,
+ IGD_PF_A8,
+ IGD_PF_AL88,
+ IGD_PF_AI44,
+ IGD_PF_L16,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_AWVU32_2101010,
+ IGD_PF_QWVU32_8888,
+ IGD_PF_GR32_1616,
+ IGD_PF_VU32_1616,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ 0
+};
+
+unsigned long depth_pixel_formats_plb[] = {
+ IGD_PF_Z16,
+ IGD_PF_Z24,
+ IGD_PF_S8Z24,
+ 0
+};
+
+
+unsigned long cursor_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_RGB_2,
+ IGD_PF_RGB_XOR_2,
+ IGD_PF_RGB_T_2,
+ 0
+};
+
+unsigned long overlay_pixel_formats_plb[] = {
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ 0
+};
+
+unsigned long video_pixel_formats_plb[] = {
+ IGD_PF_YUV420_PLANAR_NV12,
+ 0
+};
+
+unsigned long blt_pixel_formats_plb[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_xBGR32,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ IGD_PF_DVDU_88,
+ IGD_PF_LDVDU_655,
+ IGD_PF_xLDVDU_8888,
+ IGD_PF_DXT1,
+ IGD_PF_DXT2,
+ IGD_PF_DXT3,
+ IGD_PF_DXT4,
+ IGD_PF_DXT5,
+ IGD_PF_Z16,
+ IGD_PF_Z24,
+ IGD_PF_S8Z24,
+ IGD_PF_RGB_2,
+ IGD_PF_RGB_XOR_2,
+ IGD_PF_RGB_T_2,
+ IGD_PF_L8,
+ IGD_PF_A8,
+ IGD_PF_AL88,
+ IGD_PF_AI44,
+ IGD_PF_L16,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_AWVU32_2101010,
+ IGD_PF_QWVU32_8888,
+ IGD_PF_GR32_1616,
+ IGD_PF_VU32_1616,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ 0
+};
+
+static igd_fb_caps_t caps_table_plb[] = {
+ {IGD_PF_ARGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_xRGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ABGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_xBGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ARGB32_2101010, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_RGB16_565, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ARGB8_INDEXED, IGD_CAP_FULL_2D},
+ {0, 0}
+};
+
+#endif
+
+/*
+ * Plane Definitions for PLB family.
+ */
+static igd_plane_t planea_plb = {
+ DSPACNTR, IGD_PLANE_DISPLAY | IGD_PLANE_DIH, 0, 0,
+ fb_pixel_formats_plb, &fb_info_cmn[0], NULL
+};
+
+static igd_plane_t planeb_plb = {
+ DSPBCNTR, IGD_PLANE_DISPLAY | IGD_PLANE_SPRITE | IGD_PLANE_DIH, 0, 0,
+ fb_pixel_formats_plb, &fb_info_cmn[1], NULL
+};
+
+static igd_plane_t planec_plb = {
+ DSPCCNTR, IGD_PLANE_SPRITE, 0, 0,
+ OPT_MICRO_VALUE(sprite_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_vga_plb = {
+ VGACNTRL, IGD_PLANE_VGA, 0, 0,
+ vga_pixel_formats_plb, NULL, NULL
+};
+
+static igd_plane_t plane_overlay_plb = {
+ OVADD, IGD_PLANE_OVERLAY, 0, 0,
+ OPT_MICRO_VALUE(overlay_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursora_plb = {
+ CUR_A_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+ OPT_MICRO_VALUE(cursor_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursorb_plb = {
+ CUR_B_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+ OPT_MICRO_VALUE(cursor_pixel_formats_plb, NULL), NULL, NULL
+};
+
+/*
+ * Plane lists for PLB family members.
+ */
+/* Two Main Plane, One Sprite, One VGA, One Overlay, Two Cursor */
+static igd_plane_t *plane_table_plb[] = {
+ &planeb_plb,
+ &planea_plb,
+ &planec_plb,
+ &plane_vga_plb,
+ &plane_overlay_plb,
+ &plane_cursora_plb,
+ &plane_cursorb_plb,
+ NULL
+};
+
+static igd_clock_t clock_a_plb = {
+ DPLLACNTR, FPA0, 16
+};
+
+static igd_clock_t clock_b_plb = {
+ DPLLBCNTR, FPB0, 16
+};
+
+/*
+ * Pipe definitions for PLB family.
+ */
+static igd_display_pipe_t pipea_plb = {
+ 0, PIPEA_CONF, PIPEA_TIMINGS, DPALETTE_A, &clock_a_plb,
+ (IGD_PIPE_IS_PIPEA | IGD_PORT_SHARE_DIGITAL),
+ 0, 0,{NULL, NULL, NULL}, &planea_plb, NULL, NULL, NULL,
+ NULL, NULL
+};
+
+static igd_display_pipe_t pipeb_plb = {
+ 1, PIPEB_CONF, PIPEB_TIMINGS, DPALETTE_B, &clock_b_plb,
+ (IGD_PIPE_IS_PIPEB | IGD_PORT_SHARE_LVDS),
+ 0, 0,{NULL, NULL, NULL}, &planeb_plb, NULL, NULL, NULL,
+ NULL, NULL
+};
+
+static igd_display_pipe_t *pipe_table_plb[] = {
+ &pipea_plb,
+ &pipeb_plb,
+ NULL
+};
+
+/*
+ * Port definitions for PLB family.
+ */
+
+/*
+ * Port number: Port number is 1-number of available ports on any hardware.
+ * Here are the definitions:
+ *
+ * On PLB:
+ * =======
+ * Port mappings:
+ * 1 - None
+ * 2 - DVO B port
+ * 3 - None
+ * 4 - Internal LVDS port
+ * 5 - None
+ *
+ * Note: Port number should match with port numbers in port parameters.
+ * See igd_init.h for more information.
+ */
+
+#endif
+/*
+ * These are the port attributes that the PLB core support.
+ * Note that currently it only contains color correction attributes.
+ * Eventually, this will include all the attributes.
+ */
+igd_attr_t port_attrib_plb[IGD_MAX_PORTS][5] = {
+ { /* Config for port 1: Integrated TV Encoder (Alviso only) */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+ },
+ { /* Config for port 2: DVO B */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+ },
+ { /* Config for port 3: DVO C */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+ },
+ { /* Config for port 4: LVDS */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+ },
+ { /* Config for port 5: ANALOG */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+ }
+};
+
+#ifdef CONFIG_PLB
+
+igd_display_port_t dvob_port_plb = {
+ IGD_PORT_DIGITAL, 2, "SDVO B", 0x61140, GMBUS_DVO_REG, 0,
+ GMBUS_DVOB_DDC, 0xA0,
+ (IGD_PORT_USE_PIPEA | IGD_VGA_COMPRESS | IGD_RGBA_COLOR |
+ IGD_PORT_GANG),
+ TVCLKINBC, 0, IGD_POWERSTATE_D0, IGD_POWERSTATE_D0,
+ NULL, NULL,
+ NULL, NULL, NULL, 0, NULL, 0,
+ DDC_DEFAULT_SPEED, NULL, NULL, NULL, NULL, 0, NULL, 0, 0,
+ IGD_POWERSTATE_UNDEFINED,
+ port_attrib_plb[2 - 1], /* Port Number - 1 */
+ 0, { NULL },
+ (BIT14 | BIT16 | BIT17),
+ (BIT17), 1,
+
+};
+
+static igd_display_port_t lvds_port_plb = {
+ IGD_PORT_LVDS, 4, "IntLVDS", 0x61180, 0, 0,
+ GMBUS_INT_LVDS_DDC, 0xA0,
+ (IGD_PORT_USE_PIPEB | IGD_VGA_COMPRESS),
+ DREFCLK, 0, IGD_POWERSTATE_D0, IGD_POWERSTATE_D0, NULL, NULL,
+ NULL, NULL, NULL, 0, NULL, 0,
+ DDC_DEFAULT_SPEED, NULL, NULL, NULL, NULL, 0, NULL, 0, 0,
+ IGD_POWERSTATE_UNDEFINED,
+ port_attrib_plb[4 - 1], /* Port Number - 1 */
+ 0, { NULL }, 0, 0, 0,
+};
+
+static igd_display_port_t *port_table_plb[] = {
+ &lvds_port_plb,
+ &dvob_port_plb,
+ NULL
+};
+
+static int dsp_init_plb(igd_context_t *context)
+{
+ return 0;
+}
+
+void dsp_control_plane_format_plb(igd_context_t *context,
+ int enable, int plane, igd_plane_t *plane_override)
+{
+ igd_plane_t * pl = NULL;
+ unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ unsigned long tmp;
+
+ if (plane_override == NULL) {
+ pl = (plane == 0) ? &planea_plb : &planeb_plb;
+ } else {
+ pl = plane_override;
+ }
+ tmp = EMGD_READ32(mmio + pl->plane_reg);
+
+ /*
+ * Pixel format bits (29:26) are in plane control register 0x70180 for
+ * Plane A and 0x71180 for Plane B
+ * 0110 = XRGB pixel format
+ * 0111 = ARGB pixel format
+ * Note that the plane control register is double buffered and will be
+ * updated on the next VBLANK operation so there is no need to sync with
+ * an explicit VSYNC.
+ */
+ if(enable) {
+ if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_RGB_8888) {
+ EMGD_WRITE32(tmp | DSPxCNTR_ARGB_8888, mmio + pl->plane_reg);
+ tmp = EMGD_READ32(mmio + pl->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + pl->plane_reg + 4);
+ EMGD_DEBUG("Changed pixel format from XRGB to ARGB\n");
+ }
+ } else {
+ if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) {
+ tmp = tmp & (~(DSPxCNTR_SRC_FMT_MASK));
+ EMGD_WRITE32(tmp | DSPxCNTR_RGB_8888, mmio + pl->plane_reg);
+ tmp = EMGD_READ32(mmio + pl->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + pl->plane_reg + 4);
+ OS_SLEEP(100);
+ EMGD_DEBUG("Changed pixel format from ARGB to XRGB\n");
+ }
+ }
+ EMGD_DEBUG("Plane register 0x%lX has value of 0x%X\n", pl->plane_reg,
+ EMGD_READ32(mmio + pl->plane_reg));
+
+}
+
+dsp_dispatch_t dsp_dispatch_plb = {
+ plane_table_plb, pipe_table_plb, port_table_plb,
+ OPT_MICRO_VALUE(caps_table_plb, NULL),
+ OPT_MICRO_VALUE(overlay_pixel_formats_plb, NULL),
+ OPT_MICRO_VALUE(render_pixel_formats_plb, NULL),
+ OPT_MICRO_VALUE(texture_pixel_formats_plb, NULL),
+ dsp_init_plb,
+ dsp_control_plane_format_plb,
+};
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c b/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
new file mode 100644
index 0000000..9d5072d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
@@ -0,0 +1,542 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_tnc.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+
+#include "../cmn/dsp_dispatch.h"
+
+#ifdef CONFIG_TNC
+
+extern igd_framebuffer_info_t fb_info_cmn[];
+
+/*
+ * NOTE: Some of these format lists are shared with GMM. For this reason
+ * they cannot be static.
+ */
+unsigned long fb_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_ARGB8_INDEXED,
+ 0
+};
+
+unsigned long vga_pixel_formats_tnc[] = {
+ IGD_PF_ARGB8_INDEXED,
+ 0
+};
+
+#ifndef CONFIG_MICRO
+unsigned long sprite_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ 0
+};
+
+unsigned long render_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ 0
+};
+
+unsigned long texture_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_xBGR32,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_DVDU_88,
+ IGD_PF_LDVDU_655,
+ IGD_PF_xLDVDU_8888,
+ IGD_PF_DXT1,
+ IGD_PF_DXT2,
+ IGD_PF_DXT3,
+ IGD_PF_DXT4,
+ IGD_PF_DXT5,
+ IGD_PF_L8,
+ IGD_PF_A8,
+ IGD_PF_AL88,
+ IGD_PF_AI44,
+ IGD_PF_L16,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_AWVU32_2101010,
+ IGD_PF_QWVU32_8888,
+ IGD_PF_GR32_1616,
+ IGD_PF_VU32_1616,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ 0
+};
+
+unsigned long depth_pixel_formats_tnc[] = {
+ IGD_PF_Z16,
+ IGD_PF_Z24,
+ IGD_PF_S8Z24,
+ 0
+};
+
+
+unsigned long cursor_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_RGB_2,
+ IGD_PF_RGB_XOR_2,
+ IGD_PF_RGB_T_2,
+ 0
+};
+
+unsigned long overlay_pixel_formats_tnc[] = {
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ 0
+};
+
+unsigned long video_pixel_formats_tnc[] = {
+ IGD_PF_YUV420_PLANAR_NV12,
+ 0
+};
+
+unsigned long blt_pixel_formats_tnc[] = {
+ IGD_PF_ARGB32,
+ IGD_PF_xRGB32,
+ IGD_PF_ABGR32,
+ IGD_PF_xBGR32,
+ IGD_PF_RGB16_565,
+ IGD_PF_xRGB16_555,
+ IGD_PF_ARGB16_1555,
+ IGD_PF_ARGB16_4444,
+ IGD_PF_ARGB8_INDEXED,
+ IGD_PF_YUV422_PACKED_YUY2,
+ IGD_PF_YUV422_PACKED_UYVY,
+ IGD_PF_YUV420_PLANAR_I420,
+ IGD_PF_YUV420_PLANAR_IYUV,
+ IGD_PF_YUV420_PLANAR_YV12,
+ IGD_PF_YUV420_PLANAR_NV12,
+ IGD_PF_YUV410_PLANAR_YVU9,
+ IGD_PF_DVDU_88,
+ IGD_PF_LDVDU_655,
+ IGD_PF_xLDVDU_8888,
+ IGD_PF_DXT1,
+ IGD_PF_DXT2,
+ IGD_PF_DXT3,
+ IGD_PF_DXT4,
+ IGD_PF_DXT5,
+ IGD_PF_Z16,
+ IGD_PF_Z24,
+ IGD_PF_S8Z24,
+ IGD_PF_RGB_2,
+ IGD_PF_RGB_XOR_2,
+ IGD_PF_RGB_T_2,
+ IGD_PF_L8,
+ IGD_PF_A8,
+ IGD_PF_AL88,
+ IGD_PF_AI44,
+ IGD_PF_L16,
+ IGD_PF_ARGB32_2101010,
+ IGD_PF_AWVU32_2101010,
+ IGD_PF_QWVU32_8888,
+ IGD_PF_GR32_1616,
+ IGD_PF_VU32_1616,
+ IGD_PF_R16F,
+ IGD_PF_GR32_1616F,
+ IGD_PF_R32F,
+ IGD_PF_ABGR64_16161616F,
+ 0
+};
+
+static igd_fb_caps_t caps_table_tnc[] = {
+ {IGD_PF_ARGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_xRGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ABGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_xBGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ARGB32_2101010, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_RGB16_565, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+ {IGD_PF_ARGB8_INDEXED, IGD_CAP_FULL_2D},
+ {0, 0}
+};
+
+#endif
+
+/*
+ * Plane Definitions for Atom E6xx family.
+ */
+static igd_plane_t planea_tnc = {
+ DSPACNTR, IGD_PLANE_DISPLAY | IGD_PLANE_DIH | IGD_PLANE_USE_PIPEA, 0, 0,
+ fb_pixel_formats_tnc, &fb_info_cmn[0], NULL
+};
+
+static igd_plane_t planeb_tnc = {
+ DSPBCNTR, IGD_PLANE_DISPLAY | IGD_PLANE_SPRITE | IGD_PLANE_DIH | IGD_PLANE_USE_PIPEB, 0, 0,
+ fb_pixel_formats_tnc, &fb_info_cmn[1], NULL
+};
+
+static igd_plane_t planec_tnc = {
+ DSPCCNTR, IGD_PLANE_SPRITE, 0, 0,
+ OPT_MICRO_VALUE(sprite_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_vga_tnc = {
+ VGACNTRL, IGD_PLANE_VGA, 0, 0,
+ vga_pixel_formats_tnc, NULL, NULL
+};
+
+static igd_plane_t plane_overlay_tnc = {
+ OVADD, IGD_PLANE_OVERLAY, 0, 0,
+ OPT_MICRO_VALUE(overlay_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursora_tnc = {
+ CUR_A_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+ OPT_MICRO_VALUE(cursor_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursorb_tnc = {
+ CUR_B_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+ OPT_MICRO_VALUE(cursor_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+/*
+ * Plane lists for Atom E6xx family members.
+ */
+/* Two Main Plane, One Sprite, One VGA, One Overlay, Two Cursor */
+static igd_plane_t *plane_table_tnc[] = {
+ &planea_tnc,
+ &planeb_tnc,
+ &planec_tnc,
+ &plane_vga_tnc,
+ &plane_overlay_tnc,
+ &plane_cursora_tnc,
+ &plane_cursorb_tnc,
+ NULL
+};
+
+static igd_clock_t clock_a_tnc = {
+ DPLLACNTR, FPA0, 17
+};
+
+static igd_clock_t clock_b_tnc = {
+ DPLLBCNTR, FPB0, 16
+};
+
+/*
+ * Pipe definitions for Atom E6xx family.
+ * Pipe A is always tied to LVDS and Pipe B always to SDVO
+ */
+static igd_display_pipe_t pipea_tnc = {
+ 0, PIPEA_CONF, PIPEA_TIMINGS, DPALETTE_A, &clock_a_tnc,
+ (IGD_PIPE_IS_PIPEA | IGD_PORT_SHARE_LVDS),
+ 0, 0,{NULL, NULL, NULL}, &planea_tnc, NULL, NULL,
+ NULL, NULL, NULL
+};
+
+static igd_display_pipe_t pipeb_tnc = {
+ 1, PIPEB_CONF, PIPEB_TIMINGS, DPALETTE_B, &clock_b_tnc,
+ (IGD_PIPE_IS_PIPEB | IGD_PORT_SHARE_DIGITAL),
+ 0, 0,{NULL, NULL, NULL}, &planeb_tnc, NULL, NULL,
+ NULL, NULL, NULL
+};
+
+static igd_display_pipe_t *pipe_table_tnc[] = {
+ &pipea_tnc,
+ &pipeb_tnc,
+ NULL
+};
+#endif /*CONFIG_TNC*/
+
+/*
+ * HAL attributes for Atom E6xx display ports
+ * These are the port attributes that the PLB core support.
+ * Note that currently it only contains color correction attributes.
+ */
+igd_attr_t port_attrib_sdvo_tnc[5] = {
+ /* Config for port 2: DVO B */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+};
+
+/* HAL attributes for LVDS port */
+igd_attr_t port_attrib_lvds_tnc[5] = {
+ /* Config for port 4: LVDS */
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_GAMMA,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Gamma",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x202020, /* default */
+ 0x202020, /* current */
+ 0x131313, /* Min: ~0.6 in 3i.5f format for R-G-B*/
+ 0xC0C0C0, /* Max: 6 in 3i.5f format for R-G-B */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_BRIGHTNESS,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Brightness",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_FB_CONTRAST,
+ PD_ATTR_TYPE_RANGE,
+ "Frame Buffer Contrast",
+ PD_ATTR_FLAG_PD_INVISIBLE,
+ 0x808080,
+ 0x808080,
+ 0x000000, /* Min: */
+ 0xFFFFFF, /* Max: */
+ 1),
+ PD_MAKE_ATTR(
+ PD_ATTR_ID_EXTENSION,
+ 0,
+ "",
+ PD_ATTR_FLAG_PD_INVISIBLE|PD_ATTR_FLAG_USER_INVISIBLE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
+ PD_MAKE_ATTR(
+ PD_ATTR_LIST_END,
+ 0,
+ "",
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0)
+};
+
+#ifdef CONFIG_TNC
+/*
+ * Port definitions for Atom E6xx gfx.
+ *
+ * Port mappings:
+ * 1 - None
+ * 2 - sDVO B port
+ * 3 - None
+ * 4 - Internal LVDS port
+ * 5 - None
+ */
+igd_display_port_t dvob_port_tnc = {
+ IGD_PORT_DIGITAL, 2, "SDVO B", 0x61140, GMBUS_DVO_REG, 0,
+ GMBUS_DVOB_DDC, 0xA0,
+ (IGD_PORT_USE_PIPEB | IGD_VGA_COMPRESS),
+ TVCLKINBC, 0, IGD_POWERSTATE_D0, IGD_POWERSTATE_D0,
+ NULL, NULL,
+ NULL, NULL, NULL, 0, NULL, 0,
+ DDC_DEFAULT_SPEED, NULL, NULL, NULL, NULL, 0, NULL, 0, 0,
+ IGD_POWERSTATE_UNDEFINED,
+ port_attrib_sdvo_tnc,
+ 0, { NULL },
+ (BIT14 | BIT16 | BIT17),
+ (BIT17), 1,
+
+};
+
+static igd_display_port_t lvds_port_tnc = {
+ IGD_PORT_LVDS, 4, "IntLVDS", 0x61180, 0, 0,
+ I2C_INT_LVDS_DDC, 0xA0,
+ (IGD_PORT_USE_PIPEA | IGD_VGA_COMPRESS),
+ DREFCLK, 0, IGD_POWERSTATE_D0, IGD_POWERSTATE_D0, NULL, NULL,
+ NULL, NULL, NULL, 0, NULL, 0,
+ DDC_DEFAULT_SPEED, NULL, NULL, NULL, NULL, 0, NULL, 0, 0,
+ IGD_POWERSTATE_UNDEFINED,
+ port_attrib_lvds_tnc,
+ 0, { NULL }, 0, 0, 0,
+};
+
+static igd_display_port_t *port_table_tnc[] = {
+ &lvds_port_tnc,
+ &dvob_port_tnc,
+ NULL
+};
+
+static int dsp_init_tnc(igd_context_t *context)
+{
+ return 0;
+}
+
+void dsp_control_plane_format_tnc(igd_context_t *context,
+ int enable, int plane, igd_plane_t *plane_override)
+{
+ igd_plane_t * pl = NULL;
+ unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ unsigned long tmp;
+
+ if (plane_override == NULL) {
+ pl = (plane == 0) ? &planea_tnc : &planeb_tnc;
+ } else {
+ pl = plane_override;
+ }
+ tmp = EMGD_READ32(mmio + pl->plane_reg);
+ /*
+ * Pixel format bits (29:26) are in plane control register 0x70180 for
+ * Plane A and 0x71180 for Plane B
+ * 0110 = XRGB pixel format
+ * 0111 = ARGB pixel format
+ * Note that the plane control register is double buffered and will be
+ * updated on the next VBLANK operation so there is no need to sync with
+ * an explicit VSYNC.
+ */
+ if(enable) {
+ if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_RGB_8888) {
+ tmp = tmp & (~(DSPxCNTR_SRC_FMT_MASK));
+ EMGD_WRITE32(tmp | DSPxCNTR_ARGB_8888, mmio + pl->plane_reg);
+ EMGD_READ32(mmio + pl->plane_reg);
+ tmp = EMGD_READ32(mmio + pl->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + pl->plane_reg + 0x1c);
+ EMGD_DEBUG("Changed pixel format from XRGB to ARGB\n");
+ }
+ } else {
+ if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) {
+ tmp = tmp & (~(DSPxCNTR_SRC_FMT_MASK));
+ EMGD_WRITE32(tmp | DSPxCNTR_RGB_8888, mmio + pl->plane_reg);
+ EMGD_READ32(mmio + pl->plane_reg);
+ tmp = EMGD_READ32(mmio + pl->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + pl->plane_reg + 0x1c);
+ OS_SLEEP(100);
+ EMGD_DEBUG("Changed pixel format from ARGB to XRGB\n");
+ }
+ }
+ EMGD_DEBUG("Plane register 0x%lX has value of 0x%X\n", pl->plane_reg,
+ EMGD_READ32(mmio + pl->plane_reg));
+}
+
+dsp_dispatch_t dsp_dispatch_tnc = {
+ plane_table_tnc, pipe_table_tnc, port_table_tnc,
+ OPT_MICRO_VALUE(caps_table_tnc, NULL),
+ OPT_MICRO_VALUE(overlay_pixel_formats_tnc, NULL),
+ OPT_MICRO_VALUE(render_pixel_formats_tnc, NULL),
+ OPT_MICRO_VALUE(texture_pixel_formats_tnc, NULL),
+ dsp_init_tnc,
+ dsp_control_plane_format_tnc,
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
new file mode 100755
index 0000000..827645d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
@@ -0,0 +1,2362 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_mode.c
+ * $Revision: 1.35 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contains client interface support functions for display allocations
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <config.h>
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+#include <gart.h>
+
+#include <igd.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+#include <igd_gmm.h>
+#include <igd_pd.h>
+
+#include <debug.h>
+#include <math_fix.h>
+#include <context.h>
+#include <rb.h>
+#include <pd.h>
+#include <intelpci.h>
+#include <dsp.h>
+#include <pi.h>
+#include <dispatch.h>
+#include <mode.h>
+#include <mode_access.h>
+#include <dsp.h>
+#include <utils.h>
+#include <general.h>
+
+#include "emgd_drv.h"
+#include "drm_emgd_private.h"
+#include "match.h"
+#include "mode_dispatch.h"
+
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+#define CURSOR_1_STATE 0x01
+#define CURSOR_2_STATE 0x02
+#define CURSOR_STATE(display) \
+ ((display == &display_list[0]) ? CURSOR_1_STATE : CURSOR_2_STATE)
+
+/*!
+ * This function is an exported utility function.
+ * Its meant for calculating backbuffer to frontbuffer coordinates when in
+ * rotation, render-scaling and / or flipping (in any combination).
+ *
+ * Eventually, this function will be only for HAL usage.
+ *
+ * @param rotation
+ * @param do_flip
+ * @param do_rscale
+ * @param x_rnd_scale
+ * @param y_rnd_scale
+ * @param front_width
+ * @param front_height
+ * @param x
+ * @param y
+ * @param hotx
+ * @param hoty
+ *
+ * @return void
+ */
+void igd_fb_to_screen(unsigned short rotation,
+ unsigned char do_flip, unsigned char do_rscale,
+ unsigned long x_rnd_scale, unsigned long y_rnd_scale,
+ unsigned short front_width, unsigned short front_height,
+ unsigned short *x, unsigned short *y,
+ unsigned short hotx, unsigned short hoty);
+
+int igd_kms_match_mode(void *emgd_encoder,
+ void *fb_info, igd_timing_info_h **timing);
+
+/* Do not malloc the context */
+extern mode_context_t mode_context[];
+
+extern emgd_drm_config_t config_drm;
+
+/* This symbol has to be in this file as it is part of
+ * driver ONLY.
+ */
+static fw_info_t global_fw_info;
+
+/*!
+ * This function sets the per-port attribute to the values given in
+ * the parameter. If the requested port is the PIPE master, then
+ * this function will proceed to program the palette.
+ *
+ * @param display used to program palette, if necessary
+ * @param attr_to_set contains the new color attribute to set
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int set_color_correct(igd_display_context_t *display,
+ const igd_range_attr_t *attr_to_set)
+{
+ igd_display_port_t *port;
+ igd_attr_t *hal_attr_list;
+ mode_dispatch_t *dispatch = mode_context->dispatch;
+ igd_range_attr_t *attr = NULL;
+ unsigned int i = 0;
+ int changed_flag_set = 1;
+
+ EMGD_TRACE_ENTER;
+
+ port = PORT_OWNER(display);
+ hal_attr_list = port->attributes;
+
+
+ /* update the HAL's own copy of attributes */
+ while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+ if (attr_to_set->id == hal_attr_list[i].id) {
+ attr = (igd_range_attr_t *) &hal_attr_list[i];
+
+ if (!(attr_to_set->flags & PD_ATTR_FLAG_VALUE_CHANGED)){
+ changed_flag_set = 0;
+ }
+ /* make sure the value is within range */
+ attr->current_value = OS_MAX(attr_to_set->current_value,
+ attr->min);
+
+ attr->current_value = OS_MIN(attr_to_set->current_value,
+ attr->max);
+
+ break;
+ }
+
+ i++;
+ }
+
+ /* if we didn't find anything, then quit with an error */
+ if (PD_ATTR_LIST_END == hal_attr_list[i].id) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* If the current display is not the pipe master, then we're done */
+ if (PIPE(display)->owner != display) {
+ return 0;
+ }
+
+ /* Program palette */
+ if(changed_flag_set){
+ dispatch = mode_context->dispatch;
+ dispatch->full->set_color_correct(display);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is used to put the mode module into the
+ * requested powerstate.
+ *
+ * @param context SS level igd_context
+ * @param powerstate IGD_POWERSTATE_D*
+ *
+ * @return 0 on success
+ * @return >0 on failure
+ */
+int mode_pwr(igd_context_t *context,
+ unsigned long powerstate)
+{
+
+#if 0
+ igd_display_context_t *display_list[2];
+ igd_display_context_t *display = NULL;
+ int i,j;
+#endif
+
+ EMGD_TRACE_ENTER;
+
+ switch(powerstate) {
+ case IGD_POWERSTATE_D0:
+ mode_context->dispatch->program_cdvo();
+ toggle_vblank_interrupts(TRUE);
+ break;
+
+#if 0
+ for(j = 0; j < 2; j++) {
+ display = display_list[j];
+ /* if there is no display or display not allocated, continue */
+ if(!display || !display->allocated) {
+ continue;
+ }
+
+ if (!PIPE(display)->timing) {
+ /* if there is no pipe timing, cannot enable, continue */
+ EMGD_DEBUG("No pipe timing for port = %lu",
+ display->port_number);
+ continue;
+ }
+
+ /* Set port power state */
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ if (display->port[i] &&
+ (((igd_display_port_t *)display->port[i])->pt_info->flags &
+ IGD_DISPLAY_ENABLE)) {
+ mode_context->dispatch->program_port(display, i+1, TRUE);
+ }
+ }
+
+ mode_context->dispatch->program_pipe(display, TRUE);
+ mode_context->dispatch->program_plane(display, TRUE);
+
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ if (display->port[i] &&
+ (((igd_display_port_t *)display->port[i])->pt_info->flags &
+ IGD_DISPLAY_ENABLE)) {
+ mode_context->dispatch->post_program_port(display, i+1, 0);
+ }
+ }
+
+ }
+
+ break;
+#endif
+
+ case IGD_POWERSTATE_D1:
+ case IGD_POWERSTATE_D2:
+ case IGD_POWERSTATE_D3:
+ toggle_vblank_interrupts(FALSE);
+ mode_context->dispatch->reset_plane_pipe_ports(mode_context->context);
+ break;
+ default:
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end mode_pwr() */
+
+/*!
+ * This function is used to save mode module register state.
+ *
+ * @param context SS level igd_context
+ * @param state pointer to module_state handle, where module_state_h is
+ * pointer to actual state
+ *@param flags should have IGD_REG_SAVE_MODE bit set for save
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int mode_save(igd_context_t *context, module_state_h *state,
+ unsigned long *flags)
+{
+ mode_state_t *mstate;
+ int i, ret;
+ igd_display_port_t *port = NULL;
+ inter_module_dispatch_t *md;
+
+ EMGD_TRACE_ENTER;
+
+ if (!state || !(*flags & IGD_REG_SAVE_MODE)) {
+ EMGD_ERROR_EXIT("NULL pointer to save mode state or"
+ " flags don't have IGD_REG_SAVE_MODE bit set.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* First allocate memory for mode state which includes pd states */
+ mstate = OS_ALLOC(sizeof(mode_state_t));
+ if (!mstate) {
+ EMGD_ERROR_EXIT("memory allocation failed.");
+ return -IGD_ERROR_NOMEM;
+ }
+ OS_MEMSET(mstate, 0, sizeof(mode_state_t));
+
+ md = &context->mod_dispatch;
+
+ /* Call pd_save */
+ port = NULL;
+ i = 0;
+ while ((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
+ if (port->pd_driver) {
+ EMGD_DEBUG("saving %s", port->pd_driver->name);
+ ret = port->pd_driver->pd_save(port->pd_context,
+ &(mstate->pd_state[i].state), 0);
+ if (ret) {
+ EMGD_DEBUG("pd_save failed for %s", port->pd_driver->name);
+ }
+
+ mstate->pd_state[i].port = port;
+ i++;
+ }
+ }
+
+ /* Update mode state */
+ *state = (module_state_h) mstate;
+
+ EMGD_DEBUG("mode_save: saved %d port driver states.", i);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end mode_save() */
+
+/*!
+ * This function is used to save mode module register state.
+ *
+ * @param context SS level igd_context
+ * @param state pointer to module_state handle, where module_state_h is
+ * pointer to actual state
+ * *@param flags should have IGD_REG_SAVE_MODE bit set for restore
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int mode_restore(igd_context_t *context, module_state_h *state,
+ unsigned long *flags)
+{
+ int i, ret;
+ igd_display_port_t *port = NULL;
+ mode_state_t *mstate;
+
+ EMGD_TRACE_ENTER;
+
+ if (!state || !(*flags & IGD_REG_SAVE_MODE)) {
+ EMGD_ERROR_EXIT("Null mode state.or trying to restore without a save");
+ return 0;
+ }
+
+ mstate = (mode_state_t *)(*state);
+
+ if (!mstate) {
+ EMGD_DEBUG("mode_restore: mstate = NULL");
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ /* Restore all PD drivers */
+ i = 0;
+ while (mstate->pd_state[i].port) {
+ port = mstate->pd_state[i].port;
+
+ EMGD_DEBUG("restoring %s", port->pd_driver->name);
+ ret = port->pd_driver->pd_restore(port->pd_context,
+ mstate->pd_state[i].state, 0);
+ if (ret) {
+ /* What can be done if restore fails */
+ EMGD_DEBUG("pd_restore failed for %s", port->pd_driver->name);
+ }
+
+ i++;
+ }
+
+ /* Free the memory allocated */
+ OS_FREE(mstate);
+ *state = NULL;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end mode_restore() */
+
+/*!
+ *
+ * @param cursor
+ * @param image
+ * @param rotate
+ * @param flip
+ * @param width
+ * @param height
+ *
+ * @return void
+ */
+static void load_argb_cursor_image(unsigned long *cursor,
+ unsigned long *image,
+ int rotate, int flip,
+ int width, int height)
+{
+ int w, h, x, y;
+ unsigned short nx, ny;
+ unsigned long *i;
+
+ w = width;
+ h = height;
+
+ /* make sure size is constrained to 64x64 */
+ if (w > 64) {
+ w = 64;
+ }
+ if (h > 64) {
+ h = 64;
+ }
+
+ /* Copy image */
+ for (y = 0; y < h; y++) {
+ i = image;
+ image += width;
+ for (x = 0; x < w; x++) {
+ /* rotate, flip x,y here. No scaling! */
+ nx = (unsigned short) x;
+ ny = (unsigned short) y;
+ igd_fb_to_screen((unsigned short) rotate, (unsigned char) flip,
+ 0, 0, 0, 64, 64, &nx, &ny, 0, 0);
+ cursor[nx + (64 * ny)] = *i++;
+ }
+ }
+}
+
+/*!
+ *
+ * @param cursor
+ * @param image
+ * @param rotate
+ * @param flip
+ * @param width
+ * @param height
+ *
+ * @return void
+ */
+static void load_xor_cursor_image(unsigned char *cursor,
+ unsigned char *image,
+ int rotate, int flip,
+ int width, int height)
+{
+ int j, x, y;
+ int pixel_num, byte_num, line_num;
+ int npixel_num, nbyte_num, nline_num, nbit_num;
+ unsigned short nx, ny;
+ unsigned char b_val, sbit, mask, pixel;
+
+ for (j = 0; j < 2; j++) {
+ cursor += (j * 8);
+ image += (j * 8);
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64; x++) {
+ pixel_num = x + (y * 64);
+ line_num = pixel_num / 64;
+ byte_num = (pixel_num & 63) / 8;
+ b_val = *(image + (16 * line_num) + byte_num);
+ pixel = (b_val >> ( 7 - (pixel_num & 7))) & 0x01;
+
+ nx = (unsigned short) x;
+ ny = (unsigned short) y;
+ igd_fb_to_screen((unsigned short) rotate, (unsigned char) flip,
+ 0, 0, 0, (unsigned short) width, (unsigned short) height,
+ &nx, &ny, 0 , 0);
+ npixel_num = nx + (ny * 64);
+ nline_num = npixel_num / 64;
+ nbyte_num = (npixel_num & 63) / 8;
+ nbit_num = 7 - (npixel_num & 7);
+ b_val = *(cursor + (16 * nline_num) + nbyte_num);
+
+ sbit = pixel << nbit_num;
+ mask = 0x01 << nbit_num;
+ b_val = (b_val & ~mask) | sbit;
+ *(cursor + (16 * nline_num) + nbyte_num) = b_val;
+
+ /*(cursor + (16 * line_num) + byte_num) = b_val; */
+ }
+ }
+ }
+}
+
+/*!
+ * This function caclulates the correct cursor position from IAL
+ * provided coordinates. It takes into account hotspot, rotation, flip,
+ * and render_scale.
+ *
+ * This takes an x and y coordinate and sets the internal cursor
+ * info structure with the updated values. In addition, it
+ * sets a flag if the coordiantes are outside the displays active
+ * area.
+ *
+ * @param display
+ * @param x
+ * @param y
+ * @param hotx
+ * @param hoty
+ *
+ * @return void
+ */
+static void igd_set_cursor_pos(igd_display_context_t *display,
+ unsigned short x, unsigned short y,
+ unsigned short hotx, unsigned short hoty)
+{
+ igd_display_context_t *primary;
+ igd_cursor_info_t *internal_ci;
+ igd_display_info_t *timing;
+ igd_display_plane_t *plane;
+ unsigned char render_scale = 0;
+ unsigned short rotation, flip;
+ unsigned long cursor_state;
+
+ if (!display || !PLANE(display) || !PIPE(display) ||
+ !PIPE(display)->cursor || !PIPE(display)->cursor->cursor_info ||
+ !PORT_OWNER(display) || !PORT_OWNER(display)->pt_info) {
+ return;
+ }
+
+ internal_ci = PIPE(display)->cursor->cursor_info;
+ timing = PORT_OWNER(display)->pt_info;
+ plane = PLANE(display);
+
+ rotation = (unsigned short) ((internal_ci->rotation &
+ IGD_RENDER_OP_ROT_MASK) >> 8) * 90;
+ flip = (unsigned short) (internal_ci->rotation &
+ IGD_RENDER_OP_FLIP) >> 10;
+
+ /*
+ * Handle rotation, flip and render scale
+ * Note that the x,y arguments are unsigned, but cursor cordinates
+ * are signed and we need to preserve the signness when saving back
+ * into internal_ci structure!
+ */
+ if ((internal_ci->render_scale_x > 0) ||
+ (internal_ci->render_scale_y > 0)) {
+ render_scale = 1;
+ } else {
+ render_scale = 0;
+ }
+
+ igd_fb_to_screen((unsigned short) rotation, (unsigned char) flip,
+ render_scale,
+ internal_ci->render_scale_x, internal_ci->render_scale_y,
+ (unsigned short) plane->fb_info->width,
+ (unsigned short) plane->fb_info->height,
+ &x, &y,
+ hotx, hoty);
+
+ /* Adjust the x and y values relative to the current display offset */
+ internal_ci->x_offset = (long)((short)x - (short)timing->x_offset);
+ internal_ci->y_offset = (long)((short)y - (short)timing->y_offset);
+
+
+ /* Adjust the cursor offset for rotation and flip */
+
+ switch (rotation) {
+ case 0:
+ if (flip) {
+ internal_ci->x_offset -= 63;
+ }
+ break;
+ case 90:
+ internal_ci->y_offset += 1;
+ if (!flip) {
+ internal_ci->y_offset -= 63;
+ }
+ break;
+ case 180:
+ internal_ci->x_offset += 1;
+ internal_ci->y_offset -= 63;
+ if (!flip) {
+ internal_ci->x_offset -= 63;
+ }
+ break;
+ case 270:
+ internal_ci->x_offset -= 63;
+ if (flip) {
+ internal_ci->y_offset -= 63;
+ }
+ break;
+ default:
+ break;
+ }
+
+ display->context->mod_dispatch.dsp_get_dc(NULL, &primary, NULL);
+ if(display == primary) {
+ cursor_state = CURSOR_1_STATE;
+ } else {
+ cursor_state = CURSOR_2_STATE;
+ }
+
+ /*
+ * When panning, the cursor can be positioned off screen. The hardware
+ * doesn't like it if this happens. Thus, we set a flag to indicate
+ * that the cursor is currently off screen. That way it can be
+ * turned off when actually programmed.
+ *
+ * This also moves the position so that it is at the very edge of the
+ * screen, just in case it is turned on.
+ */
+
+ internal_ci->off_screen &= ~cursor_state;
+
+ /* Make sure the cursor is fully displayed */
+ if (internal_ci->x_offset < -63) {
+ internal_ci->x_offset = -63;
+ internal_ci->off_screen |= cursor_state;
+ }
+ if (internal_ci->x_offset >= (long)timing->width) {
+ internal_ci->x_offset = timing->width - 1;
+ internal_ci->off_screen |= cursor_state;
+ }
+ if (internal_ci->y_offset < -63) {
+ internal_ci->y_offset = -63;
+ internal_ci->off_screen |= cursor_state;
+ }
+ if (internal_ci->y_offset >= (long)timing->height) {
+ internal_ci->y_offset = timing->height - 1;
+ internal_ci->off_screen |= cursor_state;
+ }
+
+ return;
+}
+
+/*!
+ * This function sets the cursor_info obtained from igd_alloc_cursor
+ * and programs the cursor
+ *
+ * @param display_handle
+ * @param cursor_info
+ * @param image
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int igd_alter_cursor(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info,
+ unsigned char *image)
+{
+ igd_display_context_t *display = (igd_display_context_t *) display_handle;
+ igd_display_context_t *display2;
+ igd_display_context_t *primary;
+ igd_cursor_info_t *internal_ci;
+ unsigned short rotation, flip;
+ unsigned long cursor_state;
+ unsigned long cursor_state2;
+ unsigned long *cursora = NULL;
+ unsigned char *cursorx = NULL;
+// unsigned long in_dihclone=0;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(display, "Null Display Handle", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(cursor_info, "Null cursor info", -IGD_ERROR_INVAL);
+
+// in_dihclone = display->context->mod_dispatch.in_dih_clone_mode;
+ if(validate_cursor(cursor_info, display)) {
+ EMGD_ERROR_EXIT("pixel_format validation failed.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ internal_ci = PIPE(display)->cursor->cursor_info;
+
+ cursor_info->argb_offset = internal_ci->argb_offset;
+ cursor_info->xor_offset = internal_ci->xor_offset;
+
+ rotation = (unsigned short) ((cursor_info->rotation &
+ IGD_RENDER_OP_ROT_MASK) >> 8) * 90;
+ flip = (unsigned short) (cursor_info->rotation & IGD_RENDER_OP_FLIP) >> 10;
+
+ display->context->mod_dispatch.dsp_get_dc(NULL, &primary, NULL);
+
+ /* If cursor plane is mirrored, then do the same for the other cursor */
+// if (PIPE(display)->cursor->mirror != NULL || in_dihclone) {
+ if (PIPE(display)->cursor->mirror != NULL ) {
+ if(display == primary) {
+ display->context->mod_dispatch.dsp_get_dc(NULL, NULL,
+ &display2);
+ } else {
+ display2 = primary;
+ }
+ }
+
+ /*
+ * Loading new cursor (for both primary and clone):
+ * 1. Blank cursor image: This can be avoided if new hotspot and
+ * new bitmap size are same as existing hotspot and image size.
+ * 2. Move cursor to new location accounting for new hotspot
+ * 3. Wait for vblank to load the new cursor to avoid flashing/tearing.
+ * This impacts performace tests as cursor shape changes several times
+ * while running/loading tests and this wait for vblank counts against
+ * test times. So going without a wait for vblank. If flashing/tearing
+ * becomes a must fix issue, then uncomment below wait_vblank().
+ * 4. Load new image
+ */
+
+ if ((image != NULL) && (cursor_info->flags & IGD_CURSOR_LOAD_ARGB_IMAGE)) {
+ unsigned long buffer_phys = 0;
+
+ /* Calculate the cursor's address in kernel-space: */
+ if (display->context->dispatch.gmm_virt_to_phys(internal_ci->argb_offset,
+ &buffer_phys)) {
+ EMGD_ERROR_EXIT("GMM Virtual to Physical Address translation failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * TODO: Verify that phys_to_virt returns a valid address for
+ * agp memory
+ */
+ cursora = phys_to_virt(buffer_phys);
+ EMGD_DEBUG("ARGB cursor virtual address is 0x%p", cursora);
+ if (cursora == NULL) {
+ EMGD_ERROR_EXIT("Physical to Virtual Address translation failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Clear cursor plane */
+ OS_MEMSET(cursora, 0, 64*64*4);
+
+ } else if ((image != NULL) &&
+ (cursor_info->flags & IGD_CURSOR_LOAD_XOR_IMAGE)) {
+
+ unsigned long buffer_phys = 0;
+
+ /* Calculate the cursor's address in kernel-space: */
+ if (display->context->dispatch.gmm_virt_to_phys(internal_ci->xor_offset,
+ &buffer_phys)) {
+ EMGD_ERROR_EXIT("GMM Virtual to Physical Address translation failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * TODO: Verify that phys_to_virt returns a valid address for
+ * agp memory
+ */
+ cursorx = phys_to_virt(buffer_phys);
+ EMGD_DEBUG("XOR cursor virtual address is 0x%p", cursorx);
+ if (cursorx == NULL) {
+ EMGD_ERROR_EXIT("Physical to Virtual Address translation failed");
+ return -IGD_ERROR_INVAL;
+ }
+ }
+
+ /* calculate the cursor position adjusting to new hotspot */
+ igd_set_cursor_pos(display,
+ (unsigned short)cursor_info->x_offset,
+ (unsigned short)cursor_info->y_offset,
+ (unsigned short)cursor_info->hot_x,
+ (unsigned short)cursor_info->hot_y);
+
+ /* Update internal structure with altered data */
+ internal_ci->pixel_format = cursor_info->pixel_format;
+ internal_ci->palette[0] = cursor_info->palette[0];
+ internal_ci->palette[1] = cursor_info->palette[1];
+ internal_ci->palette[2] = cursor_info->palette[2];
+ internal_ci->palette[3] = cursor_info->palette[3];
+ internal_ci->flags = cursor_info->flags;
+ internal_ci->rotation = cursor_info->rotation;
+ internal_ci->render_scale_x = cursor_info->render_scale_x;
+ internal_ci->render_scale_y = cursor_info->render_scale_y;
+
+ if(display == primary) {
+ cursor_state = CURSOR_1_STATE;
+ cursor_state2 = CURSOR_2_STATE;
+ } else {
+ cursor_state = CURSOR_2_STATE;
+ cursor_state2 = CURSOR_1_STATE;
+ }
+
+ if ((cursor_info->flags & IGD_CURSOR_ON) &&
+ !(internal_ci->off_screen & cursor_state)) {
+ mode_context->dispatch->full->program_cursor(display, TRUE);
+ } else {
+ mode_context->dispatch->full->program_cursor(display, FALSE);
+ }
+
+// if (PIPE(display)->cursor->mirror || (in_dihclone && display == primary) ) {
+ if (PIPE(display)->cursor->mirror ) {
+ igd_set_cursor_pos(display2,
+ (unsigned short)cursor_info->x_offset,
+ (unsigned short)cursor_info->y_offset,
+ (unsigned short)cursor_info->hot_x,
+ (unsigned short)cursor_info->hot_y);
+
+ if ((cursor_info->flags & IGD_CURSOR_ON) &&
+ !(internal_ci->off_screen & cursor_state2)) {
+ mode_context->dispatch->full->program_cursor(display2, TRUE);
+ } else {
+ mode_context->dispatch->full->program_cursor(display2, FALSE);
+ }
+ }
+
+ /* Pitch may have been altered by program_cursor */
+ cursor_info->xor_pitch = internal_ci->xor_pitch;
+ cursor_info->argb_pitch = internal_ci->argb_pitch;
+
+ /* wait for VBLANK */
+ /* mode_context->dispatch->wait_vblank(display); */
+
+ if ((image != NULL) &&
+ (cursor_info->flags & IGD_CURSOR_LOAD_ARGB_IMAGE)) {
+ load_argb_cursor_image(cursora, (unsigned long *)image, rotation, flip,
+ cursor_info->width, cursor_info->height);
+
+ } else if ((image != NULL) &&
+ (cursor_info->flags & IGD_CURSOR_LOAD_XOR_IMAGE)) {
+ load_xor_cursor_image(cursorx, image, rotation, flip,
+ cursor_info->width, cursor_info->height);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function programs the cursor position. It takes into account
+ * rotation, flip, and render_scale. It also knows about clone mode
+ * and manages the clone cursor automaticlly.
+ *
+ * @param display_handle
+ * @param cursor_info
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_alter_cursor_pos(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info)
+{
+ igd_display_context_t *display = (igd_display_context_t *) display_handle;
+ igd_display_context_t *display2 = NULL;
+// igd_display_context_t * primary= NULL;
+ igd_cursor_info_t *internal_ci;
+ unsigned long cursor_on_screen;
+ unsigned long cursor_state=0;
+// unsigned long in_dihclone=0;
+
+ /* If there is no cursor, return immediately */
+ if (!display || !PIPE(display) || !PIPE(display)->cursor) {
+ return -IGD_INVAL;
+ }
+
+// in_dihclone = display->context->mod_dispatch.in_dih_clone_mode;
+
+// display->context->mod_dispatch.dsp_get_dc(NULL, &primary, NULL);
+
+
+// if (PIPE(display)->cursor->mirror != NULL || ( in_dihclone && display == primary )) {
+ if (PIPE(display)->cursor->mirror != NULL) {
+ display->context->mod_dispatch.dsp_get_dc(NULL, NULL, &display2);
+ if (display == display2) {
+ display->context->mod_dispatch.dsp_get_dc(NULL, &display2, NULL);
+ cursor_state = CURSOR_2_STATE;
+ } else {
+ cursor_state = CURSOR_1_STATE;
+ }
+ }
+ /* Reset display2 if cursor isn't setup */
+ if (display2) {
+ if (!PIPE(display2) || !PIPE(display2)->cursor) {
+ display2 = NULL;
+ }
+ }
+
+ while (display) {
+ internal_ci = PIPE(display)->cursor->cursor_info;
+ cursor_on_screen = (internal_ci->off_screen & cursor_state);
+
+ igd_set_cursor_pos(display,
+ (unsigned short)cursor_info->x_offset,
+ (unsigned short)cursor_info->y_offset,
+ (unsigned short)cursor_info->hot_x,
+ (unsigned short)cursor_info->hot_y);
+
+ if (cursor_on_screen !=
+ (internal_ci->off_screen & cursor_state)) {
+ /*
+ * Cursor has moved either on or off screen since the last
+ * call. If it has moved back on screen, turn the cursor
+ * back on. If it moved off screen, turn it off.
+ */
+ if (internal_ci->off_screen & cursor_state) {
+ mode_context->dispatch->full->program_cursor(display, FALSE);
+
+ } else if (cursor_info->flags & IGD_CURSOR_ON) {
+ /*
+ * Only program the cursor back on if the IAL already has it
+ * ON. This is to prevent the problem where the IAL turned
+ * of the cursor on purpose, e.g. a user app turns it off, and
+ * then have the HAL turn it back on when moving the cursor
+ * from one screen to another.
+ */
+ mode_context->dispatch->full->program_cursor(display, TRUE);
+ }
+ }
+
+ /* Program cursor position */
+ if ((cursor_info->flags & IGD_CURSOR_ON) &&
+ !(internal_ci->off_screen & cursor_state)) {
+ mode_context->dispatch->full->alter_cursor_pos(
+ (igd_display_h)display, internal_ci);
+ }
+
+ /* Switch to the second display if it is mirrored */
+ display = display2;
+ display2 = NULL;
+ /* Switch the cursor states as well */
+ if(cursor_state == CURSOR_1_STATE) {
+ cursor_state = CURSOR_2_STATE;
+ } else {
+ cursor_state = CURSOR_1_STATE;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * This function returns the current framebuffer and
+ * display information.
+ *
+ * @param hDisplay required. The hDisplay contains the display
+ * information to return. This parameter was returned from a
+ * previous call to igd_alloc_display().
+ * @param port_number
+ * @param pFbInfo required and allocated by the caller. The pFbInfo
+ * struct is returned to the caller describing the current
+ * frame buffer.
+ * @param pPtInfo required and allocated by the caller. The
+ * pPtInfo struct is returned to caller describing the
+ * requested display parameters.
+ * @param ulFlags Currently not used
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_get_display(
+ igd_display_h hDisplay,
+ unsigned short port_number,
+ pigd_framebuffer_info_t pFbInfo,
+ pigd_display_info_t pPtInfo,
+ unsigned long ulFlags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)hDisplay;
+
+ EMGD_TRACE_ENTER;
+
+ /* Check for NULL pointers */
+ EMGD_ASSERT(pFbInfo, "Null FB Info", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(pPtInfo, "Null PT Info", -IGD_ERROR_INVAL);
+
+ /* If the port->pt_info isn't set that means it is called just after
+ * igd_alloc_display and before igd_alter_display(). So, just fill
+ * port_type into pPtInfo */
+ if (PORT(display, port_number)->pt_info == NULL) {
+ OS_MEMSET(pPtInfo, 0, sizeof(igd_display_info_t));
+ pPtInfo->flags = PORT(display, port_number)->port_type;
+ } else {
+ OS_MEMCPY(pPtInfo, PORT(display, port_number)->pt_info,
+ sizeof(igd_display_info_t));
+ }
+
+ if (PLANE(display)->fb_info == NULL) {
+ OS_MEMSET(pFbInfo, 0, sizeof(igd_framebuffer_info_t));
+ } else {
+ OS_MEMCPY(pFbInfo, PLANE(display)->fb_info,
+ sizeof(igd_framebuffer_info_t));
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function pans the display on the display device.
+ * It takes a x_offset, y_offset into the frame buffer and
+ * sets the display from (x_offset, y_offset) to
+ * (x_offset+width, y_offset+height).
+ * If x_offset+width, y_offset+height crosses frame buffer
+ * width and heigth, then it will return error.
+ *
+ * @param hDisplay pointer to an IGD_DISPLAY pointer returned
+ * from a successful call to igd_allocate_display().
+ * @param x_offset frame buffer offsets from (0, 0)
+ * @param y_offset frame buffer offsets from (0, 0)
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+long igd_pan_display(igd_display_h hDisplay,
+ unsigned long x_offset, unsigned long y_offset)
+{
+ igd_display_context_t *display = (igd_display_context_t *)hDisplay;
+ igd_framebuffer_info_t *fb_info;
+ igd_display_info_t *pt_info;
+ unsigned long x_old;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT((display && PORT_OWNER(display) && PORT_OWNER(display)->pt_info),
+ "Unvalid Display Handle", -IGD_ERROR_INVAL);
+
+ fb_info = PLANE(display)->fb_info;
+ pt_info = PORT_OWNER(display)->pt_info;
+
+ /* Check paning can be done or not */
+ if (!fb_info || !pt_info) {
+ EMGD_ERROR_EXIT("Panning cannot be done. fb, pt infos weren't set.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (! (PORT_OWNER(display)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_DEBUG("Currently this display is not enabled.");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((pt_info->width == fb_info->width) &&
+ (pt_info->height == fb_info->height)) {
+ EMGD_DEBUG("FB and display pt_info are same size, no paning.");
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ /*
+ * handle case primary: 1280x720 seconday:1024x768
+ * TODO:
+ * "ideally the FB 720 height should center on LVDS 768 height and pan across horizontally that is 1280 FB width pans on LVDS 1024 width."
+ */
+ if (fb_info->height >= pt_info->height) {
+ if (pt_info->width + x_offset > fb_info->width ||
+ pt_info->height + y_offset > fb_info->height) {
+ EMGD_ERROR_EXIT("invalid offsets are passing frame buffer.");
+ return -IGD_ERROR_INVAL;
+ }
+ } else {
+ if (pt_info->width + x_offset > fb_info->width ) {
+ EMGD_ERROR_EXIT("invalid offsets are passing frame buffer.");
+ return -IGD_ERROR_INVAL;
+ }
+ }
+
+ /* Now do the paning.
+ * Note: Never change the fb_base_offset (it always points to the
+ * first pixel in the frame buffer), nor the visible_offset (it
+ * always points to the first pixel of the visible buffer). */
+ /* TODO: How to know which fb we are using, frontbuffer/backbuffer? */
+
+ x_old = x_offset;
+ mode_context->dispatch->full->set_display_base(display, fb_info,
+ &x_offset, &y_offset);
+
+ /* Save offsets into pt_info */
+ pt_info->x_offset = (unsigned short)x_offset;
+ pt_info->y_offset = (unsigned short)y_offset;
+
+ /* igd_ovl_set_display also set this flag, this flag include:
+ * 1) ovl/sprite C swap, by igd_ovl_set_display
+ * 2) swap display, or only change 1 display, by pan display
+ */
+ ovl_context->ovl_display_swapped = 1;
+
+ /* FIXME:
+ * This could be negative, and thus conflict with the error codes
+ * returned above. However, this is needed for Whitney to compensate
+ * for the framebuffer offset alignment requirements and should only
+ * be positive.
+ */
+ EMGD_TRACE_EXIT;
+ return (x_offset - x_old);
+
+} /* end igd_pan_display() */
+
+/*!
+ * This function get attributes for a port. SS will
+ * allocate the memory required to return the *attr_list.
+ * This is a live copy of attributes used by both IAL and SS.
+ * Don't deallocate this memory. This will be freed by SS.
+ *
+ * The list returned will contain a list of HAL attributes
+ * followed by a pointer to the PD attributes.
+ *
+ * @param driver_handle pointer to an IGD context pointer returned
+ * from a successful call to igd_init().
+ * @param port_number port number of port to get pd attributes.
+ * @param num_attrs pointer to return the number of attributes
+ * returned in attr_list.
+ * @param attr_list - pointer to return the attributes.
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_get_attrs(
+ igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned long *num_attrs,
+ igd_attr_t **attr_list)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t *display;
+ int ret;
+ unsigned long hal_attrib_num, pd_attr_num;
+ igd_display_port_t *port;
+ igd_attr_t *pd_attr_list = NULL;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* basic parameter check */
+ EMGD_ASSERT(driver_handle, "Null Driver Handle", -IGD_ERROR_INVAL);
+
+ /* Get the display context that is currently using this port */
+ context->mod_dispatch.dsp_get_display(port_number, &display, &port, 0);
+
+ if(!display || !port) {
+ /*
+ * No display is using this port,
+ * should we abort at this point?
+ */
+ EMGD_TRACE_EXIT;
+ printk(KERN_ALERT "[EGD] igd_get_attrs exiting: "
+ "No display is using port %d.\n", port_number);
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get PD attributes */
+ pd_attr_num = *num_attrs;
+ ret = port->pd_driver->get_attrs( port->pd_context,
+ &pd_attr_num,
+ &pd_attr_list );
+
+ if (ret) {
+ pd_attr_num = 0;
+ pd_attr_list = NULL;
+ }
+
+ /* find the extension attribute and attach the pd_attr_list */
+ for (hal_attrib_num = 0;
+ PD_ATTR_LIST_END != port->attributes[hal_attrib_num].id;
+ hal_attrib_num++ ) {
+
+ if (PD_ATTR_ID_EXTENSION == port->attributes[hal_attrib_num].id ) {
+ ((igd_extension_attr_t *)(&port->attributes[hal_attrib_num]))->extension = pd_attr_list;
+ }
+ }
+
+ /* If attr_list is NULL then the caller is only interested in
+ * the number of attributes
+ */
+ if( NULL != attr_list ) {
+ *attr_list = port->attributes;
+ }
+
+ if (0 == pd_attr_num ) {
+ /* if there are no PD attributes, then subtract 1 from hal_attrib_num
+ * so that the "extension" attribute is not counted*/
+ *num_attrs = hal_attrib_num - 1;
+ } else {
+ /* subtract 1 because we should not count the "extension" attribute */
+ *num_attrs = hal_attrib_num + pd_attr_num - 1;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end igd_get_attrs() */
+
+/*!
+ * This function set attributes on a port.
+ *
+ * @param driver_handle pointer to an IGD context pointer returned
+ * from a successful call to igd_init().
+ * @param port_number port number of port to get pd attributes.
+ * @param num_attrs pointer to return the number of attributes
+ * returned in attr_list.
+ * @param attr_list - pointer to return the attributes.
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_set_attrs(
+ igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned long num_attrs,
+ igd_attr_t *attr_list)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t *display;
+ igd_display_port_t *port;
+ igd_attr_t *attr;
+ unsigned int i;
+
+ unsigned long num_attrs_set = 0;
+ int ret = 0, setmode = 0;
+ igd_timing_info_t *pd_timing_table = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ /* basic parameter check */
+ EMGD_ASSERT(driver_handle, "Null Driver Handle", -IGD_ERROR_INVAL);
+
+ /* Get the display context that is currently using this port */
+ context->mod_dispatch.dsp_get_display(port_number, &display, &port, 0);
+ if(!display || !port) {
+ /* No display is using this port, should we abort at this point? */
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(num_attrs == 0) {
+ return 0;
+ }
+
+
+ /*
+ * Take care of HAL attributes. Here we keep track of the number of
+ * attributes set. If the number set is equal to num_attrs, then we
+ * don't need to call port driver's set_attr when this loop is done
+ */
+ for( i = 0; i < num_attrs; i ++ ) {
+ switch (attr_list[i].id) {
+ case PD_ATTR_ID_FB_GAMMA:
+ case PD_ATTR_ID_FB_BRIGHTNESS:
+ case PD_ATTR_ID_FB_CONTRAST:
+ set_color_correct(display, (igd_range_attr_t *) &attr_list[i]);
+ num_attrs_set++;
+ break;
+
+ default:
+ /* ignore all non HAL-related attributes */
+ break;
+ }
+ }
+
+ /* Pass the attribute list down to the port driver for futher processing
+ * if necessary */
+ if (num_attrs > num_attrs_set) {
+ ret = port->pd_driver->set_attrs(port->pd_context, num_attrs, attr_list);
+
+ if (ret) {
+ return -IGD_INVAL;
+ }
+ }
+
+ attr = attr_list;
+ i = 0;
+ while (i++ < num_attrs) {
+ if (attr->flags & PD_ATTR_FLAG_SETMODE) {
+ setmode = 1;
+ break;
+ }
+ attr++;
+ }
+
+ ret = 0;
+ if (setmode) {
+ /* Update internal timings */
+ ret = port->pd_driver->get_timing_list(port->pd_context,
+ (pd_timing_t *)port->timing_table,
+ (pd_timing_t **)&pd_timing_table);
+
+ if (ret) {
+ EMGD_ERROR_EXIT("get_timing_list failed.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ port->timing_table = pd_timing_table;
+ port->num_timing = get_native_dtd(pd_timing_table,
+ PI_SUPPORTED_TIMINGS, &port->fp_native_dtd,
+ PD_MODE_DTD_FP_NATIVE);
+ ret = IGD_DO_QRY_SETMODE;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* end igd_set_attrs() */
+
+/*!
+ *
+ * @param display_h
+ * @param width
+ * @param height
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int mode_getresolution(
+ igd_display_h display_h,
+ unsigned long *width,
+ unsigned long *height)
+{
+ igd_display_context_t *display;
+ int ret = 0;
+
+ if (display_h) {
+ display = (igd_display_context_t *) display_h;
+
+ if (PORT_OWNER(display)->pt_info) {
+ *width = PORT_OWNER(display)->pt_info->width;
+ *height = PORT_OWNER(display)->pt_info->height;
+ ret = 0;
+ }
+ else {
+ ret = -IGD_ERROR_INVAL;
+ }
+
+ } else {
+ ret = -IGD_ERROR_INVAL;
+ }
+
+ return ret;
+}
+
+/*!
+ *
+ * @param driver_handle A igd_driver_h type returned from a previous
+ * igd_init call.
+ * @param port_number
+ * @param port_info Returns the information about port
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_get_port_info(igd_driver_h driver_handle,
+ unsigned short port_number,
+ igd_port_info_t *port_info)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_port_t *port;
+ pd_port_status_t port_status;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(driver_handle, "Invalid Driver Handle", -IGD_ERROR_INVAL);
+
+ if(port_number >= (IGD_MAX_PORTS + 1)) {
+ EMGD_ERROR("Error, invalid port number. ");
+ return -IGD_INVAL;
+ }
+
+ OS_MEMSET(port_info, 0, sizeof(igd_port_info_t));
+
+ context->mod_dispatch.dsp_get_display(port_number, NULL, &port, 0);
+
+ if (!port || !port->pd_driver || !port->pd_driver->pd_get_port_status) {
+ EMGD_ERROR_EXIT("pd_get_port_status not implemented. ");
+ return -IGD_ERROR_INVAL;
+ }
+
+ pd_strcpy(port_info->pd_name, port->pd_driver->name);
+ pd_strcpy(port_info->port_name, port->port_name);
+
+ port_info->port_num = port->port_number;
+ OS_MEMCPY(&port_info->driver_version, port->pd_driver->version,
+ sizeof(pd_version_t));
+
+ ret = port->pd_driver->pd_get_port_status(port->pd_context, &port_status);
+ if (ret == PD_SUCCESS) {
+ if (port_status.connected == PD_DISP_STATUS_DETACHED) {
+ /* 0 = Not Connected */
+ port_info->connected = 0;
+ } else {
+ /* PD_DISP_STATUS_ATTACHED, PD_DISP_STATUS_UNKNOWN */
+ port_info->connected = 1;
+ }
+ } else {
+ port_info->connected = 1;
+ }
+
+ port_info->display_type = port_status.display_type;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param driver_handle A igd_driver_h type returned from a previous
+ * igd_init call.
+ * @param i2c_reg
+ * @param flags
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int igd_access_i2c(
+ igd_driver_h driver_handle,
+ igd_i2c_reg_t *i2c_reg,
+ unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ unsigned char i;
+ unsigned long *gpio, num_gpio;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ if (!driver_handle || !i2c_reg) {
+ return -IGD_INVAL;
+ }
+
+ num_gpio = mode_context->dispatch->get_gpio_sets(&gpio);
+
+ if (i2c_reg->bus_id >= num_gpio) {
+ EMGD_DEBUG("Invalid bus number specified.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((unsigned long)(i2c_reg->reg + i2c_reg->num_bytes) > 0xFF) {
+ EMGD_DEBUG("Invalid number of %d bytes requested from reg 0x%x.",
+ i2c_reg->num_bytes, i2c_reg->reg);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (flags == IGD_I2C_WRITE) {
+ pd_reg_t temp_reg[2];
+ temp_reg[1].reg = PD_REG_LIST_END;
+
+ /* I2C write operation */
+ for (i=0; i<i2c_reg->num_bytes; i++) {
+ temp_reg[0].reg = i2c_reg->reg + i;
+ temp_reg[0].value = i2c_reg->buffer[i];
+ ret = context->mod_dispatch.i2c_write_reg_list(
+ context,
+ gpio[i2c_reg->bus_id],
+ i2c_reg->i2c_speed,
+ i2c_reg->dab,
+ temp_reg,
+ 0);
+ if (ret) {
+ EMGD_DEBUG("i2c write error.");
+ break;
+ }
+ }
+ } else if (flags == IGD_I2C_READ) {
+ /* I2C read operation */
+ ret = context->mod_dispatch.i2c_read_regs(
+ context,
+ gpio[i2c_reg->bus_id],
+ i2c_reg->i2c_speed,
+ i2c_reg->dab,
+ i2c_reg->reg,
+ i2c_reg->buffer,
+ i2c_reg->num_bytes,
+ 0);
+ if (ret) {
+ EMGD_DEBUG("i2c read error.");
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* end igd_access_i2c() */
+
+/*!
+ *
+ * @param driver_handle A igd_driver_h type returned from a previous
+ * igd_init call.
+ * @param port_number
+ * @param edid_version
+ * @param edid_revision
+ * @param edid_size
+ *
+ * @return -IGD_ERROR_INVAL or -IGD_ERROR_EDID on failure
+ * @return 0 on success
+ */
+/* FIXME: Move to PI */
+static int igd_get_EDID_info(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned char *edid_version, unsigned char *edid_revision,
+ unsigned long *edid_size)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_port_t *port;
+ int ret;
+ unsigned char temp_buf[25];
+ unsigned char edid_1_3_header[] = {
+ 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00
+ };
+
+ EMGD_TRACE_ENTER;
+
+ if (!driver_handle || !edid_version || !edid_revision || !edid_size) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ context->mod_dispatch.dsp_get_display(port_number, NULL, &port, 0);
+ if(!port) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Read EDID */
+ ret = context->mod_dispatch.i2c_read_regs(context,
+ port->ddc_reg,
+ 10, /* DDC speed 10 KHz */
+ port->ddc_dab,
+ 0x00, /* DDC Address */
+ temp_buf, /* Read 20 bytes into temp_buf */
+ 20,
+ 0);
+ if (ret) {
+ return -IGD_ERROR_EDID;
+ }
+
+ /* Check for EDID version */
+ if (!OS_MEMCMP((void *)temp_buf, (void *)edid_1_3_header, 8)) {
+ *edid_version = temp_buf[18];
+ *edid_revision = temp_buf[19];
+ *edid_size = 128;
+
+ /* Read EDID byte 0x7E which gives the number of (optional) 128-byte
+ * EDID extension blocks to follow. */
+ temp_buf[0] = 0;
+ ret = context->mod_dispatch.i2c_read_regs(context,
+ port->ddc_reg,
+ 10, /* DDC speed 10 KHz */
+ port->ddc_dab,
+ 0x7E, /* DDC Address */
+ &temp_buf[0], /* Read 1 byte into temp_buf */
+ 1,
+ 0);
+ if (ret) {
+ return -IGD_ERROR_EDID;
+ }
+
+ *edid_size += (temp_buf[0] * 128);
+
+ } else {
+ *edid_version = temp_buf[0] >> 4;
+ if (*edid_version != 2) {
+ return -IGD_ERROR_EDID;
+ }
+
+ *edid_revision = temp_buf[0] & 0x0F;
+ *edid_size = 256;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end igd_get_EDID_info() */
+
+/*!
+ * This function sets enables or disables a specific port. Or, if
+ * the port number passed in is zero, it applies the change to all
+ * ports associated with the display handle.
+ *
+ * @param driver_handle display handle.
+ * @param port_number port number to enable or disable (or zero).
+ * @param flag IGD_ENABLE or IGD_DISABLE
+ * @param test IGD_TEST or zero
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+static int igd_enable_port(igd_display_h display_handle,
+ unsigned short port_number,
+ unsigned long flag,
+ unsigned long test)
+{
+ igd_display_context_t *display;
+ igd_display_port_t *port;
+ int i;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ display = (igd_display_context_t *)display_handle;
+
+ /*
+ * There are a number of things that will probably need to be checked.
+ *
+ * When enabling a port, make sure the display has pipe timings.
+ *
+ * When enabling a port and display_detect is on, make sure a display
+ * is detected before enabling the port.
+ *
+ * When enabling a port, check if it must be master, if so, the timings
+ * will need to be changed.
+ *
+ * When disabling a port, don't disable the only port allocated to the
+ * display.
+ *
+ * When disabling a port and it was the master, change timings to next
+ * allocated port.
+ */
+
+ if (!PIPE(display)->timing && (flag & IGD_DISPLAY_ENABLE)) {
+ EMGD_ERROR("port enable requested without pipe timings.");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((port_number > 0) && (port_number <= IGD_MAX_PORTS)) {
+ port = (igd_display_port_t *)display->port[port_number - 1];
+ if (port == NULL) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (test == IGD_TEST) {
+ if ((port->pt_info->flags & IGD_DISPLAY_ENABLE) ==
+ (flag & IGD_DISPLAY_ENABLE)) {
+ return 0;
+ } else {
+ return -IGD_ERROR_INVAL;
+ }
+ }
+
+ if (flag & IGD_DISPLAY_ENABLE) {
+ /* Can we enable this port? */
+ if (dsp_display_connected(display->context, port)) {
+ port->pt_info->flags |= IGD_DISPLAY_ENABLE;
+ } else {
+ return -IGD_ERROR_INVAL;
+ }
+ } else {
+ port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
+ }
+ } else if ((port_number == 0) && !(flag & IGD_DISPLAY_ENABLE)) {
+ /* special case, disable all ports */
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ if (display->port[i]) {
+ port = (igd_display_port_t *)display->port[i];
+ port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
+ }
+ }
+ }
+
+ /* Program ports to the proper enable/disable state */
+ for(i = 0; i < IGD_MAX_PORTS; i++) {
+ if ((port = (igd_display_port_t *)display->port[i]) != NULL) {
+ if (!port_number || (port->port_number == port_number)) {
+ if (port->pt_info->flags & IGD_DISPLAY_ENABLE) {
+ ret = mode_context->dispatch->program_port(display, i+1,
+ TRUE);
+ } else {
+ ret = mode_context->dispatch->program_port(display, i+1,
+ FALSE);
+ }
+ if (ret != 0) {
+ EMGD_ERROR("programming port %d failed", i+1);
+ }
+ if (port->pt_info->flags & IGD_DISPLAY_ENABLE) {
+ /* Call post_program_port if port is getting enabled. */
+ ret = mode_context->dispatch->post_program_port
+ (display, i+1, 0);
+ } else {
+ ret = 0;
+ }
+ if (ret != 0) {
+ EMGD_ERROR("post programming port %d failed", i+1);
+ }
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+/*!
+ * Free memory allocated to hold timing infomation. This must have been
+ * allocated using the igd_query_mode_list.
+ *
+ * @param mode_list
+ *
+ * @return void
+ */
+void igd_free_mode_list(igd_display_info_t *mode_list)
+{
+ if (mode_list) {
+ OS_FREE(mode_list);
+ }
+}
+
+/*!
+ * Generate a mode list that is correct for the given pipe master and
+ * any twins.
+ *
+ * @param driver_handle
+ * @param dc
+ * @param mode_list
+ * @param port
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int full_mode_query(igd_driver_h driver_handle,
+ unsigned long dc,
+ igd_display_info_t **mode_list,
+ igd_display_port_t *port)
+{
+ igd_timing_info_t *tt;
+ igd_timing_info_t *xt;
+ int timings = 0;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Looking up timings for port: %ld", port->port_number);
+
+ /* determine the size of the mode list including the extensions */
+ tt = port->timing_table;
+ if (!tt) {
+ EMGD_ERROR("igd_query_mode_list: No Timings");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+ while (tt->width != IGD_TIMING_TABLE_END) {
+ /*
+ * Check here to see if this timing is valid on all other
+ * ports. If it is, then we'll add it to the list, otherwise
+ * it's skipped.
+ */
+ if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
+ timings++;
+ EMGD_DEBUG("Adding timing: (%dx%d)", tt->width, tt->height);
+ }
+ tt++;
+
+ /*
+ * If reached the first table END, then check for timings
+ * added by the user or EDID.
+ */
+ if ((tt->width == IGD_TIMING_TABLE_END) && tt->extn_ptr) {
+ tt = tt->extn_ptr;
+ }
+ }
+ timings++; /* add one for the terminating marker */
+
+ *mode_list = OS_ALLOC(sizeof(igd_timing_info_t) * timings);
+ if (*mode_list != NULL) {
+ /* Now build the new mode list */
+ tt = port->timing_table;
+ xt = (igd_timing_info_t *)*mode_list;
+ while (tt->width != IGD_TIMING_TABLE_END) {
+ if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
+ OS_MEMCPY(xt, tt, sizeof(igd_timing_info_t));
+ xt++;
+ }
+
+ tt++;
+ /*
+ * If reached the first table END, then check for timings
+ * added by the user or EDID.
+ */
+ if ((tt->width == IGD_TIMING_TABLE_END) && tt->extn_ptr) {
+ tt = tt->extn_ptr;
+ }
+ }
+ /* copy end of list marker */
+ OS_MEMCPY(xt, tt, sizeof(igd_timing_info_t));
+ } else {
+ EMGD_ERROR("igd_query_mode_list: Memory allocation failure.");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is used to shutdown any module/dsp
+ * module specific structures or tables etc.
+ *
+ * @param context SS level igd_context.
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+static void mode_shutdown(igd_context_t *context)
+{
+ inter_module_dispatch_t *md;
+ module_state_h *mode_state = NULL;
+ unsigned long *flags = NULL;
+ reg_state_id_t id;
+
+ EMGD_DEBUG("mode_shutdown Entry");
+
+ /*
+ * Disable all the displays in decending pipe order
+ * Note: This isn't exactly device independent. It works for all
+ * multipipe platforms that we know of but is limited to 2 pipes
+ * and assumes that it is ok to disable pipe b before a.
+ */
+
+ dsp_wait_rb(mode_context->context);
+
+ toggle_vblank_interrupts(FALSE);
+
+ /* Disable all VBlank interrupts: */
+ context->dispatch.disable_vblank_callback(ALL_PORT_CALLBACKS);
+
+ /* Reset all planes, pipe, ports to a known "off" state */
+ mode_context->dispatch->reset_plane_pipe_ports(context);
+
+ /* Shutdown dsp module */
+ context->mod_dispatch.dsp_shutdown(context);
+
+ /* Restore mode state */
+ md = &context->mod_dispatch;
+ if (config_drm.init) {
+ id = REG_MODE_STATE_CON;
+ } else {
+ id = REG_MODE_STATE_REG;
+ }
+ md->reg_get_mod_state(id, &mode_state, &flags);
+ mode_restore(context, mode_state, flags);
+
+ /* Shutdown PI module */
+ context->mod_dispatch.pi_shutdown(context);
+
+ /*
+ * Do not clear mode_context pointer. It needs to stay around until
+ * the very last thing.
+ *
+ * context->mode_context = NULL;
+ */
+
+ EMGD_DEBUG("Return");
+ return;
+} /* end mode_shutdown() */
+
+/*!
+ * This function is used to shutdown any module/dsp
+ * module specific structures or tables etc.
+ *
+ * @param context SS level igd_context.
+ * @param mode_context mode module initialization parameters
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int full_mode_init(igd_context_t *context,
+ mode_context_t *mode_context)
+{
+ igd_dispatch_t *dispatch = &context->dispatch;
+
+ /* Hook up the IGD dispatch table entires for mode */
+ dispatch->get_display = igd_get_display;
+ dispatch->pan_display = igd_pan_display;
+ dispatch->alter_cursor = igd_alter_cursor;
+ dispatch->alter_cursor_pos = igd_alter_cursor_pos;
+ dispatch->get_attrs = igd_get_attrs;
+ dispatch->set_attrs = igd_set_attrs;
+ dispatch->get_port_info = igd_get_port_info;
+ dispatch->access_i2c = igd_access_i2c;
+ dispatch->get_EDID_info = igd_get_EDID_info;
+ dispatch->free_mode_list = igd_free_mode_list;
+ dispatch->enable_port = igd_enable_port;
+
+ /* Hook up optional inter-module functions */
+ context->mod_dispatch.mode_save = mode_save;
+ context->mod_dispatch.mode_restore = mode_restore;
+ context->mod_dispatch.mode_pwr = mode_pwr;
+ context->mod_dispatch.mode_shutdown = mode_shutdown;
+ context->mod_dispatch.set_flip_pending =
+ mode_context->dispatch->full->set_flip_pending;
+ context->mod_dispatch.check_flip_pending =
+ mode_context->dispatch->full->check_flip_pending;
+ context->mod_dispatch.get_dd_timing =
+ mode_context->dispatch->get_dd_timing;
+ context->mod_dispatch.check_port_supported =
+ mode_context->dispatch->check_port_supported;
+ context->mod_dispatch.get_refresh_in_border =
+ mode_context->dispatch->get_refresh_in_border;
+ context->mod_dispatch.get_port_control =
+ mode_context->dispatch->full->get_port_control;
+
+
+ /* Hook up Core specific IGD dispatch table entries */
+ dispatch->set_palette_entry = mode_context->dispatch->set_palette_entry;
+ dispatch->get_scanline = mode_context->dispatch->full->get_scanline;
+ dispatch->wait_vsync = mode_context->dispatch->full->wait_vsync;
+ dispatch->query_in_vblank = mode_context->dispatch->full->query_in_vblank;
+ dispatch->get_surface = mode_context->dispatch->full->get_surface;
+ dispatch->set_surface = mode_context->dispatch->full->set_surface;
+ dispatch->query_event = mode_context->dispatch->full->query_event;
+ dispatch->register_vblank_callback =
+ mode_context->dispatch->full->register_vblank_callback;
+ dispatch->unregister_vblank_callback =
+ mode_context->dispatch->full->unregister_vblank_callback;
+ dispatch->enable_vblank_callback =
+ mode_context->dispatch->full->enable_vblank_callback;
+ dispatch->disable_vblank_callback =
+ mode_context->dispatch->full->disable_vblank_callback;
+
+ dispatch->unlock_planes = mode_context->dispatch->full->unlock_planes;
+ /* Assign the fw_info structure and Zero-out the contents */
+ mode_context->fw_info = &global_fw_info;
+ OS_MEMSET(mode_context->fw_info, 0, sizeof(fw_info_t));
+
+ /* Set the mode context quickboot options from the params */
+ mode_context->quickboot = context->mod_dispatch.init_params->quickboot;
+ mode_context->seamless = context->mod_dispatch.init_params->qb_seamless;
+ mode_context->video_input = context->mod_dispatch.init_params->qb_video_input;
+ mode_context->splash = context->mod_dispatch.init_params->qb_splash;
+
+ /* Just in case, disable all VBlank interrupts: */
+ dispatch->disable_vblank_callback(ALL_PORT_CALLBACKS);
+
+ return 0;
+} /* end full_mode_init() */
+
+/*!
+ * This function clears the framebutffer.
+ *
+ * @param mode_context mode module initialization parameters
+ * @param fb_info
+ * @param user_fb - the caller can provide an fb. If they do, then this
+ * function will not mem map it. If they provide this parameter as NULL,
+ * then we will go ahead and map one here.
+ *
+ * @return void
+ */
+void full_clear_fb(mode_context_t *mode_context,
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *user_fb)
+{
+ unsigned short line, index;
+ unsigned char *fb;
+ volatile unsigned long *base_line_pitch;
+ volatile unsigned long pitch_value;
+
+ if(user_fb) {
+ fb = user_fb;
+ } else {
+ fb = mode_context->context->dispatch.gmm_map(
+ fb_info->fb_base_offset);
+ EMGD_DEBUG("After gmm_map(), fb = 0x%p", fb);
+ }
+ base_line_pitch = (unsigned long *)fb;
+ pitch_value = fb_info->screen_pitch / 4;
+
+ for (line = 0; line < fb_info->height; line++) {
+ for(index = 0; index < pitch_value; index++) {
+ base_line_pitch[index] = mode_context->display_color;
+ }
+ base_line_pitch += pitch_value;
+ }
+
+ if(!user_fb) {
+ mode_context->context->dispatch.gmm_unmap(fb);
+ }
+}
+
+/*!
+ * This is done in an attempt to re-use the plane and cursor allocated
+ * to a port when that port is moved to a new display handle. The basic
+ * case is when the DC changes in this way:
+ *
+ * 0x00200058 -> 0x00000021
+ * 0x00000021 -> 0x00200058
+ *
+ * In both these cases, it is better if the plane and cursor are sticky
+ * to port 2.
+ *
+ * @param void
+ *
+ * @return void
+ */
+void swap_fb_cursor( void )
+{
+ igd_plane_t *display_plane1, *display_plane2;
+ igd_display_pipe_t *pipe1, *pipe2;
+ void *tmp;
+
+ mode_context->context->mod_dispatch.dsp_get_planes_pipes(
+ &display_plane1, &display_plane2,
+ &pipe1, &pipe2);
+
+ /* Swap the plane info data */
+ if (display_plane1 && display_plane2) {
+
+ tmp = display_plane1->plane_info;
+ display_plane1->plane_info = display_plane2->plane_info;
+ display_plane2->plane_info = tmp;
+ }
+
+ /* Swap the cursor info */
+ if (pipe1 && pipe2 && pipe1->cursor && pipe2->cursor) {
+
+ tmp = pipe1->cursor->cursor_info;
+ pipe1->cursor->cursor_info = pipe2->cursor->cursor_info;
+ pipe2->cursor->cursor_info = tmp;
+ }
+}
+
+/*!
+ * This function calculates target X and Y coordincates
+ * for a provided front buffer dimension after including
+ * corrections for render-scaling, rotation and flipping.
+ *
+ * @param rotation 0, 90, 180 or 270
+ * @param do_flip 0 or 1
+ * @param do_rscale 0 or 1
+ * @param x_rnd_scale fixed point int = (native_width << 16) / fb_width
+ * @param y_rnd_scale fixed point int = (native_height << 16) / fb_height
+ * @param front_width front buffer width for this pipe
+ * @param front_height front buffer height for this pipe
+ * @param x
+ * @param y
+ * @param hotx
+ * @param hoty
+ *
+ * @return void
+ */
+void igd_fb_to_screen(unsigned short rotation,
+ unsigned char do_flip, unsigned char do_rscale,
+ unsigned long x_rnd_scale, unsigned long y_rnd_scale,
+ unsigned short front_width, unsigned short front_height,
+ unsigned short *x, unsigned short *y,
+ unsigned short hotx, unsigned short hoty)
+{
+ unsigned short x_temp;
+ unsigned short y_temp;
+
+ /*
+ * we only need to up(or down)-scale the coordinates of
+ * of the cursor when we are moving the cursor... dont care
+ * about scaling the cursor image itself
+ */
+ if(do_rscale){
+ unsigned long phys_x_pos_scale = x_rnd_scale;
+ unsigned long phys_y_pos_scale = y_rnd_scale;
+
+ if(rotation == 90 || rotation == 270) {
+ phys_x_pos_scale = y_rnd_scale;
+ phys_y_pos_scale = x_rnd_scale;
+ }
+
+ /* Added code to fix rounding error */
+ if(*x & 0x8000) {
+ /* if its a negative x_offset, we need to put in additional
+ * type casting so the negative signage doesnt get scaled up
+ * and down and end up being a very large positive number
+ */
+ *x = (unsigned short)(-(short)((((unsigned long )
+ ((short)-*x) * phys_x_pos_scale) + ((1<<15)-1)) >> 16));
+ } else {
+ *x = (unsigned short)((((unsigned long)*x * phys_x_pos_scale) + ((1<<15)-1)) >> 16);
+ }
+
+ if(*y & 0x8000) {
+ /* if its a negative y_offset, we need to put in additional
+ * type casting so the negative signage doesnt get scaled up
+ * and down and end up being a very large positive number
+ */
+ *y = (unsigned short)(-(short)((((unsigned long )
+ ((short)-*y) * phys_y_pos_scale) + ((1<<15)-1)) >> 16));
+ } else {
+ *y = (unsigned short)((((unsigned long)*y * phys_y_pos_scale) + ((1<<15)-1)) >> 16);
+ }
+ }
+
+ *x -= hotx;
+ *y -= hoty;
+
+ x_temp = *x;
+ y_temp = *y;
+
+ switch(rotation) {
+ case 0:
+ default:
+ if(do_flip) {
+ *x = front_width-1 - x_temp;
+ }
+ break;
+ case 90:
+ *x = y_temp;
+ *y = (front_height - 1) - x_temp;
+ if(do_flip) {
+ *y = front_height-1 - *y ;
+ }
+ break;
+ case 180:
+ /* This is accurate for a 180 rotate */
+ *x = (front_width -1) - x_temp;
+ *y = (front_height-1) - y_temp;
+ if(do_flip) {
+ *x = (front_width -1) - *x;
+ }
+ break;
+ case 270:
+ *x = (front_width - 1) - y_temp;
+ *y= x_temp;
+ if(do_flip) {
+ *y = (front_height -1) - *y;
+ }
+ break;
+ }
+}
+
+
+
+/*!
+ * Compare the incoming dc, timing, fb with the one that
+ * the firmware has already programmed and see if seamless
+ * is possible.
+ *
+ * @param dc
+ * @param index 0 for primary and 1 for secondary
+ * @param pt
+ * @param pf
+ * @param flags Not used right now
+ *
+ * @return TRUE if seamless is possible
+ * @return FALSE if not possible
+ */
+int query_seamless(unsigned long dc,
+ int index,
+ igd_timing_info_t *pt,
+ igd_framebuffer_info_t *pf,
+ unsigned long flags)
+{
+ int ret = FALSE;
+ igd_display_info_t *timing;
+ igd_framebuffer_info_t *fb_info;
+ unsigned long in_pitch;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Incoming dc = 0x%08lx", dc);
+
+ /* Get the fw programmed DC from the inter-module data
+ * structure
+ */
+ mode_context->fw_info->fw_dc =
+ mode_context->context->mod_dispatch.dsp_fw_dc;
+
+ EMGD_DEBUG("firmware dc = 0x%08lx",mode_context->fw_info->fw_dc );
+ if(dc != mode_context->fw_info->fw_dc) {
+ /*special case when seamless transition from fw clone to vext */
+ if(!(IGD_DC_VEXT(dc) && IGD_DC_CLONE(mode_context->fw_info->fw_dc)))
+ {
+ /* DC doesn't match */
+ return FALSE;
+ }
+ EMGD_DEBUG("past dc check");
+ }
+
+ /* Note: this test both overcomes a compiler warning, as well as a
+ * potential kernel Oops from chasing a NULL pointer:
+ */
+ if ((pt == NULL) || (pf == NULL)) {
+ return FALSE;
+ }
+ EMGD_DEBUG("Incoming Timing Width = %hu", pt->width);
+ EMGD_DEBUG("Incoming Timing height = %hu", pt->height);
+ EMGD_DEBUG("Incoming Timing Refresh = %hu", pt->refresh);
+
+ /* Check pipe Timings */
+ if(pt != NULL) {
+ timing = &mode_context->fw_info->timing_arr[index];
+ ret = FALSE;
+
+ if( (timing->width == pt->width) &&
+ (timing->height == pt->height) )
+
+ /* Have to build in some tolerance here because the fresh rate may
+ * not match exactly */
+ if (abs(timing->refresh - pt->refresh) <= 2) {
+
+ ret = TRUE;
+ }
+ }
+
+ EMGD_DEBUG(" ");
+ EMGD_DEBUG("Firmware Timing Width = %hu", timing->width);
+ EMGD_DEBUG("Fimrware Timing Height = %hu", timing->height);
+ EMGD_DEBUG("Fimrware Timing Refesh = %hu", timing->refresh);
+ EMGD_DEBUG("-------------------------");
+
+ if(ret == FALSE) {
+ EMGD_DEBUG("Incoming Timings and Firmware Timings Do NOT match!");
+ EMGD_DEBUG("Seamless is NOT possible");
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+
+
+ EMGD_DEBUG("Incoming FB Width = %u", pf->width);
+ EMGD_DEBUG("Incoming FB Height = %u", pf->height);
+ EMGD_DEBUG("Incoming FB Pitch = %u", pf->screen_pitch);
+
+ /* Check Plane information */
+ if(pf != NULL) {
+ fb_info = &mode_context->fw_info->fb_info[index];
+ ret = TRUE;
+ /* the incoming pitch=0, since it won't be filled until FB is allocated, calculating it now, so that
+ * it can be compared with the fw pitch */
+ in_pitch = (IGD_PF_DEPTH(pf->pixel_format) * pf->width) >> 3;
+
+ /* Pitch for both PLB and TNC requires 64-byte alignment */
+ in_pitch = ALIGN(in_pitch, 64);
+
+ if(fb_info->screen_pitch != in_pitch) {
+
+ /* If width, height or pitch is different
+ * Don't have to turn-off pipe, just update
+ * the registers with the new values.
+ * Later we just call program_plane to update
+ * the registers.
+ */
+ mode_context->fw_info->program_plane = 1;
+ }
+
+ }
+
+ EMGD_DEBUG(" ");
+ EMGD_DEBUG("Firmware FB Width = %u", fb_info->width);
+ EMGD_DEBUG("Firmware FB Height = %u", fb_info->height);
+ EMGD_DEBUG("Firmware FB Pitch = %u", fb_info->screen_pitch);
+ EMGD_DEBUG("-----------------------");
+
+ EMGD_DEBUG("value of ret = %d", ret);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* end of query_seamless */
+
+
+/*!
+ * Takes inter-module function calls and calls mode-specific
+ * kms_match_mode.
+ *
+ * @param emgd_encoder
+ * @param fb_info
+ * @param timing
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int igd_kms_match_mode(void *emgd_encoder,
+ void *fb_info,
+ igd_timing_info_h **timing)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ ret = kms_match_mode((emgd_encoder_t *)emgd_encoder,
+ (igd_framebuffer_info_t *)fb_info,
+ (igd_timing_info_t **)timing);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*
+ * Name: toggle_vblank_interrupts
+ *
+ * Description:
+ * Requests/stops requesting for vblank notification interrupts for ports
+ * where blit-batching has been enabled. Called from mode_init, mode_pwr and
+ * emgd_driver_pre_init to enable interrupts if needed, and from mode_pwr and
+ * mode_shutdown to disable the interrupts when shutting down the driver.
+ *
+ * @param status 0 to disable and 1 to enable interrupts
+ *
+ * @return None
+ */
+void toggle_vblank_interrupts(bool status) {
+
+ unsigned long toggle_for;
+ unsigned char * mmio;
+ int i;
+
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ for (i=0; i < IGD_MAX_PORTS; i++) {
+ if(mode_context->batch_blits[i]) {
+ toggle_for = 0;
+ if (i == IGD_PORT_TYPE_SDVOB - 1) {
+ toggle_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2);
+ } else if (i == IGD_PORT_TYPE_LVDS - 1) {
+ toggle_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4);
+ }
+
+ if (toggle_for) {
+
+ if (status) {
+ mode_context->dispatch->full->request_vblanks(toggle_for, mmio);
+ } else {
+ mode_context->dispatch->full->end_request(toggle_for, mmio);
+ }
+ }
+ }
+ }
+
+}
+
+/*
+ * Notifies the user-space of a VBlank event by adding an event to the event
+ * queue of the DRM master file-descriptor
+ */
+void notify_userspace_vblank(struct drm_device *dev, int port)
+{
+
+ drm_emgd_priv_t *devpriv = dev->dev_private;
+ struct drm_pending_vblank_event *e = NULL;
+ struct timeval now;
+ unsigned long flags = 0;
+
+
+ EMGD_TRACE_ENTER;
+
+ if (!(devpriv->drm_master_fd)) {
+ EMGD_DEBUG("DRM master file-descriptor not set - exiting");
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ spin_lock_irqsave(&dev->event_lock,flags);
+
+ /* Check if there is space for new event object */
+ if (devpriv->drm_master_fd->event_space < sizeof(e->event)) {
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ EMGD_DEBUG("No space on file-descriptor event queue");
+ EMGD_TRACE_EXIT;
+ return;
+ }
+ devpriv->drm_master_fd->event_space -= sizeof(e->event);
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ e = OS_ALLOC(sizeof(struct drm_pending_vblank_event));
+ if (e == NULL) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+ devpriv->drm_master_fd->event_space += sizeof(e->event);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ /* Setup event struct */
+ OS_MEMSET(e, 0, sizeof(struct drm_pending_vblank_event));
+ e->event.base.type = DRM_EVENT_VBLANK;
+ e->event.base.length = sizeof(e->event);
+ e->event.user_data = port;
+ e->base.event = &e->event.base;
+ e->base.file_priv = devpriv->drm_master_fd;
+ e->base.destroy = (void (*)(struct drm_pending_event *))kfree;
+
+ do_gettimeofday(&now);
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+
+ /* Add event to the event list */
+ list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+
+ EMGD_TRACE_EXIT;
+
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
new file mode 100755
index 0000000..4db71aa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
@@ -0,0 +1,1347 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: match.c
+ * $Revision: 1.12 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#define CURSOR_DEFAULT_WIDTH 64
+#define CURSOR_DEFAULT_HEIGHT 64
+
+#include <context.h>
+#include <igd_init.h>
+#include <io.h>
+#include <memory.h>
+#include <edid.h>
+#include <pi.h>
+
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <mode.h>
+#include <config.h>
+
+#include "match.h"
+
+
+#define MATCH_MOD(x) ((x>0)?x:-x)
+#define MATCH_EXACT 0x01
+#define MATCH_NATIVE 0x02
+#define MATCH_CENTER 0x10
+#define MATCH_FOR_VGA 0x20
+
+extern igd_timing_info_t vga_timing_table[];
+extern igd_timing_info_t crt_timing_table[];
+static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
+
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Local variables */
+#ifndef CONFIG_MICRO
+igd_cursor_info_t default_cursor = {
+ CURSOR_DEFAULT_WIDTH,
+ CURSOR_DEFAULT_HEIGHT,
+ CONFIG_DEFAULT_PF,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, {0, 0, 0, 0}, IGD_CURSOR_ON, 0, 0, 0, 0
+};
+
+/*!
+ *
+ * @param cursor_info
+ * @param display
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int validate_cursor(igd_cursor_info_t *cursor_info,
+ igd_display_context_t *display)
+{
+ unsigned long *list_pfs;
+ igd_display_pipe_t *pipe = (igd_display_pipe_t *)(display->pipe);
+
+ EMGD_TRACE_ENTER;
+ if (pipe) {
+ if (pipe->cursor) {
+ list_pfs = pipe->cursor->pixel_formats;
+
+ while (*list_pfs) {
+ if (cursor_info->pixel_format == *list_pfs) {
+ return 0;
+ }
+ list_pfs++;
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return -IGD_INVAL;
+}
+#endif
+
+/*!
+ *
+ * @param timing
+ * @param pt_info
+ *
+ * @return void
+ */
+static void fill_pt(
+ igd_timing_info_t *timing,
+ pigd_display_info_t pt_info)
+{
+ unsigned long flags;
+
+ EMGD_DEBUG("fill_pt Entry");
+
+ /* preserve existing pt_info flags */
+ flags = pt_info->flags;
+
+ /* Simply memcpy the structures and fix up the flags */
+ OS_MEMCPY(pt_info, timing, sizeof(igd_timing_info_t));
+
+ pt_info->flags |= flags;
+
+ /* pt_info doesn't require a IGD_MODE_VESA flag, so clear IGD_MODE_VESA
+ * Setting this flag creates issues in match mode. */
+ pt_info->flags &= ~IGD_MODE_VESA;
+ return;
+}
+
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param timing_table
+ * @param pt_info
+ * @param type
+ *
+ * @return NULL on failure
+ * @return timing on success
+ */
+igd_timing_info_t *kms_match_resolution(
+ emgd_encoder_t *emgd_encoder,
+ igd_timing_info_t *timing_table,
+ igd_display_info_t *pt_info,
+ int type)
+{
+ struct drm_device *dev = NULL;
+ igd_timing_info_t *timing = NULL;
+ igd_timing_info_t *match = NULL;
+ igd_timing_info_t *native_match = NULL;
+ struct drm_encoder *encoder = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_crtc *crtc = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ pt_info->width, pt_info->height, pt_info->refresh,
+ pt_info->mode_number);
+
+ encoder = &emgd_encoder->base;
+ dev = encoder->dev;
+ timing = timing_table;
+ port = emgd_encoder->igd_port;
+ match = NULL;
+
+ /*
+ * Note on Native matching.
+ * The Ideal thing is for a fp_native_dtd to already be marked as such.
+ * If there is no native timing indicated then we must choose what is
+ * most likely correct.
+ * If the mode is not VGA then we should choose any DTD that closely
+ * matches the mode being set. Failing that we should choose any timing
+ * that closely matches the mode.
+ * If the mode is VGA then we should take the current mode as it is
+ * more likely correct.
+ */
+ if(type == MATCH_NATIVE) {
+ if(port->fp_native_dtd) {
+ EMGD_DEBUG("Returning quick with a native match");
+
+ EMGD_DEBUG("NATIVE Width=%d, height=%d, refresh=%d mode_num=0x%x",
+ port->fp_native_dtd->width, port->fp_native_dtd->height,
+ port->fp_native_dtd->refresh, port->fp_native_dtd->mode_number);
+
+ return port->fp_native_dtd;
+ }
+ if((pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->mode_number <= 0x13)) {
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == encoder->crtc) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+ if(pipe->timing) {
+ native_match = pipe->timing;
+ }
+ }
+ }
+ }
+ }
+
+ while (timing->width != IGD_TIMING_TABLE_END) {
+ if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
+ timing++;
+ continue;
+ }
+
+ if(type == MATCH_NATIVE) {
+ if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
+ port->fp_native_dtd = timing;
+ return timing;
+ }
+
+ if(port->fp_info) {
+ /*
+ * We may have only fp_width and fp_height which is really
+ * not enough information to be useful. If we find a
+ * matching width and height we'll keep the first one while
+ * still hoping to find an actual native mode later.
+ */
+ if(!match &&
+ (port->fp_info->fp_width ==
+ (unsigned long)timing->width) &&
+ (port->fp_info->fp_height ==
+ (unsigned long)timing->height)) {
+ match = timing;
+ }
+ } else {
+ /*
+ * Keep a match because in the event that we never find a
+ * native DTD then we will just take the exact match.
+ */
+ if(!match &&
+ (timing->width == pt_info->width) &&
+ (timing->height == pt_info->height) &&
+ (timing->refresh == pt_info->refresh)) {
+ match = timing;
+ }
+ }
+
+ /*
+ * If it is a DTD then keep it only if it is better than any
+ * found before.
+ */
+ if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
+ if(native_match) {
+ if(MATCH_MOD((int)(pt_info->width*pt_info->height) -
+ (native_match->width * native_match->height)) >
+ MATCH_MOD((int)(pt_info->width*pt_info->height) -
+ (timing->width*timing->height))) {
+ native_match = timing;
+ }
+ } else {
+ native_match = timing;
+ }
+ }
+ } else if (type == MATCH_EXACT) {
+ /*
+ * Looking for an exact match. For VGA/VESA it must match
+ * mode number. Otherwise it must match width, height, refresh
+ * etc.
+ */
+ if(pt_info->flags & IGD_MODE_VESA) {
+ /* ((timing->mode_info_flags & IGD_MODE_VESA)) */
+ if((pt_info->mode_number == timing->mode_number) &&
+ (!pt_info->refresh ||
+ (pt_info->refresh == timing->refresh))) {
+ match = timing;
+ break;
+ }
+ } else {
+ /* If exact match found, then break the loop */
+ if((timing->width == pt_info->width) &&
+ (timing->height == pt_info->height) &&
+ (timing->refresh == pt_info->refresh) &&
+ (
+ (timing->mode_info_flags &
+ (IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+ IGD_LINE_DOUBLE)) ==
+ (pt_info->flags &
+ (IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+ IGD_LINE_DOUBLE)))) {
+ match = timing;
+
+ /* If exact match found, then break the loop */
+ if ((timing->mode_info_flags & PD_MODE_DTD_USER) ||
+ (timing->mode_info_flags & PD_MODE_DTD)) {
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* Center needs only to be bigger. Aspect ratio doesn't matter. */
+ /*
+ * Note: The timings have to be big enough to fit the pt_info
+ * including any pixel double flags. VGA modes will sometimes be
+ * pixel doubled and need to be centered in a pipe that is double
+ * in size.
+ *
+ * Note2: 720x400 VGA modes can be centered in 640x480 with a
+ * special hardware config that drops every 9th pixel. Only do
+ * this when requested.
+ */
+ else if(type & MATCH_CENTER) {
+ unsigned short eff_width = pt_info->width;
+ unsigned short eff_height = pt_info->height;
+
+ if(type & MATCH_FOR_VGA) {
+ /*
+ * 720x400 is a magic mode that means all VGA modes are supported
+ * always use that mode for centering if found.
+ */
+ if((timing->width == 720) && (timing->height == 400)) {
+ EMGD_DEBUG("Returning with a magic VGA mode");
+ return timing;
+ }
+ if(pt_info->flags & IGD_PIXEL_DOUBLE) {
+ eff_width *= 2;
+ }
+ if(pt_info->flags & IGD_LINE_DOUBLE) {
+ eff_height *= 2;
+ }
+ if((eff_width == 720) &&
+ (port->port_features & IGD_VGA_COMPRESS)) {
+ eff_width = 640;
+ }
+ }
+
+ if((timing->width >= eff_width) &&
+ (timing->height >= eff_height) &&
+ (timing->mode_info_flags & IGD_SCAN_INTERLACE) ==
+ (pt_info->flags & IGD_SCAN_INTERLACE)) {
+ if(match) {
+ /* Check for tighter fit */
+ if((match->width > timing->width) ||
+ (match->height > timing->height)) {
+ match = timing;
+ }
+ /* Try to match refreshrate as well */
+ if((match->width == timing->width) &&
+ (match->height == timing->height) &&
+ (pt_info->refresh == timing->refresh)){
+ match = timing;
+ }
+ } else {
+ match = timing;
+ }
+ }
+ }
+ timing++;
+ }
+
+ if(native_match) {
+ EMGD_DEBUG("Returning with a native match");
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ native_match->width, native_match->height, native_match->refresh,
+ native_match->mode_number);
+ return native_match;
+ }
+ if (!match) {
+ EMGD_DEBUG("Returning with NO match");
+ return NULL;
+ }
+
+ EMGD_DEBUG("Returning with a match");
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ match->width, match->height, match->refresh, match->mode_number);
+ return match;
+} /* end match_resolution */
+
+
+
+/*!
+ * Match the fb and pt structures to a Mode Structure from the table.
+ * When a mode is found update the input structures to reflect the
+ * values found.
+ *
+ * If the frambuffer is smaller than the timings requested, then we
+ * modify the timings so that the framebuffer will be centered. That is,
+ * unless we are asked to upscale the framebuffer to fit the timings requested.
+ *
+ * In the case of LVDS both centering and scaling can happen. If the mode
+ * is in the list it will be scaled to the Native Timings. If the mode
+ * is not in the list (common or VGA) it will be centered in the next larger
+ * supported mode and then scaled to the native timings.
+ *
+ * Centering is always indicated by returning the timings that should be
+ * programmed to the pipe. The timings will then have their extension pointer
+ * set to point to the centered timings. For centering with scaling the
+ * first extension pointer will contain the scalable timings and the
+ * second will contain the centering timings. The static "scaled_timings"
+ * data structure will be used when the scaled timings need to be
+ * created on the fly due to a framebuffer that is smaller than the
+ * timings.
+ *
+ * FIXME: There is a lot of mentioning of VGA modes in this function from
+ * an earlier implementation of this feature. The VGA-related code may
+ * not be relevant anymore if we are not building the VBIOS.
+ *
+ * @param emgd_encoder [IN] Encoder expected to have a mode change
+ * @param fb_info [IN] Dimension of the FB to be displayed
+ * @param timing [OUT] Best matched timing
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int kms_match_mode (
+ emgd_encoder_t *emgd_encoder,
+ igd_framebuffer_info_t *fb_info,
+ igd_timing_info_t **timing)
+{
+ struct drm_device *dev;
+ struct drm_encoder *encoder;
+ igd_display_port_t *port;
+ igd_timing_info_t *timing_table;
+ igd_timing_info_t *exact_timing = NULL;
+ igd_timing_info_t *pipe_timing = NULL;
+ igd_timing_info_t *user_timing = NULL;
+ igd_timing_info_t *native_timing = NULL;
+ igd_timing_info_t *vga_timing = NULL;
+ igd_timing_info_t *vesa_timing = NULL;
+ igd_display_info_t *pt_info = NULL;
+ struct drm_crtc *crtc = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ short cntr_dff_w = 0;
+ short cntr_dff_h = 0;
+ unsigned long upscale = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ encoder = &emgd_encoder->base;
+ dev = encoder->dev;
+ port = emgd_encoder->igd_port;
+ pt_info = port->pt_info;
+ timing_table = port->timing_table;
+
+ if(!pt_info) {
+ EMGD_ERROR("NULL Port info detected, returning");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Check for default case */
+ if (!(pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->width == 0) && (pt_info->height == 0)) {
+ EMGD_DEBUG("Display Info width, height are zero, using default case");
+ pt_info->width = CONFIG_DEFAULT_WIDTH;
+ pt_info->height = CONFIG_DEFAULT_HEIGHT;
+ }
+
+ EMGD_DEBUG("Checking for exact mode match");
+ exact_timing = kms_match_resolution(emgd_encoder, timing_table, pt_info,
+ MATCH_EXACT);
+
+ /*
+ * At this point we have one of these cases:
+ * 1) Found an exact match, VGA, VESA or other.
+ * -> Go check for FB centering and finish up.
+ * 2) Found nothing
+ * -> Check for VGA/VESA mode to center.
+ * -> Check common modes.
+ */
+ if(exact_timing) {
+ pipe_timing = exact_timing;
+ user_timing = exact_timing;
+ pipe_timing->extn_ptr = NULL;
+ } else {
+ /* No match found? Is it VGA? */
+ if( (pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->mode_number < 0x1D) ){
+ EMGD_DEBUG("Checking for exact match in VGA table");
+ /* this only happens if it was a VGA mode number */
+ pt_info->refresh = 0;
+ vga_timing = kms_match_resolution(emgd_encoder, vga_timing_table,
+ pt_info, MATCH_EXACT);
+
+ if(!vga_timing) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ vga_timing->extn_ptr = NULL;
+ /* We got something sane that needs to be centered */
+ user_timing = vga_timing;
+ fill_pt(vga_timing,pt_info);
+
+ /* continue at the bottom where we have
+ * pipe_timing = NULL, so we will look
+ * for centered timings for pt_info and
+ * use cmn_vga_timings to tell kms_match_resolution
+ * to take into account special VGA mode
+ * centering regulations
+ */
+ }
+ }
+
+ /* Find UPSCALING attr value
+ * this PI func will not modify value of upscale if attr does not exist */
+ pi_pd_find_attr_and_value(port,
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+
+
+ if(!pipe_timing){
+ /* At this point, one of 2 things has happenned:
+ * - we have a mode request that we could not match exactly.
+ * and it WASNT a VESA_MODE number request.
+ * - we have a request based on VESA_MODE number (maybe from
+ * VBIOS IAL) and we could not get a exact match from the
+ * port_timing_table, but we did get a match from the vga-
+ * timing_table.
+ * In this case, there is one thing to do - MATCH_CENTER. Match
+ * resolution will handle it this way:
+ * - if its VESA MODE number based, we only need to get
+ * the best (tightest) match if its VGA OR DONT match
+ * if its one of those magic timings
+ * - Else, we need to get the best (tightest) match, AND
+ * we need to center requested timings in that tightest fitting
+ * timing. But wait! This could mean if the requested pt_info
+ * is bigger than anything in the port timing table, we have
+ * no choice but to fail.
+ */
+ unsigned char match_type = MATCH_CENTER;
+
+ EMGD_DEBUG("Checking for a safe centered match");
+ if(vga_timing) {
+ match_type |= MATCH_FOR_VGA;
+ } else if(pt_info->flags & IGD_MODE_VESA) {
+ /* if a vesa mode number was requested...
+ * and we are centering that mode, we
+ * need to get the common mode fb size
+ * in case we need it later for VBIOS
+ * which doesnt populate the FBInfo
+ */
+ vesa_timing = kms_match_resolution(emgd_encoder, crt_timing_table,
+ pt_info, MATCH_EXACT);
+ }
+
+ if (upscale && vga_timing) {
+ /* If port supports upscaling and match is called for VGA,
+ * then center vga mode resolution directly in the native mode
+ * instead of centering VGA in another resolution */
+ pipe_timing = vga_timing;
+ } else {
+ pipe_timing = kms_match_resolution(emgd_encoder, timing_table,
+ pt_info, match_type);
+ /* This can happen if there is a spurious pt_info from IAL */
+ if (!pipe_timing) {
+ return -IGD_ERROR_INVAL;
+ }
+ pipe_timing->extn_ptr = vga_timing;
+ /* for the case of non VGA mode call,
+ * at this point, vga_timing is NULL
+ */
+ }
+
+ if(!vga_timing) {
+ user_timing = pipe_timing;
+ }
+ }
+
+ /*
+ * At this point pipe_timing is what we are going to program the
+ * pipe to roughly speaking. If there is a common timing then we
+ * want it centered in the pipe_timing.
+ *
+ * If the framebuffer is smaller than the timings then we need to
+ * generate a centered set of timings by copying the pipe timings
+ * and shifting them a bit.
+ *
+ * If fb width and height are zero just assume that we want it to
+ * match the timings and make up a pixel format. This is mostly because
+ * VGA/VESA modes will just be set by number. We don't know their size
+ * until we look up the number.
+ */
+ if(fb_info) {
+ /*
+ * fb_info is sometimes NULL when just testing something.
+ */
+ if(!fb_info->pixel_format) {
+ /* Ugly VGA modes, it doesn't matter */
+ fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
+ }
+ if(!fb_info->width) {
+ if(vga_timing) {
+ fb_info->width = vga_timing->width;
+ fb_info->height = vga_timing->height;
+ } else {
+ if(!vesa_timing){
+ vesa_timing = pipe_timing;
+ /* in case vesa_timing is false set it to
+ * pipe_timing so we dont need to check for
+ * validity later, when increasing fb size for
+ * VBIOS in clone mode (see 18 lines below)
+ */
+ }
+ fb_info->width = vesa_timing->width;
+ fb_info->height = vesa_timing->height;
+ }
+ }
+
+ /*
+ * VGA common timings are centered in pipe timings by hardware.
+ * Otherwise we need to adjust the timings when centering is
+ * needed.
+ */
+ if (!vga_timing) {
+ /*
+ * For VBIOS clone modes the FB should be the biggest mode
+ * if this is the second match we may need to update the fb
+ * data structure.
+ */
+ if(fb_info->flags & IGD_VBIOS_FB) {
+ if ((fb_info->width < vesa_timing->width) ||
+ (fb_info->height < vesa_timing->height)) {
+ fb_info->width = vesa_timing->width;
+ fb_info->height = vesa_timing->height;
+ }
+ }
+
+
+ /* Do centering if fb is smaller than timing except on TV */
+ if ((fb_info->width < pipe_timing->width) ||
+ (fb_info->height < pipe_timing->height)) {
+ unsigned short temp_width = pipe_timing->width;
+ unsigned short temp_height = pipe_timing->height;
+ /* Normally, we should NOT be in here. All IALs only
+ * are supposed to request for timings that ARE surely
+ * supported by the HAL,... i.e. query the list of
+ * supported timings by the port first!
+ *
+ * The exception would be if the IAL is purposely
+ * asking for CENTERING!!! (pt_info's that were not
+ * part of the supported mode list). This could indicate an
+ * error or an explicit request for VESA centering!.
+ */
+
+ /* let's use these 2 variables as flags... and do the
+ * actual "centering" of the timings later since we do
+ * also need to acomodate native timings as well
+ */
+ /* NOTE: we could never be in here in fb_info was NULL */
+ cntr_dff_w = (pipe_timing->width - fb_info->width) / 2;
+ cntr_dff_h = (pipe_timing->height - fb_info->height) / 2;
+
+ /* Dont forget to use a different storage sice we dont
+ * want to change the original (and to be used later)
+ * ports mode list timings
+ */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == encoder->crtc) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+
+ OS_MEMCPY(&scaled_timing[(pipe->pipe_num)],
+ pipe_timing, sizeof(igd_timing_info_t));
+ pipe_timing = &scaled_timing[(pipe->pipe_num)];
+ }
+ }
+
+ if(port->pd_type != PD_DISPLAY_TVOUT ) {
+ /* TV display don't like changed pipe actives,
+ * Updating syncs work for TV centering */
+ if (fb_info->width < temp_width) {
+ pipe_timing->width = (unsigned short)fb_info->width;
+ pipe_timing->hblank_start -= cntr_dff_w;
+ pipe_timing->hblank_end -= cntr_dff_w;
+ }
+
+ if (fb_info->height < temp_height) {
+ pipe_timing->height = (unsigned short)fb_info->height;
+ pipe_timing->vblank_start -= cntr_dff_h;
+ pipe_timing->vblank_end -= cntr_dff_h;
+ }
+ }
+
+ if (fb_info->width < temp_width) {
+ pipe_timing->hsync_start -= cntr_dff_w;
+ pipe_timing->hsync_end -= cntr_dff_w;
+ }
+
+ if (fb_info->height < temp_height) {
+ pipe_timing->vsync_start -= cntr_dff_h;
+ pipe_timing->vsync_end -= cntr_dff_h;
+ }
+ }
+ }
+ }
+
+ if(upscale) {
+ /* Get the native timings */
+ EMGD_DEBUG("Checking for Native LVDS match for scaling");
+ native_timing = kms_match_resolution(emgd_encoder, timing_table,
+ pt_info, MATCH_NATIVE);
+ if(native_timing && (native_timing != pipe_timing)) {
+ native_timing->extn_ptr = pipe_timing;
+ pipe_timing = native_timing;
+ }
+ }
+
+ /*
+ * Match mode returns as follows:
+ * In case of VGA setmode:
+ * 1) We will end up with either:
+ * magic->vga --- For displays supports native VGA
+ * or
+ * native->vga --- Upscaling displays
+ * or
+ * pipe->vga --- For other displays
+ *
+ * 2) In case of regular setmode:
+ * pipe --- For regular displays
+ * or
+ * native->vesa --- Upscaling displays
+ *
+ * Note: 1) Here "pipe" can be munged if centering is required.
+ * 2) "vesa" is the requested mode, native is the native timing
+ * of the display.
+ */
+
+ /*
+ * Update Input Structures with values found
+ * Note: This might not be what is going to be programmed. It is what
+ * the user thinks they set. Scaling or centering could have altered
+ * that.
+ */
+ fill_pt(user_timing, pt_info);
+ *timing = pipe_timing;
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+
+/*!
+ *
+ * @param display
+ * @param timing_table
+ * @param pt_info
+ * @param type
+ *
+ * @return NULL on failure
+ * @return timing on success
+ */
+static igd_timing_info_t *match_resolution(
+ igd_display_context_t *display,
+ igd_timing_info_t *timing_table,
+ igd_display_info_t *pt_info,
+ int type)
+{
+ igd_timing_info_t *timing;
+ igd_timing_info_t *match;
+ igd_timing_info_t *native_match = NULL;
+ igd_display_port_t *port;
+
+ EMGD_DEBUG("Enter match_resolution");
+
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ pt_info->width, pt_info->height, pt_info->refresh,
+ pt_info->mode_number);
+
+ timing = timing_table;
+ match = NULL;
+ port = PORT_OWNER(display);
+
+ /*
+ * Note on Native matching.
+ * The Ideal thing is for a fp_native_dtd to already be marked as such.
+ * If there is no native timing indicated then we must choose what is
+ * most likely correct.
+ * If the mode is not VGA then we should choose any DTD that closely
+ * matches the mode being set. Failing that we should choose any timing
+ * that closely matches the mode.
+ * If the mode is VGA then we should take the current mode as it is
+ * more likely correct.
+ */
+ if(type == MATCH_NATIVE) {
+ if(port->fp_native_dtd) {
+ EMGD_DEBUG("Returning quick with a native match");
+
+ EMGD_DEBUG("NATIVE Width=%d, height=%d, refresh=%d mode_num=0x%x",
+ port->fp_native_dtd->width, port->fp_native_dtd->height,
+ port->fp_native_dtd->refresh, port->fp_native_dtd->mode_number);
+
+ return port->fp_native_dtd;
+ }
+ if((pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->mode_number <= 0x13)) {
+ if(PIPE(display)->timing) {
+ native_match = PIPE(display)->timing;
+ }
+ }
+ }
+
+ while (timing->width != IGD_TIMING_TABLE_END) {
+ if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
+ timing++;
+ continue;
+ }
+
+ if(type == MATCH_NATIVE) {
+ if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
+ port->fp_native_dtd = timing;
+ return timing;
+ }
+
+ if(port->fp_info) {
+ /*
+ * We may have only fp_width and fp_height which is really
+ * not enough information to be useful. If we find a
+ * matching width and height we'll keep the first one while
+ * still hoping to find an actual native mode later.
+ */
+ if(!match &&
+ (port->fp_info->fp_width ==
+ (unsigned long)timing->width) &&
+ (port->fp_info->fp_height ==
+ (unsigned long)timing->height)) {
+ match = timing;
+ }
+ } else {
+ /*
+ * Keep a match because in the event that we never find a
+ * native DTD then we will just take the exact match.
+ */
+ if(!match &&
+ (timing->width == pt_info->width) &&
+ (timing->height == pt_info->height) &&
+ (timing->refresh == pt_info->refresh)) {
+ match = timing;
+ }
+ }
+
+ /*
+ * If it is a DTD then keep it only if it is better than any
+ * found before.
+ */
+ if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
+ if(native_match) {
+ if(MATCH_MOD((int)(pt_info->width*pt_info->height) -
+ (native_match->width * native_match->height)) >
+ MATCH_MOD((int)(pt_info->width*pt_info->height) -
+ (timing->width*timing->height))) {
+ native_match = timing;
+ }
+ } else {
+ native_match = timing;
+ }
+ }
+ } else if (type == MATCH_EXACT) {
+ /*
+ * Looking for an exact match. For VGA/VESA it must match
+ * mode number. Otherwise it must match width, height, refresh
+ * etc.
+ */
+ if(pt_info->flags & IGD_MODE_VESA) {
+ /* ((timing->mode_info_flags & IGD_MODE_VESA)) */
+ if((pt_info->mode_number == timing->mode_number) &&
+ (!pt_info->refresh ||
+ (pt_info->refresh == timing->refresh))) {
+ match = timing;
+ break;
+ }
+ } else {
+ /* If exact match found, then break the loop */
+ if((timing->width == pt_info->width) &&
+ (timing->height == pt_info->height) &&
+ (timing->refresh == pt_info->refresh) &&
+ (
+ (timing->mode_info_flags &
+ (IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+ IGD_LINE_DOUBLE)) ==
+ (pt_info->flags &
+ (IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+ IGD_LINE_DOUBLE)))) {
+ match = timing;
+
+ /* If exact match found, then break the loop */
+ if ((timing->mode_info_flags & PD_MODE_DTD_USER) ||
+ (timing->mode_info_flags & PD_MODE_DTD)) {
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* Center needs only to be bigger. Aspect ratio doesn't matter. */
+ /*
+ * Note: The timings have to be big enough to fit the pt_info
+ * including any pixel double flags. VGA modes will sometimes be
+ * pixel doubled and need to be centered in a pipe that is double
+ * in size.
+ *
+ * Note2: 720x400 VGA modes can be centered in 640x480 with a
+ * special hardware config that drops every 9th pixel. Only do
+ * this when requested.
+ */
+ else if(type & MATCH_CENTER) {
+ unsigned short eff_width = pt_info->width;
+ unsigned short eff_height = pt_info->height;
+
+ if(type & MATCH_FOR_VGA) {
+ /*
+ * 720x400 is a magic mode that means all VGA modes are supported
+ * always use that mode for centering if found.
+ */
+ if((timing->width == 720) && (timing->height == 400)) {
+ EMGD_DEBUG("Returning with a magic VGA mode");
+ return timing;
+ }
+ if(pt_info->flags & IGD_PIXEL_DOUBLE) {
+ eff_width *= 2;
+ }
+ if(pt_info->flags & IGD_LINE_DOUBLE) {
+ eff_height *= 2;
+ }
+ if((eff_width == 720) &&
+ (port->port_features & IGD_VGA_COMPRESS)) {
+ eff_width = 640;
+ }
+ }
+
+ if((timing->width >= eff_width) &&
+ (timing->height >= eff_height) &&
+ (timing->mode_info_flags & IGD_SCAN_INTERLACE) ==
+ (pt_info->flags & IGD_SCAN_INTERLACE)) {
+ if(match) {
+ /* Check for tighter fit */
+ if((match->width > timing->width) ||
+ (match->height > timing->height)) {
+ match = timing;
+ }
+ /* Try to match refreshrate as well */
+ if((match->width == timing->width) &&
+ (match->height == timing->height) &&
+ (pt_info->refresh == timing->refresh)){
+ match = timing;
+ }
+ } else {
+ match = timing;
+ }
+ }
+ }
+ timing++;
+ }
+
+ if(native_match) {
+ EMGD_DEBUG("Returning with a native match");
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ native_match->width, native_match->height, native_match->refresh,
+ native_match->mode_number);
+ return native_match;
+ }
+ if (!match) {
+ EMGD_DEBUG("Returning with NO match");
+ return NULL;
+ }
+
+ EMGD_DEBUG("Returning with a match");
+ EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+ match->width, match->height, match->refresh, match->mode_number);
+ return match;
+} /* end match_resolution */
+
+
+
+/*!
+ * Match the fb and pt structures to a Mode Structure from the table.
+ * When a mode is found update the input structures to reflect the
+ * values found.
+ *
+ * Notes:
+ * Match mode has several options for what it can do. Foremost it should
+ * attempt to find a mode matching the requested one from the timing table
+ * provided. If the mode requested is not in the list this means one of
+ * two things.
+ * 1) The IAL is calling without checking modes. It is just passing down
+ * something that a user asked for. This is ok but we need to be safe so
+ * we return the next smaller mode with the same aspect ratio.
+ *
+ * 2) The IAL is requesting a very common "required" mode even though the
+ * port doesn't support it. In this case it should be in the static common
+ * modes table and can be centered in the next larger timings in the
+ * mode table.
+ *
+ * If the Frambuffer is smaller than the timings requested a fake set of
+ * centered timings is returned to program the pipe.
+ *
+ * In the case of VGA modes. If the mode is in the mode table everything is
+ * fine and we just return that. If it is not in the table we find the next
+ * larger suitable mode and prepare to center in that mode. Using the static
+ * timings from the VGA table as the VGA mode. We do not need to generate
+ * a fake set of timings because VGA will center itself automatically in
+ * hardware.
+ *
+ * In the case of LVDS both centering and scaling can happen. If the mode
+ * is in the list it will be scaled to the Native Timings. If the mode
+ * is not in the list (common or VGA) it will be centered in the next larger
+ * supported mode and then scaled to the native timings.
+ *
+ * Centering is always indicated by returning the timings that should be
+ * programmed to the pipe. The timings will then have their extension pointer
+ * set to point to the centered timings. For centering with scaling the
+ * first extension pointer will contain the scalable timings and the
+ * second will contain the centering timings. The static "scaled_timings"
+ * data structure will be used when the scaled timings need to be
+ * created on the fly due to a Framebuffer that is smaller than the
+ * timings.
+ *
+ * @param display
+ * @param timing_table
+ * @param fb_info
+ * @param pt_info
+ * @param timing
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int match_mode (
+ igd_display_context_t *display,
+ igd_timing_info_t *timing_table,
+ igd_framebuffer_info_t *fb_info,
+ igd_display_info_t *pt_info,
+ igd_timing_info_t **timing)
+{
+ igd_timing_info_t *exact_timing = NULL;
+ igd_timing_info_t *pipe_timing = NULL;
+ igd_timing_info_t *user_timing = NULL;
+ igd_timing_info_t *native_timing = NULL;
+ igd_timing_info_t *vga_timing = NULL;
+ igd_timing_info_t *vesa_timing = NULL;
+ short cntr_dff_w = 0;
+ short cntr_dff_h = 0;
+ unsigned long upscale = 0;
+
+ EMGD_DEBUG("Enter Match Mode");
+
+ if(!pt_info) {
+ EMGD_ERROR("NULL Port info detected, returning");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Check for default case */
+ if (!(pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->width == 0) && (pt_info->height == 0)) {
+ EMGD_DEBUG("Display Info width, height are zero, using default case");
+ pt_info->width = CONFIG_DEFAULT_WIDTH;
+ pt_info->height = CONFIG_DEFAULT_HEIGHT;
+ }
+
+ EMGD_DEBUG("Checking for exact mode match");
+ exact_timing = match_resolution(display, timing_table, pt_info,
+ MATCH_EXACT);
+ /*
+ * At this point we have one of these cases:
+ * 1) Found an exact match, VGA, VESA or other.
+ * -> Go check for FB centering and finish up.
+ * 2) Found nothing
+ * -> Check for VGA/VESA mode to center.
+ * -> Check common modes.
+ */
+ if(exact_timing) {
+ pipe_timing = exact_timing;
+ user_timing = exact_timing;
+ pipe_timing->extn_ptr = NULL;
+ } else {
+ /* No match found? Is it VGA? */
+ if( (pt_info->flags & IGD_MODE_VESA) &&
+ (pt_info->mode_number < 0x1D) ){
+ EMGD_DEBUG("Checking for exact match in VGA table");
+ /* this only happens if it was a VGA mode number */
+ pt_info->refresh = 0;
+ vga_timing = match_resolution(display, vga_timing_table,
+ pt_info, MATCH_EXACT);
+
+ if(!vga_timing) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ vga_timing->extn_ptr = NULL;
+ /* We got something sane that needs to be centered */
+ user_timing = vga_timing;
+ fill_pt(vga_timing,pt_info);
+
+ /* continue at the bottom where we have
+ * pipe_timing = NULL, so we will look
+ * for centered timings for pt_info and
+ * use cmn_vga_timings to tell match_resolution
+ * to take into account special VGA mode
+ * centering regulations
+ */
+ }
+ }
+
+ /* Find UPSCALING attr value*/
+ pi_pd_find_attr_and_value(PORT_OWNER(display),
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ /* this PI func will not modify value of upscale if attr does not exist */
+
+ if(!pipe_timing){
+ /* At this point, one of 2 things has happenned:
+ * - we have a mode request that we could not match exactly.
+ * and it WASNT a VESA_MODE number request.
+ * - we have a request based on VESA_MODE number (maybe from
+ * VBIOS IAL) and we could not get a exact match from the
+ * port_timing_table, but we did get a match from the vga-
+ * timing_table.
+ * In this case, there is one thing to do - MATCH_CENTER. Match
+ * resolution will handle it this way:
+ * - if its VESA MODE number based, we only need to get
+ * the best (tightest) match if its VGA OR DONT match
+ * if its one of those magic timings
+ * - Else, we need to get the best (tightest) match, AND
+ * we need to center requested timings in that tightest fitting
+ * timing. But wait! This could mean if the requested pt_info
+ * is bigger than anything in the port timing table, we have
+ * no choice but to fail.
+ */
+ unsigned char match_type = MATCH_CENTER;
+
+ EMGD_DEBUG("Checking for a safe centered match");
+ if(vga_timing) {
+ match_type |= MATCH_FOR_VGA;
+ } else if(pt_info->flags & IGD_MODE_VESA) {
+ /* if a vesa mode number was requested...
+ * and we are centering that mode, we
+ * need to get the common mode fb size
+ * in case we need it later for VBIOS
+ * which doesnt populate the FBInfo
+ */
+ vesa_timing = match_resolution(display, crt_timing_table,
+ pt_info, MATCH_EXACT);
+ }
+
+ if (upscale && vga_timing) {
+ /* If port supports upscaling and match is called for VGA,
+ * then center vga mode resolution directly in the native mode
+ * instead of centering VGA in another resolution */
+ pipe_timing = vga_timing;
+ } else {
+ pipe_timing = match_resolution(display, timing_table, pt_info,
+ match_type);
+ /* This can happen if there is a spurious pt_info from IAL */
+ if (!pipe_timing) {
+ return -IGD_ERROR_INVAL;
+ }
+ pipe_timing->extn_ptr = vga_timing;
+ /* for the case of non VGA mode call,
+ * at this point, vga_timing is NULL
+ */
+ }
+
+ if(!vga_timing) {
+ user_timing = pipe_timing;
+ }
+ }
+
+ /*
+ * At this point pipe_timing is what we are going to program the
+ * pipe to roughly speaking. If there is a common timing then we
+ * want it centered in the pipe_timing.
+ *
+ * If the framebuffer is smaller than the timings then we need to
+ * generate a centered set of timings by copying the pipe timings
+ * and shifting them a bit.
+ *
+ * If fb width and height are zero just assume that we want it to
+ * match the timings and make up a pixel format. This is mostly because
+ * VGA/VESA modes will just be set by number. We don't know their size
+ * until we look up the number.
+ */
+ if(fb_info) {
+ /*
+ * fb_info is sometimes NULL when just testing something.
+ */
+ if(!fb_info->pixel_format) {
+ /* Ugly VGA modes, it doesn't matter */
+ fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
+ }
+ if(!fb_info->width) {
+ if(vga_timing) {
+ fb_info->width = vga_timing->width;
+ fb_info->height = vga_timing->height;
+ } else {
+ if(!vesa_timing){
+ vesa_timing = pipe_timing;
+ /* in case vesa_timing is false set it to
+ * pipe_timing so we dont need to check for
+ * validity later, when increasing fb size for
+ * VBIOS in clone mode (see 18 lines below)
+ */
+ }
+ fb_info->width = vesa_timing->width;
+ fb_info->height = vesa_timing->height;
+ }
+ }
+
+ /*
+ * VGA common timings are centered in pipe timings by hardware.
+ * Otherwise we need to adjust the timings when centering is
+ * needed.
+ */
+ if (!vga_timing) {
+ /*
+ * For VBIOS clone modes the FB should be the biggest mode
+ * if this is the second match we may need to update the fb
+ * data structure.
+ */
+ if(fb_info->flags & IGD_VBIOS_FB) {
+ if ((fb_info->width < vesa_timing->width) ||
+ (fb_info->height < vesa_timing->height)) {
+ fb_info->width = vesa_timing->width;
+ fb_info->height = vesa_timing->height;
+ }
+ }
+
+
+ /* Do centering if fb is smaller than timing except on TV */
+ if ((fb_info->width < pipe_timing->width) ||
+ (fb_info->height < pipe_timing->height)) {
+ unsigned short temp_width = pipe_timing->width;
+ unsigned short temp_height = pipe_timing->height;
+ /* Normally, we should NOT be in here. All IALs only
+ * are supposed to request for timings that ARE surely
+ * supported by the HAL,... i.e. query the list of
+ * supported timings by the port first!
+ *
+ * The exception would be if the IAL is purposely
+ * asking for CENTERING!!! (pt_info's that were not
+ * part of the supported mode list). This could indicate an
+ * error or an explicit request for VESA centering!.
+ */
+
+ /* let's use these 2 variables as flags... and do the
+ * actual "centering" of the timings later since we do
+ * also need to acomodate native timings as well
+ */
+ /* NOTE: we could never be in here in fb_info was NULL */
+ cntr_dff_w = (pipe_timing->width - fb_info->width) / 2;
+ cntr_dff_h = (pipe_timing->height - fb_info->height) / 2;
+
+ /* Dont forget to use a different storage sice we dont
+ * want to change the original (and to be used later)
+ * ports mode list timings
+ */
+ OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
+ pipe_timing,
+ sizeof(igd_timing_info_t));
+
+ pipe_timing = &scaled_timing[(PIPE(display)->pipe_num)];
+
+ if(PORT_OWNER(display)->pd_type != PD_DISPLAY_TVOUT ) {
+ /* TV display don't like changed pipe actives,
+ * Updating syncs work for TV centering */
+ if (fb_info->width < temp_width) {
+ pipe_timing->width = (unsigned short)fb_info->width;
+ pipe_timing->hblank_start -= cntr_dff_w;
+ pipe_timing->hblank_end -= cntr_dff_w;
+ }
+
+ if (fb_info->height < temp_height) {
+ pipe_timing->height = (unsigned short)fb_info->height;
+ pipe_timing->vblank_start -= cntr_dff_h;
+ pipe_timing->vblank_end -= cntr_dff_h;
+ }
+ }
+
+ if (fb_info->width < temp_width) {
+ pipe_timing->hsync_start -= cntr_dff_w;
+ pipe_timing->hsync_end -= cntr_dff_w;
+ }
+
+ if (fb_info->height < temp_height) {
+ pipe_timing->vsync_start -= cntr_dff_h;
+ pipe_timing->vsync_end -= cntr_dff_h;
+ }
+ }
+ }
+ }
+
+ if(upscale) {
+ /* Get the native timings */
+ EMGD_DEBUG("Checking for Native LVDS match for scaling");
+ native_timing = match_resolution(display, timing_table, pt_info,
+ MATCH_NATIVE);
+ if(native_timing && (native_timing != pipe_timing)) {
+ native_timing->extn_ptr = pipe_timing;
+ pipe_timing = native_timing;
+ }
+ }
+
+ /*
+ * Match mode returns as follows:
+ * In case of VGA setmode:
+ * 1) We will end up with either:
+ * magic->vga --- For displays supports native VGA
+ * or
+ * native->vga --- Upscaling displays
+ * or
+ * pipe->vga --- For other displays
+ *
+ * 2) In case of regular setmode:
+ * pipe --- For regular displays
+ * or
+ * native->vesa --- Upscaling displays
+ *
+ * Note: 1) Here "pipe" can be munged if centering is required.
+ * 2) "vesa" is the requested mode, native is the native timing
+ * of the display.
+ */
+
+ /*
+ * Update Input Structures with values found
+ * Note: This might not be what is going to be programmed. It is what
+ * the user thinks they set. Scaling or centering could have altered
+ * that.
+ */
+ fill_pt(user_timing, pt_info);
+ *timing = pipe_timing;
+ EMGD_DEBUG("Return");
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
new file mode 100755
index 0000000..40a6721
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: match.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the mode matching algorithms
+ *-----------------------------------------------------------------------------
+ */
+
+#include <mode.h>
+
+int validate_fb(
+ pigd_framebuffer_info_t fb_info,
+ igd_display_plane_t *plane);
+
+int validate_cursor(
+ igd_cursor_info_t *cursor_info,
+ igd_display_context_t *display);
+
+int match_mode (
+ igd_display_context_t *display,
+ igd_timing_info_t *timing_table,
+ igd_framebuffer_info_t *fb_info,
+ igd_display_info_t *pt_info,
+ igd_timing_info_t **timing);
+
+int kms_match_mode (
+ emgd_encoder_t *emgd_encoder,
+ igd_framebuffer_info_t *fb_info,
+ igd_timing_info_t **timing);
+
+igd_timing_info_t *kms_match_resolution(
+ emgd_encoder_t *emgd_encoder,
+ igd_timing_info_t *timing_table,
+ igd_display_info_t *pt_info,
+ int type);
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
new file mode 100644
index 0000000..c642572
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
@@ -0,0 +1,1772 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_mode.c
+ * $Revision: 1.32 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contains client interface support functions for display allocations
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <config.h>
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+#include <igd_gmm.h>
+#include <igd_pd.h>
+
+#include <debug.h>
+#include <context.h>
+#include <rb.h>
+#include <pd.h>
+#include <intelpci.h>
+#include <dsp.h>
+#include <pi.h>
+#include <pd_init.h>
+#include <dispatch.h>
+#include <mode.h>
+#include <mode_access.h>
+#include <dsp.h>
+#include <utils.h>
+#include <general.h>
+#include <module_init.h>
+
+#include "drm_emgd_private.h"
+#include "match.h"
+#include "mode_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+#ifndef CONFIG_MICRO
+#define TIMING_CHANGED(a,b,c,d,e,f,g) timing_changed(a,b,c,d,e,f,g)
+#define CALCULATE_ELD_INFOFRAMES
+#else
+#define TIMING_CHANGED(a,b,c,d,e,f,g) 1
+#endif /* CONFIG_MICRO */
+
+#define MODE_MIN(x, y) (x<y)?x:y
+
+extern emgd_drm_config_t config_drm;
+
+/*
+ * NOTE: Do not add comma's to this dispatch table. The macro's
+ * remove the entire entry.
+ */
+static dispatch_table_t mode_dispatch[] = {
+ DISPATCH_PLB( &mode_dispatch_plb )
+ DISPATCH_TNC( &mode_dispatch_tnc )
+ DISPATCH_END
+};
+
+
+
+/*
+ * Kernel Mode Setting (KMS) dispatch table
+ */
+static dispatch_table_t mode_kms_dispatch[] = {
+ DISPATCH_PLB( &mode_kms_dispatch_plb )
+ DISPATCH_TNC( &mode_kms_dispatch_tnc )
+ DISPATCH_END
+};
+
+
+
+/*
+ * Do not malloc the context for two reasons.
+ * 1) vBIOS needs to minimize mallocs
+ * 2) Mode context needs to stay around until after all modules are
+ * shut down for the register restore functionality.
+*/
+mode_context_t mode_context[1];
+
+
+#ifndef CONFIG_MICRO
+
+/*!
+ * Check user supplied timing against what is currently
+ * programmed to see if it needs to change. If the timing
+ * isn't going to change, then we don't want to turn off and
+ * reprogram the port.
+ *
+ * NOTE: If this increases the size too much for vbios, then it
+ * could be ifndef CONFIG_MICRO with an else that returns 1. That
+ * would mean vbios wouldn't have these checks and always assume
+ * the timing was changing.
+ *
+ * @param display
+ * @param new_dc DC changes always require port/plane/pipe programming.
+ * @param pt_info User supplied timing info to check.
+ * @param fb_info User supplied framebuffer info.
+ * @param port_number
+ * @param display_mask Which display is being checked.
+ * @param alter flags used to force the alter
+ *
+ * @return 1 timing has changed
+ * @return 0 timing hasn't changed
+ */
+static int timing_changed(igd_display_context_t *display,
+ unsigned long new_dc,
+ unsigned long dc,
+ igd_display_info_t *pt_info,
+ igd_framebuffer_info_t *fb_info,
+ unsigned long display_mask,
+ unsigned long flags)
+{
+ igd_framebuffer_info_t *cfb;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * will this cover every case? Can a change on one display effect
+ * the timings of the other? I don't think so.
+ */
+ if ((new_dc & display_mask) != (dc & display_mask)) {
+ return 1; /* Ports are changing on this display, must re-program. */
+ }
+
+ /*
+ * Make sure the owner port has a pt_info, if not then we'll assume
+ * that it hasn't been programmed yet and thus the timings are going
+ * to change.
+ */
+ if (PORT_OWNER(display)->pt_info == NULL) {
+ return 1;
+ }
+
+ /*
+ * Make sure we have valid timing info. If not, then don't try
+ * and change the timings.
+ */
+ if (!pt_info || !fb_info) {
+ return 0;
+ }
+
+ /*
+ * If the caller really wants to re-program the planes/pipes/ports
+ * then do it
+ */
+
+ if (flags & IGD_FORCE_ALTER) {
+ return 1;
+ }
+
+ /*
+ * Check only width, height, refresh. If these don't match, then we
+ * know that something is changing.
+ */
+
+ if ((pt_info->width == PORT_OWNER(display)->pt_info->width) &&
+ (pt_info->height == PORT_OWNER(display)->pt_info->height) &&
+ (pt_info->refresh == PORT_OWNER(display)->pt_info->refresh)) {
+
+ /* Check framebuffer for changes, fb changes may change timing */
+ if ((cfb = PLANE(display)->fb_info) != NULL) {
+ if ((cfb->width != fb_info->width) ||
+ (cfb->height != fb_info->height) ||
+ (cfb->pixel_format != fb_info->pixel_format) ||
+ ((fb_info->flags^fb_info->flags) &~ IGD_SURFACE_RENDER)){
+ /* Timing ok buf fb_info doesn't match */
+ return 1;
+ }
+ }
+ } else {
+ /* Timing doesn't match */
+ return 1;
+ }
+
+ /* Timing and fb have not changed */
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+#endif
+
+/*!
+ * Update internal data structures for the plane, pipe, and port as
+ * requested. Allocate a new framebuffer if the new parameters do not
+ * match the existing framebuffer.
+ *
+ * @param display
+ * @param port_number
+ * @param timing
+ * @param pt_info User supplied timing info to check.
+ * @param fb_info User supplied framebuffer info.
+ * @param flags
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int mode_update_plane_pipe_ports(
+ igd_display_context_t *display,
+ unsigned short port_number,
+ igd_timing_info_t *timing,
+ igd_framebuffer_info_t *fb_info,
+ igd_display_info_t *pt_info,
+ unsigned long flags)
+{
+ int ret;
+ int alloc_fb;
+ unsigned long size = 0;
+ igd_framebuffer_info_t *plane_fb_info;
+ igd_display_plane_t *mirror;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Port Number (%d)", port_number);
+
+ EMGD_ASSERT( (fb_info || pt_info), "ERROR: fb_info & pt_info are NULL",
+ -IGD_ERROR_INVAL);
+
+ EMGD_ASSERT( PLANE(display)->fb_info, "ERROR: fb_info in plane is NULL",
+ -IGD_ERROR_INVAL);
+
+ plane_fb_info = PLANE(display)->fb_info;
+ mirror = PLANE(display)->mirror;
+
+ /*
+ * If there is a mirror plane (for Clone) and the mirror is populated
+ * then update our plane from the mirror. If the mirror is not populated
+ * then update the mirror from ours.
+ */
+ if (mirror) {
+ if(mirror->fb_info->flags) {
+ OS_MEMCPY(plane_fb_info, mirror->fb_info,
+ sizeof(igd_framebuffer_info_t));
+ } else {
+ OS_MEMCPY(mirror->fb_info, plane_fb_info,
+ sizeof(igd_framebuffer_info_t));
+ }
+ }
+
+ if (PORT(display, port_number)->pt_info == NULL) {
+ if ((PORT(display, port_number)->pt_info = (igd_display_info_t *)
+ OS_ALLOC(sizeof(igd_display_info_t))) == NULL) {
+ EMGD_ERROR_EXIT("unable to alloc a pt_info struct in pipe.");
+ return -IGD_ERROR_INVAL;
+ }
+ }
+
+ /*
+ * If the fb_info was provided, and either we were asked to update
+ * the internal structures via the flags, or we are allocating a new
+ * framebuffer.
+ */
+ if(fb_info && (flags & MODE_UPDATE_PLANE)) {
+
+ /* Assume we will be allocating a FB */
+ alloc_fb = 1;
+
+ /* If the frambuffer parameters are unchanged then do not re-alloc */
+ if((fb_info->width == plane_fb_info->width) &&
+ (fb_info->height == plane_fb_info->height) &&
+ (fb_info->pixel_format == plane_fb_info->pixel_format) &&
+ ((fb_info->flags^plane_fb_info->flags) & ~IGD_SURFACE_RENDER) == 0) {
+ alloc_fb = 0;
+ }
+
+ /* Do not re-alloc a framebuffer if the re-use flag is set. */
+ if(fb_info->flags & IGD_REUSE_FB) {
+ alloc_fb = 0;
+ /* May need to get the MIN_PITCH flags */
+ plane_fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
+ (plane_fb_info->flags & ~IGD_FB_FLAGS_MASK);
+ }
+
+ /*
+ * If we don't have a framebuffer at all then we MUST allocate
+ * one.
+ */
+ if(!plane_fb_info->allocated && !fb_info->allocated) {
+ alloc_fb = 1;
+ }
+
+ EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
+ plane_fb_info->fb_base_offset);
+ if(alloc_fb) {
+ if(plane_fb_info->allocated) {
+ /* Free frame buffer memory */
+ display->context->dispatch.gmm_free(
+ plane_fb_info->fb_base_offset);
+ plane_fb_info->allocated = 0;
+ }
+
+ fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
+ /*
+ * Keep the FB flags, add in Displayable flag and blank out
+ * the rest. This insures that any tiled or usage flags from an
+ * earlier call do not get reused.
+ */
+ fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
+ IGD_SURFACE_DISPLAY;
+
+ /*
+ * Framebuffer allocations must always come from a reservation
+ * if the IAL changes the address the new address must also be
+ * from a reservation.
+ */
+ GMM_SET_DEBUG_NAME("Framebuffer");
+ ret = display->context->dispatch.gmm_alloc_surface(
+ &fb_info->fb_base_offset,
+ fb_info->pixel_format,
+ &fb_info->width,
+ &fb_info->height,
+ &fb_info->screen_pitch,
+ &size,
+ IGD_GMM_ALLOC_TYPE_RESERVATION,
+ &fb_info->flags);
+ if(ret) {
+ EMGD_ERROR_EXIT("Allocation of Front buffer failed: %d", ret);
+ return ret;
+ }
+ fb_info->allocated = 1;
+ /* Set the visible offset to the newly-allocated offset: */
+ fb_info->visible_offset = fb_info->fb_base_offset;
+ } else {
+ /* If not reallocating, use back the offset in plane_fb_info */
+ fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
+ /* We must set the visible offset and screen pitch
+ * to proper value if we use back the plane.
+ */
+ fb_info->visible_offset = fb_info->fb_base_offset;
+ fb_info->screen_pitch = plane_fb_info->screen_pitch;
+ }
+
+ OS_MEMCPY(plane_fb_info, fb_info, sizeof(igd_framebuffer_info_t));
+ plane_fb_info->allocated = 1;
+ EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
+ plane_fb_info->fb_base_offset);
+
+ }
+
+ if(timing && (flags & MODE_UPDATE_PIPE)) {
+ EMGD_DEBUG("Updating pipe timing.");
+ PIPE(display)->timing = timing;
+ PIPE(display)->owner = display;
+ }
+
+ if(pt_info && (flags & MODE_UPDATE_PORT)) {
+ EMGD_DEBUG("OLD_PT========NEW PT ");
+ IGD_PRINTK_PTINFO_2(PORT(display, port_number)->pt_info, pt_info);
+ OS_MEMCPY(PORT(display, port_number)->pt_info, pt_info,
+ sizeof(igd_display_info_t));
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end mode_update_plane_pipe_ports() */
+
+#ifdef CALCULATE_ELD_INFOFRAMES
+
+/*!
+ * Calculates infoframes information top be used by HDMI port drivers
+ *
+ * @param port
+ * @param timing_info
+ * @param temp_cea
+ *
+ * @return 0
+ */
+static int calculate_infoframes(
+ igd_display_port_t *port,
+ igd_timing_info_t *timing_info,
+ cea_extension_t *temp_cea)
+{
+
+ pd_timing_t *cea_timings = NULL, *cea_timing_temp = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ /* VBIOS has no access to CEA timing tables and this is not supported
+ there as well */
+ if(timing_info->mode_info_flags & PD_MODE_CEA){
+ if(timing_info->width != 640 && timing_info->height != 480){
+ port->edid->cea->quantization = HDMI_QUANTIZATION_RGB_220;
+ }
+
+ /* Based on DPG algorithm. If monitors support more than 2 channels
+ for 192Khz or/and 92Khz then set two pixel repeat one.
+ KIV: Add pruning for pixel PIX_REPLICATION_3 if required */
+ if(temp_cea->audio_cap[CAP_192_KHZ].max_channels>2 ||
+ temp_cea->audio_cap[CAP_96_KHZ].max_channels>2){
+ port->edid->cea->pixel_rep = PIX_REPLICATION_1;
+ }
+
+
+ /* Based on HDMI spec 6.7.1 & 6.7.2 */
+ if ((timing_info->width == 720) && ((timing_info->height == 480) ||
+ (timing_info->height== 576))){
+ port->edid->cea->colorimetry = HDMI_COLORIMETRY_ITU601;
+ } else if(((timing_info->width==1280) && (timing_info->height==720)) ||
+ ((timing_info->width == 1920) && (timing_info->height == 1080))){
+ port->edid->cea->colorimetry = HDMI_COLORIMETRY_ITU709;
+ }
+
+ cea_timings = (igd_timing_info_t *) OS_ALLOC(cea_timing_table_size);
+ OS_MEMCPY(cea_timings, cea_timing_table, cea_timing_table_size);
+ cea_timing_temp = cea_timings;
+
+ while (cea_timings->width != IGD_TIMING_TABLE_END){
+ if(cea_timings->width == timing_info->width &&
+ cea_timings->height == timing_info->height &&
+ cea_timings->refresh == timing_info->refresh &&
+ cea_timings->dclk == timing_info->dclk &&
+ (cea_timings->mode_info_flags &
+ (PD_ASPECT_16_9| IGD_SCAN_INTERLACE)) ==
+ (timing_info->mode_info_flags &
+ (PD_ASPECT_16_9| IGD_SCAN_INTERLACE))){
+ port->edid->cea->video_code = cea_timings->mode_number;
+ break;
+ }
+ cea_timings++;
+ }
+
+ OS_FREE(cea_timing_temp);
+
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+#endif /* CALCULATE_ELD_INFOFRAMES */
+
+/*!
+ * Calculates the Edid like data (ELD) if port supports audio transmission
+ *
+ * @param port
+ * @param timing_info
+ *
+ * @return 0
+ */
+int calculate_eld(
+ igd_display_port_t *port,
+ igd_timing_info_t *timing_info)
+{
+ /* Calculate for non-content protected & content protected(Array of 2) */
+#ifdef CALCULATE_ELD_INFOFRAMES
+ unsigned long cal_NPL[2]; /* Number of packer per line calculate*/
+ unsigned long poss_NPL[2]; /* Number of packer per line possible*/
+ unsigned long max_bitRate_2[2],max_bitRate_8[2];
+ unsigned long h_refresh, audio_freq;
+ unsigned char input;
+ int i,j,pix_rep;
+#endif
+ cea_extension_t *temp_cea = NULL ;
+
+ EMGD_TRACE_ENTER;
+ /* Only calculate eld for HDMI port */
+ if((port->pd_driver->type != PD_DISPLAY_HDMI_EXT &&
+ port->pd_driver->type != PD_DISPLAY_HDMI_INT)){
+ return 0;
+ }
+ if(port->firmware_type == PI_FIRMWARE_EDID){
+ temp_cea = (cea_extension_t*)port->edid->cea;
+ }
+ /* Displayid unsupported for now. Uncomment this code when audio
+ information is available for Display ID
+ temp_cea = (&cea_extension_t)port->displayid->cea;*/
+
+ if(temp_cea == NULL){
+ /* CEA data unavailable, display does not have audio capability? */
+ /* We would allocate dummy edid structure and here and we should ony
+ used canned ELD */
+ if(port->edid == NULL) {
+ port->edid = (edid_t *) OS_ALLOC(sizeof(edid_t));
+ OS_MEMSET(port->edid, 0 , (sizeof(edid_t)));
+ }
+
+ port->edid->cea = (cea_extension_t *) OS_ALLOC(sizeof(cea_extension_t));
+ OS_MEMSET(port->edid->cea, 0 , (sizeof(cea_extension_t)));
+ port->edid->cea->canned_eld = 1;
+ temp_cea = (cea_extension_t*)port->edid->cea;
+ port->callback->eld = &(port->edid->cea);
+ }
+
+ /* Default to canned ELD data */
+ temp_cea->LPCM_CAD[0] = 0x9;
+ temp_cea->speaker_alloc_block[0] = 0x1;
+ /* Default 0 Pixel replication */
+ port->edid->cea->pixel_rep = PIX_REPLICATION_0;
+ /* Default */
+ port->edid->cea->colorimetry = HDMI_COLORIMETRY_NODATA;
+ /* Default RGB 256 wuantization full range */
+ port->edid->cea->quantization = HDMI_QUANTIZATION_RGB_256;
+ /* Default Unknown video code */
+ port->edid->cea->video_code = 0;
+ port->edid->cea->aspect_ratio = (timing_info->mode_info_flags & PD_ASPECT_16_9)
+ ? PD_ASPECT_RATIO_16_9 : PD_ASPECT_RATIO_4_3;
+
+#ifdef CALCULATE_ELD_INFOFRAMES
+ calculate_infoframes(port,timing_info,temp_cea);
+ /* If canned eld is not set and audio info from transmitter is available */
+ if(temp_cea->canned_eld != 1 && (temp_cea->audio_flag & PD_AUDIO_CHAR_AVAIL)){
+ pix_rep = port->edid->cea->pixel_rep;
+ /*h_refresh = timing_info->dclk/timing_info->htotal;*/
+ h_refresh = timing_info->refresh;
+ cal_NPL[0] = (pix_rep*(timing_info->hsync_end - timing_info->hsync_start) -
+ port->edid->cea->K0) /32;
+ cal_NPL[1] = (pix_rep*(timing_info->hsync_end - timing_info->hsync_start) -
+ port->edid->cea->K1) /32;
+
+ poss_NPL[0] = MODE_MIN(cal_NPL[0],port->edid->cea->NPL);
+ poss_NPL[1] = MODE_MIN(cal_NPL[1],port->edid->cea->NPL);
+
+ max_bitRate_2[0] = h_refresh * poss_NPL[0] - 1500;
+ max_bitRate_2[1] = h_refresh * poss_NPL[1] - 1500;
+
+ max_bitRate_8[0] = h_refresh * poss_NPL[0] * 4 - 1500;
+ max_bitRate_8[1] = h_refresh * poss_NPL[1] * 4 - 1500;
+
+ /* Loop trough Content Protection disabled then enabled */
+ for(i=0 ; i<2; i++){
+ for(j=0 ; j<3; j++){
+ input = 0;
+ audio_freq = 48000 * (1<<j); /* 48Khz->96Khz->192Khz */
+ if(max_bitRate_8[i] >= audio_freq){
+ input = 7;
+ }else if(max_bitRate_2[i] >= audio_freq){
+ input = 1;
+ }
+ /* take the minimum value min(transmitter, receiver) */
+ input = MODE_MIN(input,temp_cea->audio_cap[j].max_channels);
+ temp_cea->LPCM_CAD[j] |= input<<((1-i)*3);
+ if(temp_cea->audio_cap[j]._24bit){
+ temp_cea->LPCM_CAD[j] |= BIT(7);
+ }
+ if(temp_cea->audio_cap[j]._20bit){
+ temp_cea->LPCM_CAD[j] |= BIT(6);
+ }
+ }
+ }
+
+ /* TODO: Further construction of ELD from Monitor Name String begins here
+ for now we only support VSDB */
+ /* By default we don send any vendor specific block unless latency value
+ use for audio sync feature is available */
+ temp_cea->vsdbl = 0;
+ /* This means the latecy field is available VSBD_LATENCY_FIELD = 8*/
+ if(temp_cea->vendor_block.vendor_block_size > VSBD_LATENCY_FIELD){
+ OS_MEMCPY(temp_cea->misc_data, temp_cea->vendor_data_block,
+ temp_cea->vendor_block.vendor_block_size);
+ temp_cea->vsdbl = temp_cea->vendor_block.vendor_block_size;
+ /* If the VSBD has latency fields */
+ if(*(temp_cea->vendor_data_block + VSBD_LATENCY_FIELD - 1) & 0x80){
+ if(timing_info->mode_info_flags & IGD_SCAN_INTERLACE){
+ if(*(temp_cea->vendor_data_block + VSBD_LATENCY_FIELD - 1) & 0x40){
+ temp_cea->vendor_block.p_latency = 1;
+ temp_cea->vendor_block.i_latency = 1;
+ }else{
+ /* No latency available: Since it is an interlace mode but no
+ vsbd_intlc_fld_present is available */
+ temp_cea->vendor_block.p_latency = 0;
+ temp_cea->vendor_block.i_latency = 0;
+ }
+ }else{
+ temp_cea->vendor_block.p_latency = 1;
+ temp_cea->vendor_block.i_latency = 0;
+ }
+ }
+ }
+ }
+#endif /* CALCULATE_ELD_INFOFRAMES */
+ temp_cea->audio_flag |= ELD_AVAIL;
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Configure either the primary or secondary display. This means all the
+ * timings, the framebuffer, the ports, the plane, and the pipe.
+ *
+ * The port range could be calculated based on primary or secondary
+ * display but it seems easier at this point to pass the port range
+ * in since it is used for all the for loops.
+ *
+ * @param driver_handle
+ * @param display
+ * @param pt_info
+ * @param fb_info
+ * @param dc
+ * @param p0
+ * @param pn
+ * @param flags
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int configure_display(
+ igd_driver_h driver_handle,
+ igd_display_context_t *display,
+ igd_display_info_t *pt_info,
+ igd_framebuffer_info_t *fb_info,
+ unsigned long dc,
+ int p0, int pn,
+ unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ int p;
+ igd_display_port_t *port;
+ igd_timing_info_t *timing_info;
+ unsigned long update_flags;
+ unsigned short port_number = 0;
+ int ret;
+ int seamless = FALSE;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: Should this be an assert? */
+ if (display == NULL) {
+ EMGD_DEBUG("Trying to configure a NULL display");
+ return 0;
+ }
+
+ EMGD_DEBUG("Configure timings");
+ for (p = pn; p > p0; p--) {
+ EMGD_DEBUG("Configure port %d", DC_PORT_NUMBER(dc, p));
+ if ((port_number = DC_PORT_NUMBER(dc, p))) {
+ port = context->mod_dispatch.dsp_port_list[port_number];
+ if (!port) {
+ EMGD_DEBUG("Port %d not found", port_number);
+ } else {
+
+ /* Put a copy of the timings in the port's structure */
+ if (pt_info) {
+ if (port->pt_info == NULL) {
+ port->pt_info = OS_ALLOC(sizeof(igd_display_info_t));
+ if (!port->pt_info) {
+ EMGD_ERROR_EXIT("unable to alloc a pt_info "
+ "struct in port.");
+ return -IGD_ERROR_INVAL;
+ }
+ }
+ OS_MEMCPY(port->pt_info, pt_info,
+ sizeof(igd_display_info_t));
+ } else {
+ EMGD_ERROR("No primary timing info!");
+ }
+ }
+ }
+ }
+
+ if(!(pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_ERROR_EXIT("Ptinfo has no IGD_DISPLAY_ENABLE!");
+ return 0;
+ }
+
+ display->port_number = DC_PORT_NUMBER(dc, (p0 + 1));
+
+ /* Set mode */
+ EMGD_DEBUG("Set mode, using port %ld", display->port_number);
+ port = PORT(display, display->port_number);
+
+ EMGD_DEBUG("Calling matchmode on display");
+ ret = match_mode(display, port->timing_table, fb_info, pt_info,
+ &timing_info);
+ if(ret) {
+ EMGD_DEBUG("Match Mode for display failed");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Now b4, we program the timing_info, let's first see if seamless
+ * option is requested, if it is then
+ * We need to make sure the incoming dc, timing, framebuffer
+ * info and etc match. We must respect the FORCE_ALTER flag.
+ *
+ * Seamless option buys you a one-time ticket for the seamless
+ * experience from the firmware to the driver. After the first mode set
+ * in driver, you don't get it the next time when you alter display.
+ *
+ */
+#ifndef CONFIG_MICRO
+ if(dc && !(flags & IGD_FORCE_ALTER) &&
+ (mode_context->seamless == TRUE) ) {
+
+ /* User wants seamless */
+ if(mode_context->fw_info != NULL) {
+
+ OPT_MICRO_CALL_RET(seamless, query_seamless(dc,
+ /*(p0/4),*/
+ PIPE(display)->pipe_num,
+ timing_info,
+ fb_info,
+ 0));
+
+ EMGD_DEBUG(":Seamless = %s", seamless ?"ON" : "OFF");
+ /* moved this to alter_displays to handle the case for CLONE */
+ /*mode_context->seamless = FALSE;*/
+ /* FIXME: For clone you get called twice. Need to
+ * Fix that corner case
+ */
+
+ }
+ }
+#endif
+ /* In case the seamless is FALSE, we do reset_plane_pipe_ports
+ * which is supposed to be called in alter_displays anyway.
+ * But we have to delay it since the user asked for seamless.
+ * And we don't want to switch-off the display during
+ * seamless.
+ * Now we know that even though the user asked for it, we cannot
+ * support seamless, so we call reset_plane_pipe_ports now.
+ */
+ if(seamless == FALSE) {
+
+ /* Reset planes/pipes/ports before doing first alter display */
+ if (mode_context->first_alter) {
+ mode_context->dispatch->reset_plane_pipe_ports(
+ mode_context->context);
+ mode_context->first_alter = FALSE;
+ }
+
+ }
+
+ if(calculate_eld(port, timing_info)){
+ EMGD_DEBUG("Fail to calculate ELD");
+ }
+ /* turn on all ports */
+ EMGD_DEBUG("turn on displays plane_pipe_ports %d..%d", (p0 + 1), (pn-1));
+
+ for (p = (p0 + 1); p <= pn; p++) {
+ if (DC_PORT_NUMBER(dc, p)) {
+ port = context->mod_dispatch.dsp_port_list[DC_PORT_NUMBER(dc, p)];
+
+ display->allocated = 1;
+
+ /* Update mode info for the port */
+ if (p == (p0 + 1)) {
+ update_flags = MODE_UPDATE_PLANE | MODE_UPDATE_PIPE |
+ MODE_UPDATE_PORT;
+ } else {
+ update_flags = MODE_UPDATE_PORT;
+ }
+ ret = mode_update_plane_pipe_ports(display, DC_PORT_NUMBER(dc, p),
+ timing_info, fb_info, pt_info, update_flags);
+ if (ret) {
+ /*
+ * This could happen if there was no memory for the
+ * framebuffer or the FB was an invalid format. The
+ * first is a too bad failure. The second should have
+ * been checked by the IAL.
+ */
+ EMGD_ERROR_EXIT("mode_update_plane_pipe_ports returned error "
+ "%d", ret);
+ port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
+ return ret;
+ }
+
+ /* Program the port registers */
+ if(seamless == TRUE) {
+ /* Don't have to program the registers, Since it's
+ * all updated. Just return 0
+ */
+ ret = 0;
+ } else {
+ ret = mode_context->dispatch->program_port(display,
+ DC_PORT_NUMBER(dc, p), TRUE);
+ }
+ if (ret == 0) {
+ port->inuse = 1;
+ } else {
+ port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
+ }
+ }
+ }
+ EMGD_DEBUG("done - turn on displays plane_pipe_ports %d", p);
+
+ /* Clear the Framebuffer after the planes, pipes and ports are
+ * disabled and before they are enabled. */
+ if (flags & IGD_CLEAR_FB) {
+ OPT_MICRO_VOID_CALL(full_clear_fb(mode_context, fb_info, NULL));
+ }
+
+ /* program the pipe/plane/port if seamless is FALSE */
+ if(seamless == FALSE) {
+
+ EMGD_DEBUG("Seamless is FALSE");
+
+ ret = TRUE;
+
+ do{
+ /* turn on pipe */
+ mode_context->dispatch->program_pipe(display, TRUE);
+
+ /* turn on plane */
+ mode_context->dispatch->program_plane(display, TRUE);
+
+ /* turn on port */
+ for (p = pn; p > p0; p--) {
+ if (DC_PORT_NUMBER(dc, p)) {
+ mode_context->dispatch->post_program_port(display,
+ DC_PORT_NUMBER(dc, p), TRUE);
+ }
+ }
+
+ /* Check is display working fine */
+ OPT_MICRO_CALL_RET(ret, mode_context->dispatch->
+ check_display(display, DC_PORT_NUMBER(dc, p),TRUE));
+
+ if(!ret){
+ /* turn off plane and pipe */
+ mode_context->dispatch->program_plane(display, FALSE);
+ mode_context->dispatch->program_pipe(display, FALSE);
+ }
+ }while(!ret);
+
+ }
+#ifndef CONFIG_MICRO
+ else { /* Seamless is TRUE */
+
+ /* Updating the plane registers, does not require us to
+ * turn-off the pipe and we can still have seamless
+ * because the display is not turned-off
+ */
+
+ EMGD_DEBUG(" Seamless is TRUE");
+ /* special handling for fw clone to vext seamless */
+ if((IGD_DC_VEXT(config_drm.dc) && IGD_DC_CLONE(mode_context->fw_info->fw_dc))){
+ mode_context->dispatch->full->lock_planes(display);
+ }
+ if(mode_context->fw_info->program_plane == 1) {
+
+ /* This means we have to update the plane registers
+ * with the new values.eg. Change in pitch size between
+ * firmware values and driver values. But we MUST also
+ * update the palette registers for this to work and
+ * palette registers are programmed when pipe is programmed.
+ * This means we program the pipe , followed by the plane.
+ */
+
+ /* By doing this, we update the palette */
+ mode_context->dispatch->program_pipe(display, TRUE);
+
+ /* update the plane registers */
+ mode_context->dispatch->program_plane(display, TRUE);
+ }
+ }
+#endif
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int igd_configure_display(
+ igd_driver_h driver_handle,
+ igd_display_h *display,
+ igd_display_info_t *pt_info,
+ igd_framebuffer_info_t *fb_info,
+ unsigned long dc,
+ int fb_index,
+ unsigned long flags)
+{
+ int p0, pn;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* Which ports do we loop through in the dc */
+ if (fb_index == 0) {
+ p0 = 0;
+ pn = 4;
+ } else {
+ p0 = 4;
+ pn = 7;
+ }
+
+ ret = configure_display(driver_handle, (igd_display_context_t *)display,
+ pt_info, fb_info, dc, p0, pn, flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+#ifndef CONFIG_MICRO
+
+/*!
+ * This function checks whether all the ports on the primary pipe of a dc are
+ * moving to a secondary pipe on a new dc.
+ *
+ * @param current_dc current_dc the system is in.
+ * @param dc new requested dc.
+ *
+ * @return 0 if not all the ports are moving
+ * @return 1 if all the ports are moving
+ */
+int all_ports_moving(unsigned long current_dc, unsigned long dc)
+{
+ unsigned long index, index2, port;
+ int found_port;
+ int result = 1;
+
+ /*
+ * We need to look for each of the primary ports on the current dc,
+ * and see if they exist on the secondary port of the new dc.
+ */
+ for (index = IGD_DC_IDX_PRIMARY_MASTER;
+ index <= IGD_DC_IDX_PRIMARY_TWIN3; index++) {
+ found_port = 0;
+ port = IGD_DC_PORT_NUMBER(current_dc, index);
+ /* If there is a port, let's look for it. */
+ if (port) {
+ /* Try to find this port on the secondary pipe */
+ for (index2 = IGD_DC_IDX_SECONDARY_MASTER;
+ index2 <= IGD_DC_IDX_SECONDARY_TWIN2; index2++) {
+ /*
+ * We found the port, let's stop looking for this port and
+ * move on to the next port
+ */
+ if (port == IGD_DC_PORT_NUMBER(dc, index2)) {
+ found_port = 1;
+ break;
+ }
+ }
+ /* As soon as there is a port that we don't find, we can exit */
+ if (!found_port) {
+ result = 0;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * This function checks whether a specified port exists in a dc, and if it does
+ * it returns the pipe master index for the pipe which contained the port.
+ *
+ * @param dc the dc to check for a port.
+ * @param port the port to check for.
+ *
+ * @return 0 if the specified does not exist
+ * @return IGD_DC_IDX_PRIMARY_MASTER if the port was found on the primary pipe
+ * @return IGD_DC_IDX_SECONDARY_MASTER if the port was found on the secondary
+ * pipe
+ */
+int dc_contains_port_type(unsigned long dc, unsigned long port)
+{
+ unsigned long index;
+ int result = 0;
+
+ for (index = IGD_DC_IDX_PRIMARY_MASTER;
+ index <= IGD_DC_IDX_PRIMARY_TWIN3; index++) {
+
+ if (IGD_DC_PORT_NUMBER(dc, index) == port) {
+ result = IGD_DC_IDX_PRIMARY_MASTER;
+ break;
+ }
+ }
+
+ for (index = IGD_DC_IDX_SECONDARY_MASTER;
+ index <= IGD_DC_IDX_SECONDARY_TWIN2; index++) {
+
+ if (IGD_DC_PORT_NUMBER(dc, index) == port) {
+ result = IGD_DC_IDX_SECONDARY_MASTER;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * This function checks whether a frame buffer swap and cursor
+ * swap is required based on given current_dc and new_dc.
+ *
+ * @param current_dc current_dc the system is in.
+ * @param dc new requested dc.
+ * @param dsp pointer to a display context pointer
+ *
+ * @return 0 if no swap is required
+ * @return 1 if swap is required
+ */
+int swap_required(
+ unsigned long current_dc,
+ unsigned long dc,
+ igd_display_context_t **dsp)
+{
+
+ /*
+ * Note: Preserve the order of conditions as is. Changing the order
+ * of below conditions require relook into the whole function to
+ * make sure sematics match to return right value.
+ */
+
+ /* Do not swap if no dc or current_dc */
+ if (!dc || !current_dc) {
+ return 0;
+ }
+
+ /*
+ * Do NOT swap the frame buffer and cursor if dc is going
+ * from twin to extended and not all the ports are moving to the other
+ * pipe. If all the ports are moving to the other pipe, then DO swap
+ * the frame buffer and cursor.
+ * We also need to make sure we are not in the special case where our
+ * extended mode contains LVDS and we are on a platform which does not
+ * support LVDS on PIPE A. In this case we do not want to swap here because
+ * we will not be swapping later since the twin configuration will stay on
+ * PIPE A so that the LVDS can move to PIPE B.
+ */
+ if (IGD_DC_TWIN(current_dc) && IGD_DC_EXTENDED(dc)) {
+ if (dsp && *dsp && all_ports_moving(current_dc, dc) &&
+ !(dc_contains_port_type(dc, IGD_PORT_TYPE_LVDS) &&
+ !(PIPE(*dsp)->pipe_features & IGD_PORT_SHARE_LVDS))) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /*
+ * Do NOT swap if dc is changing from Single to clone or
+ * vice versa. In this case there is only 1 fb and no swap is required
+ * and it stays with primary display.
+ */
+ if ((IGD_DC_SINGLE(current_dc) && IGD_DC_CLONE(dc)) ||
+ (IGD_DC_CLONE(current_dc) && IGD_DC_SINGLE(dc))) {
+ return 0;
+ }
+
+ /*
+ * If secondary master port is moving to primary master or
+ * primary master is moving to secondary master, try
+ * and keep the framebuffer address and cursor the same.
+ */
+ if (DC_PORT_NUMBER(current_dc, 5) == DC_PORT_NUMBER(dc, 1) ||
+ (DC_PORT_NUMBER(current_dc, 1) == DC_PORT_NUMBER(dc, 5))) {
+ /*
+ Note: This was previosuly return 1 to indicate swap required, which will cause
+ a frame buffer swap when changing display from twin to clone. If the display is
+ in extended mode before changing from twin to clone, then both Plane A and Plane B
+ will point to the secondary frame buffer offset adress in clone mode and cause
+ blank screen (.
+ */
+ return 0;
+ }
+ return 0;
+}
+#endif
+
+/*!
+ * This function sets up planes, pipes, and ports
+ * with the configuration passed in and returnes either one
+ * or two display handle lists.
+ *
+ * @param driver_handle from igd_init_driver().
+ * @param primary on return, this points to a list of displays.
+ * @param primary_ptinfo incoming timing info for the primary.
+ * @param primary_fbinfo incoming framebuffer info.
+ * @param secondary on return, this points to a list of displays.
+ * @param secondary_fbinfo incoming framebuffer info.
+ * @param dc display configuration
+ * @param flags modify function behavior
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_alter_displays(
+ igd_driver_h driver_handle,
+ igd_display_h *_primary,
+ igd_display_info_t *primary_pt_info,
+ igd_framebuffer_info_t *primary_fb_info,
+ igd_display_h *_secondary,
+ igd_display_info_t *secondary_pt_info,
+ igd_framebuffer_info_t *secondary_fb_info,
+ unsigned long dc,
+ unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t **primary = (igd_display_context_t **)_primary;
+ igd_display_context_t **secondary = (igd_display_context_t **)_secondary;
+ igd_framebuffer_info_t *fb_info = NULL;
+ igd_display_context_t *display = NULL,*tv_display=NULL;
+ drm_emgd_priv_t *priv = ((struct drm_device *)context->drm_dev)->dev_private;
+ int p;
+ int ret;
+ unsigned short tv_port_num=0;
+ int p_chng = 1, s_chng = 1;
+ unsigned char disable_plane_pipe = 0;
+ unsigned long current_dc;
+
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Make sure the DC is valid
+ *
+ * vBIOS won't be able to do this every time, for now only have
+ * the drivers's do the check.
+ */
+#ifndef CONFIG_MICRO
+ if (dc && !dsp_valid_dc(dc, 0)) {
+ EMGD_ERROR_EXIT("Invalid display configuration: 0x%08lx", dc);
+ return -IGD_ERROR_INVAL;
+ }
+#endif
+
+
+ /*
+ * Can all display_info's and fb_info's be NULL? I.E. make this
+ * function do an alloc of display handles only? If so, then
+ * check for that condition and return without error. Otherwise
+ * return an error.
+ */
+ if (dc && (!primary_pt_info && !primary_fb_info) &&
+ (!secondary_pt_info && !secondary_fb_info)) {
+ EMGD_ERROR_EXIT("Invalid timing and framebuffer info");
+ return -IGD_ERROR_INVAL;
+ }
+
+#ifndef CONFIG_MICRO
+ /* FIXME: GDK Change this to dispatch->idle() */
+ if (dsp_wait_rb(mode_context->context) != 0) {
+ return -IGD_ERROR_INVAL;
+ }
+#endif
+
+ /* If seamless request is NOT set , then do reset_plane_pipe_ports
+ * else delay it until we cannot support it.
+ * If seamless is requested by the user and we CAN support it
+ * then we need to make sure reset_plane_pipe_ports is NOT
+ * called. That's the whole point anyway. Not to reset anything
+ * during seamless transition
+ */
+ if(mode_context->seamless != TRUE) {
+
+ /* Reset planes/pipes/ports before doing first alter display */
+ if (mode_context->first_alter) {
+ mode_context->dispatch->reset_plane_pipe_ports(
+ mode_context->context);
+ mode_context->first_alter = FALSE;
+ }
+ }
+
+ current_dc = *(context->mod_dispatch.dsp_current_dc);
+
+#ifndef CONFIG_MICRO
+ /* Check if platform needs force alter
+ * to make sure we run tuning code. This
+ * is for TNC-B0 workaround.*/
+ if (mode_context->dispatch->dsp_is_force_alter_required){
+ if (mode_context->dispatch-> dsp_is_force_alter_required(context->
+ mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(current_dc)],
+ current_dc, dc)){
+ flags |= IGD_FORCE_ALTER;
+ }
+ }
+#endif
+
+ /*
+ * Turn off the planes, pipes, and ports associated with the current
+ * DC. However, limit the change to the primary if the secondary
+ * display handle is NULL or limit the change to the secondary if the
+ * the pimary display handle is NULL.
+ */
+ for (p = 7; p > 0; p--) {
+ if (p > 4) {
+ display = NULL;
+ if (DC_PORT_NUMBER(current_dc, p)) {
+ display = context->mod_dispatch.
+ dsp_display_list[IGD_DC_SECONDARY(current_dc)];
+ s_chng = TIMING_CHANGED(display, dc, current_dc,
+ secondary_pt_info, secondary_fb_info,
+ (unsigned long)0xfff00000, flags);
+ }
+
+ if (s_chng && display && secondary) {
+ /* if the port is TV, then don't set the power to S3 as this causes
+ * blank screen and system hang on LVDS on FSDOS, probably because the
+ * external clock needs to be on till the pipes and
+ * DPLLs are off
+ */
+ /* Invalidate flip-chains to avoid race conditions during the
+ * mode-set */
+ priv->invalidate_flip_chains(IGD_DISPLAY_SECONDARY);
+
+ if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
+ PD_DISPLAY_TVOUT) {
+ tv_display = display;
+ tv_port_num = DC_PORT_NUMBER(current_dc, p);
+ } else {
+ ret = mode_context->dispatch->program_port(display,
+ DC_PORT_NUMBER(current_dc, p), FALSE);
+ }
+ /* The secondary pipe master */
+ if (p == 5) {
+ disable_plane_pipe = 1;
+ }
+ }
+ } else {
+ display = NULL;
+ if (DC_PORT_NUMBER(current_dc, p)) {
+ display = context->mod_dispatch.
+ dsp_display_list[IGD_DC_PRIMARY(current_dc)];
+ p_chng = TIMING_CHANGED(display, dc, current_dc,
+ primary_pt_info, primary_fb_info,
+ (unsigned long)0x000ffff0, flags);
+ }
+
+ if (p_chng && display && primary) {
+ /* if the port is TV, then don't set the power to S3 as this causes
+ * blank screen and system hang on LVDS on FSDOS, probably because the
+ * external clock needs to be on till the pipes and
+ * DPLLs are off
+ */
+ /* Invalidate flip-chains to avoid race conditions during the
+ * mode-set */
+ priv->invalidate_flip_chains(IGD_DISPLAY_PRIMARY);
+
+ if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
+ PD_DISPLAY_TVOUT) {
+ tv_display = display;
+ tv_port_num = DC_PORT_NUMBER(current_dc, p);
+ } else {
+ ret = mode_context->dispatch->program_port(display,
+ DC_PORT_NUMBER(current_dc, p), FALSE);
+ }
+ /* The primary pipe master */
+ if (p == 1) {
+ disable_plane_pipe = 1;
+ }
+ }
+ }
+
+ /* Disable plane and pipe after disabling the ports */
+ if (disable_plane_pipe) {
+ if(mode_context->dispatch->full) {
+ mode_context->dispatch->full->program_cursor(display, FALSE);
+ }
+ mode_context->dispatch->program_plane(display, FALSE);
+ mode_context->dispatch->program_pipe(display, FALSE);
+ /*pipes and dplls are off, now turn off tv port */
+ if(tv_display) {
+ ret = mode_context->dispatch->program_port(tv_display,
+ tv_port_num, FALSE);
+ tv_display = NULL;
+ }
+ disable_plane_pipe = 0;
+ }
+ }
+
+#ifndef CONFIG_MICRO
+ /* If DC is zero, then return here. A zero dc turns everything off */
+ /* This never happens for VBIOS since it only always calls *
+ * alter_displays at the same point with the same valid DC */
+ if (!dc) {
+ int i;
+
+ priv->invalidate_flip_chains(IGD_DISPLAY_ALL);
+
+ mode_context->dispatch->reset_plane_pipe_ports(mode_context->context);
+ /* Should de-allocate everything here */
+ dsp_alloc(driver_handle, dc, flags);
+ /*
+ * FIXME: This should be done inside dsp alloc, mode module does
+ * not own this information.
+ * When dc = 0, set all displays allocated to 0.
+ */
+ for (i=0; i<IGD_MAX_PORTS+1; i++) {
+ if (context->mod_dispatch.dsp_display_list[i]) {
+ context->mod_dispatch.dsp_display_list[i]->allocated = 0;
+ }
+ context->mod_dispatch.dsp_display_list[i] = NULL;
+ }
+
+ return 0;
+ }
+#endif
+
+ /*
+ * Check the DC (display configuration). If it is the same as the
+ * current configuration, then don't change any allocations, only
+ * modify the framebuffers and timings.
+ */
+ if (dc != current_dc) {
+ EMGD_DEBUG("Allocate display handles based on DC");
+
+#ifndef CONFIG_MICRO
+ if (swap_required(current_dc, dc, primary)) {
+ swap_fb_cursor();
+ }
+#endif
+ /*
+ * This function should never be called after VBIOS initialization *
+ * The dsp_alloc is discarded after VBIOS init and is over- *
+ * written by font tables. Thus in VBIOS IAL, alter_displays *
+ * is never get called with a different DC from the 1st time *
+ */
+ dsp_alloc(driver_handle, dc, flags);
+
+ }
+
+ /* Attach the displays to the caller's pointers */
+ if (primary) {
+ *primary = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+ }
+ if (secondary) {
+ EMGD_DEBUG("Attaching display 1 to secondary pointer");
+ *secondary = context->mod_dispatch.
+ dsp_display_list[IGD_DC_SECONDARY(dc)];
+ }
+
+ /*
+ * Configure the primary display. This configures the timings and the
+ * framebuffer. Once configured, it turns everythying on.
+ */
+ if(primary && *primary && (primary_pt_info || primary_fb_info) && p_chng) {
+ EMGD_DEBUG("Configure primary timings");
+ /* make framebuffer changes */
+ if (primary_fb_info) {
+ /* set up new frame buffer info */
+ fb_info = primary_fb_info;
+ } else {
+ fb_info = PLANE(*primary)->fb_info;
+ }
+
+ ret = configure_display(driver_handle,
+ (igd_display_context_t *)(*primary), primary_pt_info,
+ fb_info, dc, 0, 4, flags);
+ if (ret) {
+ EMGD_DEBUG("Primary display disabled.");
+ }
+ }
+
+ /*
+ * Configure the secondary display. This configures the timings and the
+ * framebuffer. Once configured, it turns everythying on.
+ *
+ * How close is this code to the code for the primary? Could this
+ * be moved to a separate function?
+ */
+ if (secondary != NULL) {
+
+#ifndef CONFIG_MICRO
+ /*
+ * In the case where we are in extended or clone and our pipe is not
+ * turned on, we need to turn the pipes on.
+ * We can run into this situation on pre-Cantiga Gen platforms on Linux
+ * where LVDS was the primary display and was assigned PIPE B. Then we
+ * are switching from LVDS to another display and that other display
+ * wants to take PIPE A. In this case PIPE B will be turned on, the
+ * display's new port will take PIPE A and turn on PIPE A. The second
+ * display thinks it is still PIPE A and nothing has changed for it.
+ * In this case where our pipe is not turned on, we need to let the
+ * system know that something has changed.
+ */
+ if ((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
+ && !(EMGD_READ32(MMIO(*secondary) + PIPE(*secondary)->pipe_reg)
+ & 0x80000000)) {
+ s_chng = 1;
+ }
+#endif
+
+ EMGD_DEBUG("Starting secondary pipe programming");
+ if ((*secondary != NULL) && (secondary_pt_info || secondary_fb_info) &&
+ s_chng){
+ /*
+ * Configure the framebuffer. For clone, it is the same
+ * as the primary. For DIH, it is a unique fb.
+ */
+ EMGD_DEBUG("configure secondary framebuffer");
+ if (dc & IGD_DISPLAY_CONFIG_CLONE) {
+ fb_info = PLANE(*primary)->fb_info;
+ } else {
+ if (secondary_fb_info) {
+ fb_info = secondary_fb_info;
+ } else {
+ fb_info = PLANE(*secondary)->fb_info;
+ }
+ }
+
+ ret = configure_display(driver_handle,
+ (igd_display_context_t *)(*secondary), secondary_pt_info,
+ fb_info, dc, 4, 7, flags);
+ if (ret) {
+ EMGD_DEBUG("Secondary display disabled.");
+ EMGD_ERROR("Secondary display disabled.");
+ }
+ }
+ } else {
+ EMGD_DEBUG("Skipped secondary programming, NULL handle");
+ }
+
+ /*
+ * Workaround: wait for Vblank to avoid people accessing display
+ * plane registers before the register is updated properly.
+ */
+ if (primary && *primary) {
+ EMGD_DEBUG("Wait for vblank on primary display (%p)", primary);
+ EMGD_DEBUG("Wait for vblank on primary display (%p)", *primary);
+ mode_context->dispatch->wait_vblank(*primary);
+ } else if (secondary && *secondary) {
+ EMGD_DEBUG("Wait for vblank on secondary display");
+ mode_context->dispatch->wait_vblank(*secondary);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function sets the power state for the passed
+ * display handle. This only updates the power state for the
+ * display/port. The pipe, plane, and ringbuffer are left in
+ * the same power state. There is also no need to
+ * alter_display, since only the port is modified.
+ *
+ * @param driver_handle from igd_init().
+ * @param port_number
+ * @param power_state
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_power_display(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned int power_state)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t *display;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Requested power state = %d", power_state);
+
+ /* Get the display context that is currently using this port. */
+ display = context->mod_dispatch.dsp_display_list[port_number];
+ if(!display) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* If this display is allocated, but has not been altered, return
+ * an error. */
+ if (!PORT(display, port_number)->pt_info || !PIPE(display)->timing) {
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Set the desired power state to the display handle and let program_port
+ * take care of the rest
+ */
+ PORT(display, port_number)->power_state = (unsigned long)power_state;
+
+ switch(power_state) {
+ case IGD_POWERSTATE_D0:
+ mode_context->dispatch->program_port(display, port_number, TRUE);
+ mode_context->dispatch->post_program_port(display, port_number, 0);
+ break;
+ case IGD_POWERSTATE_D1:
+ case IGD_POWERSTATE_D2:
+ case IGD_POWERSTATE_D3:
+ mode_context->dispatch->program_port(display, port_number, TRUE);
+ break;
+ default:
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param driver_handle from igd_init().
+ * @param port_number
+ * @param edid_ptr
+ * @param block_number
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL or -IGD_ERROR_EDID on failure
+ */
+/* FIXME: Move this to PI */
+static int igd_get_EDID_block(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned char FAR *edid_ptr,
+ unsigned char block_number)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_port_t *port;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(driver_handle, "Null driver_handle", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(edid_ptr, "Null edid_ptr", -IGD_ERROR_INVAL);
+
+ port = context->mod_dispatch.dsp_port_list[port_number];
+ if(!port) {
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+ /* Read EDID */
+ ret = context->mod_dispatch.i2c_read_regs(
+ context,
+ port->ddc_reg,
+ 10, /* DDC speed 10 KHz */
+ port->ddc_dab,
+ 128*block_number,
+ edid_ptr,
+ 128,
+ 0);
+
+ if (ret) {
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_EDID;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end igd_get_EDID_block() */
+
+/*!
+ * Return either a pointer to the live mode list or a copy of the mode list
+ * for the requested display. This will be the mode list for the master port
+ * on the pipe.
+ *
+ * @note Currently (AS of 3.3 development) the mode list is
+ * described as a igd_display_info_t. However IT IS NOT, this
+ * pointer must be cast to a igd_timing_info_t to be used. After
+ * 3.3 the igd_display_info_t will be altered to match the
+ * igd_timing_info_t with the exception of the private pointers.
+ *
+ * @param driver_handle handle returned from a successful call to
+ * igd_driver_init().
+ * @param dc Display configuration that will determine which port
+ * controlls the pipe timings and thus, which set of timings to return.
+ * @param mode_list The returned mode list. This data may be LIVE. If
+ * a live list is returned, care should be taken to not free or alter
+ * the data.
+ * @param flags The flags will determine which display to query (primary
+ * or secondary) and if the mode list returned should be the live list.
+ *
+ * @return 0 on success.
+ * @return -IGD_INVAL if an error occured (memory allocation failed)
+ */
+int igd_query_mode_list(igd_driver_h driver_handle,
+ unsigned long dc,
+ igd_display_info_t **mode_list,
+ unsigned long flags)
+{
+ igd_context_t *context;
+ unsigned short port_number;
+ igd_display_port_t *port;
+
+ EMGD_TRACE_ENTER;
+
+ context = (igd_context_t *)driver_handle;
+ *mode_list = NULL;
+
+ /* given the DC and flags, which port number to check? */
+ port_number = (flags & IGD_QUERY_SECONDARY_MODES) ? DC_PORT_NUMBER(dc, 5) :
+ DC_PORT_NUMBER(dc, 1);
+
+ port = context->mod_dispatch.dsp_port_list[port_number];
+ if (port) {
+ if (flags & IGD_QUERY_LIVE_MODES) {
+ /*
+ * FIXME:
+ * timing_table is not an igd_dislay_info_t structure but
+ * eventually it will be?
+ */
+ *mode_list = (igd_display_info_t *)port->timing_table;
+ } else {
+ OPT_MICRO_CALL(full_mode_query(driver_handle, dc, mode_list,
+ port));
+ }
+ }
+
+ if (*mode_list == NULL) {
+ EMGD_DEBUG("No port on requested pipe");
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function is used to initialize any module/dsp
+ * module specific structures or tables etc.
+ *
+ * @param context SS level igd_context.
+ *
+ * @return 0 on success.
+ * @return -IGD_INVAL or -IGD_ERROR_NODEV on failure
+ */
+int mode_init(igd_context_t *context)
+{
+ igd_dispatch_t *dispatch = &context->dispatch;
+ inter_module_dispatch_t *md;
+ int port_num;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Allocating a mode context...");
+
+ /* Clear the allocated memory for mode context */
+ OS_MEMSET((void *)mode_context, 0, sizeof(mode_context_t));
+
+ /* Set the pointer to igd level context */
+ mode_context->context = context;
+ mode_context->first_alter = TRUE;
+ mode_context->display_color =
+ context->mod_dispatch.init_params->display_color;
+#ifndef CONFIG_MICRO
+ mode_context->ref_freq =
+ context->mod_dispatch.init_params->ref_freq;
+ mode_context->tuning_wa =
+ context->mod_dispatch.init_params->tuning_wa;
+ /*To give option for validation*/
+ mode_context->clip_hw_fix =
+ context->mod_dispatch.init_params->clip_hw_fix;
+ mode_context->async_flip_wa =
+ context->mod_dispatch.init_params->async_flip_wa;
+ mode_context->en_reg_override =
+ context->mod_dispatch.init_params->en_reg_override;
+ mode_context->disp_arb =
+ context->mod_dispatch.init_params->disp_arb;
+ mode_context->fifo_watermark1 =
+ context->mod_dispatch.init_params->fifo_watermark1;
+ mode_context->fifo_watermark2 =
+ context->mod_dispatch.init_params->fifo_watermark2;
+ mode_context->fifo_watermark3 =
+ context->mod_dispatch.init_params->fifo_watermark3;
+ mode_context->fifo_watermark4 =
+ context->mod_dispatch.init_params->fifo_watermark4;
+ mode_context->fifo_watermark5 =
+ context->mod_dispatch.init_params->fifo_watermark5;
+ mode_context->fifo_watermark6 =
+ context->mod_dispatch.init_params->fifo_watermark6;
+ mode_context->gvd_hp_control =
+ context->mod_dispatch.init_params->gvd_hp_control;
+ mode_context->bunit_chicken_bits =
+ context->mod_dispatch.init_params->bunit_chicken_bits;
+ mode_context->bunit_write_flush =
+ context->mod_dispatch.init_params->bunit_write_flush;
+ mode_context->disp_chicken_bits =
+ context->mod_dispatch.init_params->disp_chicken_bits;
+#endif
+
+ for (i=0; i < IGD_MAX_PORTS; i++) {
+ port_num = context->mod_dispatch.init_params->display_params[i].port_number;
+ mode_context->batch_blits[port_num - 1] =
+ (context->mod_dispatch.init_params->display_params[i].flags
+ & IGD_DISPLAY_BATCH_BLITS);
+ }
+
+ /* Get mode's dispatch table */
+ mode_context->dispatch = (mode_dispatch_t *)
+ dispatch_acquire(context, mode_dispatch);
+ if(!mode_context->dispatch) {
+ EMGD_ERROR_EXIT("Unsupported Device");
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Hook up KMS dispatch table */
+ mode_context->kms_dispatch = (mode_kms_dispatch_t *)
+ dispatch_acquire(context, mode_kms_dispatch);
+ if(!mode_context->kms_dispatch) {
+ EMGD_ERROR_EXIT("Unsupported Device");
+ return -IGD_ERROR_NODEV;
+ }
+
+
+ md = &context->mod_dispatch;
+
+ /* Set the fw_info to 0 */
+ mode_context->fw_info = NULL;
+
+ /* Hook up the IGD dispatch table entires for mode */
+ dispatch->get_EDID_block = igd_get_EDID_block;
+ dispatch->power_display = igd_power_display;
+ dispatch->query_mode_list = igd_query_mode_list;
+ dispatch->alter_displays = igd_alter_displays;
+ dispatch->igd_configure_display = igd_configure_display;
+
+ OPT_MICRO_CALL(full_mode_init(context, mode_context));
+
+ /* Hook up inter-module dispatch functions */
+ md->mode_get_gpio_sets = mode_context->dispatch->get_gpio_sets;
+ md->mode_reset_plane_pipe_ports =
+ mode_context->dispatch->reset_plane_pipe_ports;
+ md->filter_modes = mode_context->dispatch->filter_modes;
+
+ /* Hook up Core specific IGD dispatch table entries */
+ dispatch->set_palette_entries =
+ mode_context->dispatch->full->set_palette_entries;
+ dispatch->set_palette_entry = mode_context->dispatch->set_palette_entry;
+ dispatch->get_palette_entry = mode_context->dispatch->get_palette_entry;
+ dispatch->wait_vblank = mode_context->dispatch->wait_vblank;
+
+ /* Initialize dsp module */
+ if (dsp_init(context)) {
+ EMGD_ERROR("dsp_init() failed.");
+ return -IGD_INVAL;
+ }
+
+ /* Initialze port interface (pi) module */
+ if (pi_init(context)) {
+ EMGD_ERROR_EXIT("pi_init() failed.");
+ if(md->dsp_shutdown) {
+ md->dsp_shutdown(context);
+ }
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (mode_context->dispatch->full && md->reg_get_mod_state) {
+ module_state_h *state = NULL;
+
+ /* Save mode state for the regular case*/
+ unsigned long *flags = NULL;
+ md->reg_get_mod_state(REG_MODE_STATE_REG, &state, &flags);
+ md->mode_save(context, state, flags);
+
+ /*Save mode state for the console case */
+ if (config_drm.init) {
+ state = NULL;
+ md->reg_get_mod_state(REG_MODE_STATE_CON, &state, &flags);
+ md->mode_save(context, state, flags);
+ }
+ }
+
+ toggle_vblank_interrupts(TRUE);
+ /* Initialize the Display Configuration List */
+ /* FIXME: This should be done in dsp init */
+ dsp_dc_init(context);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
new file mode 100644
index 0000000..221e4d2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
@@ -0,0 +1,393 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_dispatch.h
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This header file defined the interface between the DI layer of the mode
+ * module and the DD layer. Additionally it defines the interface between
+ * the different DI object files within the mode module.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MODE_DISPATCH_H
+#define _MODE_DISPATCH_H
+
+#include <mode.h>
+
+
+
+typedef struct _mode_kms_dispatch {
+ void (*kms_program_pipe) (emgd_crtc_t *emgd_crtc);
+ void (*kms_set_pipe_pwr) (emgd_crtc_t *emgd_crtc, unsigned long enable);
+ void (*kms_program_plane)(emgd_crtc_t *emgd_crtc, unsigned long status);
+ void (*kms_set_plane_pwr)(emgd_crtc_t *emgd_crtc, unsigned long enable);
+ int (*kms_program_port) (emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+ int (*kms_post_program_port)(emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+ u32 (*kms_get_vblank_counter)(emgd_crtc_t *emgd_crtc);
+ int (*kms_match_mode)(emgd_encoder_t *emgd_encoder,
+ igd_framebuffer_info_t *fb_info, igd_timing_info_t **timing);
+} mode_kms_dispatch_t;
+
+
+
+typedef struct _mode_full_dispatch {
+ int (*alter_cursor_pos)(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info);
+ int (*set_palette_entries)(igd_display_h display_handle,
+ unsigned long *palette_colors, unsigned int start_index,
+ unsigned int count);
+ int (*wait_vsync)(igd_display_h display_handle);
+ int (*query_in_vblank)(igd_display_h display_handle);
+ int (*get_scanline)(igd_display_h display_handle, int *scanline);
+ int (*set_display_base)(igd_display_context_t *display,
+ igd_framebuffer_info_t *fb, unsigned long *x, unsigned long *y);
+ void (*program_cursor)(igd_display_context_t *display,
+ unsigned long status);
+ int (*set_color_correct)(igd_display_context_t *display);
+ int (*get_surface)(igd_display_h display_handle, igd_buffertype_t type,
+ igd_surface_t *surface, igd_appcontext_h appcontext);
+ int (*set_surface)(igd_display_h display_handle, int priority,
+ igd_buffertype_t type, igd_surface_t *surface,
+ igd_appcontext_h appcontext, unsigned long flags);
+ int (*query_event)(igd_display_h display_handle, igd_event_t event,
+ unsigned long *status);
+
+ int (*set_flip_pending)(unsigned char *mmio,
+ unsigned long pipe_status_reg);
+ int (*check_flip_pending)(unsigned char *mmio,
+ unsigned long pipe_status_reg);
+
+ int (*get_plane_info)(void); /* dispatch routines that gets fw info */
+ int (*get_pipe_info)(igd_display_h *display );
+ int (*get_port_info)(void);
+ /* Implementation of "public" igd_dispatch_t.register_vblank_callback(). */
+ emgd_vblank_callback_h (*register_vblank_callback)(
+ emgd_process_vblank_interrupt_t callback,
+ void *priv,
+ unsigned long port_number);
+ /* Implementation of "public" igd_dispatch_t.unregister_vblank_callback().
+ */
+ void (*unregister_vblank_callback)(
+ emgd_vblank_callback_h callback_h);
+ /* Implementation of "public" igd_dispatch_t.enable_vblank_callback(). */
+ int (*enable_vblank_callback)(emgd_vblank_callback_h callback_h);
+ /* Implementation of "public" igd_dispatch_t.disable_vblank_callback(). */
+ void (*disable_vblank_callback)(
+ emgd_vblank_callback_h callback_h);
+ /*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to request VBlank interrupts for a particular purpose & port.
+ * Based upon the outstanding requests, this function decides whether to
+ * touch registers, register the interrupt handler, etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+ int (*request_vblanks)(unsigned long request_for, unsigned char *mmio);
+ /*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to end a previous request VBlank interrupts for a particular
+ * purpose & port. Based upon the outstanding requests, this function
+ * decides whether to touch registers, unregister the interrupt handler,
+ * etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+ int (*end_request)(unsigned long request_for, unsigned char *mmio);
+ /*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to check whether a requested VBlank interrupt occured.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @return Non-zero if the requested VBlank occured, zero if not.
+ */
+ int (*vblank_occured)(unsigned long request_for);
+ unsigned long (*get_port_control)(unsigned long port_num, unsigned long port_reg);
+ void (*lock_planes)(igd_display_h display_handle);
+ int (*unlock_planes)(igd_display_h display_handle, unsigned int scrn_num);
+} mode_full_dispatch_t;
+
+typedef struct _mode_dispatch {
+ int (*set_palette_entry)(igd_display_h display_handle,
+ unsigned long palette_entry, unsigned long palette_color);
+ int (*get_palette_entry)(igd_display_h display_handle,
+ unsigned long palette_entry, unsigned long *palette_color);
+ int (*wait_vblank)(igd_display_h display_handle);
+ void (*program_plane)(igd_display_context_t *display,
+ unsigned long status);
+ void (*program_pipe)(igd_display_context_t *display, unsigned long status);
+ int (*program_port)(igd_display_context_t *display,
+ unsigned short port_number, unsigned long status);
+ int (*post_program_port)(igd_display_context_t *display,
+ unsigned short port_number, unsigned long status);
+ int (*program_clock)(igd_display_context_t *display,
+ igd_clock_t *clock, unsigned long dclk);
+ int (*program_cdvo)(void);
+ void (*reset_plane_pipe_ports)(igd_context_t *context);
+ unsigned long (*get_gpio_sets)(unsigned long **);
+ void (*filter_modes)(igd_context_t *context,
+ igd_display_port_t *port, pd_timing_t *in_list);
+ int (*check_display)(igd_display_context_t *display,
+ unsigned short port_number, unsigned long status);
+ int (*get_dd_timing)(igd_display_context_t *display,
+ pd_timing_t *in_list);
+ int (*check_port_supported)(void *port_tmp);
+ int (*get_refresh_in_border)(pd_timing_t *in_list);
+ bool (*dsp_is_force_alter_required)(igd_display_context_t *display,
+ unsigned long current_dc, unsigned long dc_to_set);
+ mode_full_dispatch_t *full;
+} mode_dispatch_t;
+
+
+/*
+ * Firmware(VBIOS or EFI Video Driver) related information
+ * that needs to be populated before the driver re-programs
+ * the Hardware Registers. This information is needed to provide
+ * seamless transition from firmware to driver.
+ */
+typedef struct _fw_info {
+
+ /* TODO: Fill this up */
+ unsigned long fw_dc; /* The dsp module already has this value */
+
+ /* Plane information */
+ igd_framebuffer_info_t fb_info[2]; /* one for each plane */
+
+ /* Pipe information */
+ igd_display_info_t timing_arr[2]; /* one for each pipe */
+
+ /* Port information */
+
+ /* if the plane registers needs an update, set this field to 1 */
+ int program_plane;
+
+} fw_info_t;
+
+
+
+typedef struct _mode_context {
+ /*
+ * All of the below values will be initialized in mode module
+ * init function mode_init().
+ */
+ unsigned long first_alter;
+ mode_dispatch_t *dispatch;
+ mode_kms_dispatch_t *kms_dispatch;
+
+ igd_context_t *context;
+ unsigned long display_color;
+ fw_info_t* fw_info; /* This needs to be zero for VBIOS */
+
+ /* quickboot options */
+ unsigned long quickboot;
+ int seamless;
+ unsigned long video_input;
+ int splash;
+ unsigned long ref_freq;
+ int tuning_wa;
+ unsigned long clip_hw_fix;
+ unsigned long async_flip_wa;
+
+ /*
+ * Enable override of following registers when en_reg_override=1.
+ * Display Arbitration, FIFO Watermark Control, GVD HP_CONTROL,
+ * Bunit Chickenbits, Bunit Write Flush, Display Chickenbits
+ */
+ unsigned long en_reg_override;
+ unsigned long disp_arb;
+ unsigned long fifo_watermark1;
+ unsigned long fifo_watermark2;
+ unsigned long fifo_watermark3;
+ unsigned long fifo_watermark4;
+ unsigned long fifo_watermark5;
+ unsigned long fifo_watermark6;
+ unsigned long gvd_hp_control;
+ unsigned long bunit_chicken_bits;
+ unsigned long bunit_write_flush;
+ unsigned long disp_chicken_bits;
+
+ /* Flags specifying whether to notify user-space of a v-blank event.
+ * This is used when synchronizing back-buffer blits */
+ bool batch_blits[IGD_MAX_PORTS];
+
+} mode_context_t;
+
+extern int full_mode_init(igd_context_t *context,
+ mode_context_t *mode_context);
+
+extern int full_mode_query(igd_driver_h driver_handle, unsigned long dc,
+ igd_display_info_t **mode_list, igd_display_port_t *port);
+
+extern void full_clear_fb(mode_context_t *mode_context,
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb);
+
+extern int query_seamless(unsigned long dc,
+ int index,
+ igd_timing_info_t *pt,
+ igd_framebuffer_info_t *pf,
+ unsigned long flags);
+
+extern void swap_fb_cursor( void );
+
+extern int set_color_correct(igd_display_context_t *display,
+ const igd_range_attr_t *attr_to_set);
+
+extern void toggle_vblank_interrupts(bool status);
+
+extern mode_context_t mode_context[];
+
+/*
+ * NOTE: Some of these externs are declared with the struct name because the
+ * contents of that struct are unavailable at the DI layer. The symbol
+ * is used as the generic mode_dispatch_t which is a subset.
+ */
+
+
+extern mode_dispatch_t mode_dispatch_plb;
+extern mode_dispatch_t mode_dispatch_tnc;
+
+extern mode_kms_dispatch_t mode_kms_dispatch_plb;
+extern mode_kms_dispatch_t mode_kms_dispatch_tnc;
+
+
+
+/*******************************************************************************
+ *
+ * The following macros provide part of the "protected" interface to support
+ * mode-module "requests" for VBlank interrupts.
+ *
+ * Requests are for a "who" and "what." The "who" is what type of code is
+ * making the request, and the "what" is the port that the requestor wants to
+ * know about VBlanks for. Here is additional information:
+ *
+ * - Who - which software is asking:
+ * - WAIT - The code that implements the wait_vblank() function pointer.
+ * When interrupts are requested for WAIT, the interrupt handler
+ * makes note of when VBlanks occur. The WAIT code queries (polls)
+ * whether a VBlank has occured since its request.
+ * - FLIP - The code that implements the {check|set}_flip_pending() function
+ * pointers. When interrupts are requested for FLIP, the interrupt
+ * handler makes note of when VBlanks occur. The FLIP code queries
+ * (polls) whether a VBlank has occured since its request.
+ * - CB - The non-HAL code that registers a VBlank interrupt "callback"
+ * (CB). When interrupts are requested for CB, the interrupt
+ * handler calls the callback when VBlanks occur.
+ *
+ * - What - which port (Note: space is reserve for 4 ports, even only two exist
+ * at this time):
+ * - PORT2 (Port 2, Pipe A, SDVO-B)
+ * - PORT4 (Port 4, Pipe B, Int-LVDS)
+ *
+ * Note: internally, the requests are stored in bits within an unsigned long.
+ * This helps explain the way the macros are implemented:
+ *
+ ******************************************************************************/
+
+/* A requestor uses this macro to generate the bit request for who and what: */
+#define VBINT_REQUEST(who,port) ((port) << (who))
+
+/* A requestor uses one of these macros to specify a what (i.e. port): */
+#define VBINT_PORT2 0x01
+#define VBINT_PORT4 0x02
+/* Note: the following 2 macros reserve space for 2 more (future) ports: */
+#define VBINT_PORTn 0x04
+#define VBINT_PORTm 0x08
+
+/* A requestor uses one of these macros to identify itself (the what): */
+/* Note: Each "who" has 4 bits (for 4 ports); the value is a shift amount: */
+#define VBINT_WAIT 0
+#define VBINT_FLIP 4
+#define VBINT_CB 8
+
+
+/*******************************************************************************
+ *
+ * The following macros provide part of the "private" interface to support
+ * mode-module "requests" for VBlank interrupts. The VBlank-interrupt code
+ * uses these macros to manage requests, and to record VBlanks that occur
+ * (a.k.a. "answers").
+ *
+ * Other parts of the "mode" module should not use these macros.
+ *
+ ******************************************************************************/
+
+/* Answers for a request are stored in bits to the left of the request bits: */
+#define VBINT_ANSWER_SHIFT 12
+#define VBINT_ANSWER(who,port) (((port) << (who)) << VBINT_ANSWER_SHIFT)
+#define VBINT_ANSWER4_REQUEST(request) ((request) << VBINT_ANSWER_SHIFT)
+
+/* The following special bit is used by disable_vblank_interrupts_{plb|tnc}() to
+ * disable the hardware, but not unregister the never-registered interrupt
+ * handler:
+ */
+#define VBLANK_DISABLE_HW_ONLY BIT31
+
+/* The following macros aggregate all of the who's can enable interrupts for a
+ * given port:
+ */
+#define VBLANK_INT4_PORT2 (VBINT_REQUEST(VBINT_WAIT, VBINT_PORT2) | \
+ VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2) | \
+ VBINT_REQUEST(VBINT_CB, VBINT_PORT2))
+#define VBLANK_INT4_PORT4 (VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4) | \
+ VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4) | \
+ VBINT_REQUEST(VBINT_CB, VBINT_PORT4))
+
+/* The following macros aggregate all of the whats (ports) that can enable
+ * interrupts for a given who (they aren't used, but do help document that
+ * 4 bits are reserved for each "who"):
+ */
+/* FIXME -- KEEP THESE??? */
+#define VBLANK_INT4_WAIT 0x0000000f
+#define VBLANK_INT4_FLIP 0x000000f0
+#define VBLANK_INT4_CB 0x00000f00
+
+/* The following macros tell whether interrupts are enabled, either in general,
+ * or for a certain port.
+ */
+#define VBLANK_INTERRUPTS_ENABLED \
+ (vblank_interrupt_state & (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4 | \
+ VBLANK_DISABLE_HW_ONLY))
+#define VBLANK_INTERRUPTS_ENABLED4_PORT2 \
+ (vblank_interrupt_state & VBLANK_INT4_PORT2)
+#define VBLANK_INTERRUPTS_ENABLED4_PORT4 \
+ (vblank_interrupt_state & VBLANK_INT4_PORT4)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
new file mode 100644
index 0000000..546b699
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
@@ -0,0 +1,1467 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: vga_mode.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains VGA plane/pipe programming functions that can
+ * be used on any VGA compatible hardware. Hardware specific functions
+ * should put the device in VGA compatible mode prior to calling thses
+ * functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <context.h>
+
+#include <sched.h>
+
+#include <igd_vga.h>
+
+#include "drm_emgd_private.h"
+
+#include <mode.h>
+#include <utils.h>
+#include <vga.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*
+ * For mono modes this is 0 (CRTC is at 0x3b4)
+ * For other modes it is 0x20 (CRTC is at 0x3d4)
+ */
+unsigned char vga_port_offset = 0x20;
+
+/* This is a global variable used by the vBIOS to override the mode table
+ * if a User Defined Mode Table is set. */
+vga_mode_data_t FAR (*vga_mode_data_ptr)[]=&vga_mode_data;
+
+/* This is a global variable used by the vBIOS to enable/disable the
+ * loading of the palette during a mode change. A global variable is
+ * the best choice, since this is not really an OAL interface.
+ * 0=Do load the default palette on a mode change.
+ * 1=Do NOT load the default palette on a mode change. */
+unsigned char vga_disable_default_palette_load = 0;
+
+/*!
+ *
+ * @param mmio
+ * @param port
+ * @param index
+ * @param value
+ *
+ * @return void
+ */
+void write_vga_reg(unsigned char *mmio, unsigned short port,
+ unsigned char index, unsigned char value)
+{
+ WRITE_VGA(mmio, port, index, value);
+}
+
+/*!
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void kms_program_plane_vga(unsigned char *mmio,
+ igd_timing_info_t *timings)
+{
+
+ EMGD_DEBUG("Enter program_plane_vga");
+
+ /* Set Bit 5 so the plane remains off. It will be turned on
+ * in the IAL. This is necessary, so the clear screen can occur
+ * before the mode is enabled. */
+ write_vga_reg(mmio, SR_PORT, 0x01,
+ (*vga_mode_data_ptr)[timings->mode_number].sr_regs[0] | 0x20);
+ OS_SLEEP(1000);
+
+ return;
+}
+
+/*!
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void program_plane_vga(igd_display_context_t *display,
+ igd_timing_info_t *timings)
+{
+ unsigned char *mmio;
+
+ EMGD_DEBUG("Enter program_plane_vga");
+
+ mmio = (unsigned char *)MMIO(display);
+ /* Set Bit 5 so the plane remains off. It will be turned on
+ * in the IAL. This is necessary, so the clear screen can occur
+ * before the mode is enabled. */
+ write_vga_reg(mmio, SR_PORT, 0x01,
+ (*vga_mode_data_ptr)[timings->mode_number].sr_regs[0] | 0x20);
+ OS_SLEEP(1000);
+
+ return;
+}
+
+unsigned char mono_colors[] = {0x00, 0x2a, 0x00, 0x3f};
+unsigned char normal_colors[] = {0x00, 0x2a, 0x15, 0x3f};
+
+unsigned char mono_color_bits[] = {8,16,8,16,8,16};
+unsigned char p16_color_bits[] = {4,16,2,16,1,16};
+unsigned char p64_color_bits[] = {4,32,2,16,1,8};
+
+/*!
+ *
+ * @param mmio
+ * @param n
+ *
+ * @return void
+ */
+void set_3f_palette(unsigned char *mmio, int n)
+{
+ int i;
+ for(i=0; i<n*3; i++) {
+ EMGD_WRITE8(0x3f, EMGD_MMIO(mmio) + 0x3c9);
+ }
+}
+
+/*!
+ *
+ * @param mmio
+ * @param n
+ * @param bits
+ * @param colors
+ * @param palette_hack
+ *
+ * @return void
+ */
+void set_palette_vga(unsigned char *mmio, int n, unsigned char *bits,
+ unsigned char *colors, unsigned char palette_hack)
+{
+ int i, j;
+ unsigned char *current_bits;
+ unsigned char color;
+
+ for(i=0; i<n; i++) {
+ current_bits = bits;
+ for(j=0; j<3; j++) {
+ color = colors[((i & current_bits[1])?2:0) |
+ ((i & current_bits[0])?1:0)];
+ /* Nasty Hack for Special Case VGA palette */
+ if(palette_hack && (color == 0x2a) && (i%8==6) && (j==1)) {
+ color = 0x15;
+ }
+ EMGD_WRITE8( color, EMGD_MMIO(mmio) + 0x3c9);
+ current_bits += 2;
+ }
+ }
+}
+
+/*!
+ *
+ * @param mmio
+ *
+ * @return void
+ */
+void set_256_palette(unsigned char *mmio)
+{
+ unsigned char top_of_range[] = {
+ 0x3f, 0x1c, 0x10
+ };
+ unsigned char bottom_of_range[] = {
+ 0x00, 0x1f, 0x2d,
+ 0x00, 0x0e, 0x14,
+ 0x00, 0x08, 0x0b
+ };
+ unsigned char mono_256_color[]={
+ 0x00, 0x05, 0x08,
+ 0x0B, 0x0E, 0x11,
+ 0x14, 0x18, 0x1C,
+ 0x20, 0x24, 0x28,
+ 0x2D, 0x32, 0x38,
+ 0x3F
+ };
+ unsigned char p256_color_bits[] = {4,8,2,8,1,8};
+ unsigned char *bottom = bottom_of_range;
+ unsigned char *top = top_of_range;
+ unsigned char pattern_number[] = {4, 0, 0};
+ unsigned char changing_pattern = 2;
+ unsigned short adder;
+ char diff = 1;
+ int h,i,j,k,l;
+
+ set_palette_vga(mmio, 16, p256_color_bits, normal_colors, 1);
+
+ /* mono data */
+ for(i=0; i<16; i++) {
+ for (j=0; j<3; j++) {
+ EMGD_WRITE8(mono_256_color[i], EMGD_MMIO(mmio) + 0x3c9);
+ }
+ }
+ for(l=0; l<3; l++) {
+ for(k=0; k<3; k++) {
+ /* Adder is in 14.2 fixed point */
+ adder = *top - *bottom;
+ for(j=0; j<6; j++) {
+ for(i=0; i<4; i++) {
+ for(h=2; h>=0; h--) {
+ EMGD_WRITE8( *bottom + (pattern_number[h]*adder + 1)/4,
+ EMGD_MMIO(mmio) + 0x3c9);
+ }
+ pattern_number[changing_pattern] += diff;
+ }
+ diff = -diff;
+ changing_pattern++;
+ changing_pattern %= 3;
+ }
+ bottom++;
+ }
+ top++;
+ }
+ set_3f_palette(mmio, 8);
+}
+
+static unsigned char next_ar;
+static unsigned char next_cr;
+static unsigned char next_gr;
+static unsigned char *g_mmio;
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_ar_reg(unsigned char value)
+{
+ WRITE_AR(g_mmio, next_ar, value);
+ next_ar++;
+}
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_cr_reg(unsigned char value)
+{
+ write_vga_reg(g_mmio, CR_PORT, next_cr, value);
+ next_cr++;
+}
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_gr_reg(unsigned char value)
+{
+ write_vga_reg(g_mmio, GR_PORT, next_gr, value);
+ next_gr++;
+}
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param emgd_crtc
+ * @param timings
+ *
+ * @return void
+ */
+void kms_program_pipe_vga(emgd_crtc_t *emgd_crtc,
+ igd_timing_info_t *timings)
+{
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ unsigned char *mmio, i;
+ unsigned char *colors=0;
+ unsigned char palette_hack=0;
+ unsigned char *color_bits = 0;
+ int mode_index;
+ unsigned char msr_temp;
+
+ /* This is a mapping from the HAL mode number to the type of Palette
+ * being programmed for this mode. */
+ char palette_type[] = {
+ /* 9=Don't care.
+ * 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 1, 1, 1, 1, 1, 1, 1, 2, 9, 9, 9, 9, 9, 1, 1, 9,
+ 9, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 };
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ mmio = (unsigned char *)context->device_context.virt_mmadr;
+ g_mmio = mmio;
+ mode_index = timings->mode_number;
+
+ EMGD_DEBUG("IGD Mode#:0x%x", mode_index);
+
+ /* Disable Group 0 Protection */
+ write_vga_reg(mmio, CR_PORT, 0x11, 0x00);
+
+ /*
+ * Note: for monochrome modes this will cause the IO port to change
+ * for the CRTC and the Status regs.
+ */
+ msr_temp = (*vga_mode_data_ptr)[mode_index].misc_reg;
+
+#ifdef CONFIG_GN4
+ /*
+ * According to Chrontel the VGA By-pass requires the HSYNC and VSYNC to be
+ * of positive polarity. In the MSR - Miscellaneous Output register
+ * Bit 7 is CRT VSYNC polarity (0 = Positive, 1 = Negative)
+ * Bit 6 is CRT HSYNC polarity (0 = Positive, 1 = Negative)
+ */
+ {
+ pt = get_port_type(emgd_crtc->crtc_id);
+ if (pt == IGD_PORT_DIGITAL) {
+ msr_temp &= (~(BIT(7)|BIT(6)));
+ }
+ }
+#endif
+ EMGD_WRITE8(msr_temp, EMGD_MMIO(mmio) + 0x3c2);
+
+ if((*vga_mode_data_ptr)[mode_index].misc_reg & 1) {
+ vga_port_offset = 0x20;
+ } else {
+ vga_port_offset = 0;
+ }
+
+ /* Sequencer registers */
+ /*
+ * Note: Most specs say 0 in SR00 scratch bits but in practice seems
+ * that everyone uses 3.
+ */
+ write_vga_reg(mmio, SR_PORT, 0x00, 0x03);
+ /* SR01 is on/off and done in program plane */
+ for (i=2; i<=4; i++) {
+ write_vga_reg(mmio, SR_PORT, i,
+ /* The SR Regs in the table are from SR01-SR04, there is
+ * no SR00 in the table, so -1. */
+ (*vga_mode_data_ptr)[mode_index].sr_regs[i-1]);
+ }
+
+ /* Graphics control registers 0x0-0x8,0x10 */
+ next_gr = 0;
+ for(i=0; i<=0x8; i++) {
+ write_next_gr_reg((*vga_mode_data_ptr)[mode_index].gr_regs[i]);
+ }
+ /*
+ * GR10 is a non-standard register that controls the mapping of
+ * 0xa000 to MMIO or GTT memory.
+ */
+ next_gr = 0x10;
+ write_next_gr_reg(0x0);
+
+ next_ar = 0;
+ for(i=0; i<=0x13; i++) {
+ write_next_ar_reg((*vga_mode_data_ptr)[mode_index].ar_regs[i]);
+ }
+ /* Spec says 0x8 for text modes, not done in practice */
+ write_next_ar_reg(0x00);
+
+ /* Ensure the Pixel Data Mask Register does not mask the pixel data */
+ EMGD_WRITE8(0xFF, EMGD_MMIO(mmio) + 0x3c6);
+
+ /* set DAC data value */
+ EMGD_WRITE8(0, EMGD_MMIO(mmio) + 0x3c8);
+
+ /* Load RAMDAC*/
+ switch(palette_type[mode_index]){
+ case 0:
+ color_bits = p64_color_bits;
+ colors = normal_colors;
+ palette_hack = 0;
+ break;
+ case 1:
+ color_bits = p16_color_bits;
+ colors = normal_colors;
+ palette_hack = 1;
+ break;
+ case 2:
+ color_bits = mono_color_bits;
+ colors = mono_colors;
+ palette_hack = 0;
+ break;
+ default:
+ break;
+ }
+ /* Program the Palette based on the mode. */
+ if (!vga_disable_default_palette_load) {
+ if (color_bits) {
+ set_palette_vga(mmio, 64, color_bits, colors, palette_hack);
+ set_3f_palette(mmio, 192);
+ } else {
+ set_256_palette(mmio);
+ }
+ }
+
+ /* Timings */
+ next_cr = 0;
+ for(i=0; i<=0x18; i++) {
+ write_next_cr_reg((*vga_mode_data_ptr)[mode_index].crtc_regs[i]);
+ }
+
+ return;
+}
+
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void program_pipe_vga(igd_display_context_t *display,
+ igd_timing_info_t *timings)
+{
+ unsigned char *mmio, i;
+ unsigned char *colors=0;
+ unsigned char palette_hack=0;
+ unsigned char *color_bits = 0;
+ int mode_index;
+ unsigned char msr_temp;
+
+ /* This is a mapping from the HAL mode number to the type of Palette
+ * being programmed for this mode. */
+ char palette_type[] = {
+ /* 9=Don't care.
+ * 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 1, 1, 1, 1, 1, 1, 1, 2, 9, 9, 9, 9, 9, 1, 1, 9,
+ 9, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 };
+
+ EMGD_DEBUG("Enter program_pipe_vga");
+
+ mmio = (unsigned char *)MMIO(display);
+ g_mmio = mmio;
+ mode_index = timings->mode_number;
+
+ EMGD_DEBUG("IGD Mode#:0x%x", mode_index);
+
+ /* Disable Group 0 Protection */
+ write_vga_reg(mmio, CR_PORT, 0x11, 0x00);
+
+ /*
+ * Note: for monochrome modes this will cause the IO port to change
+ * for the CRTC and the Status regs.
+ */
+ msr_temp = (*vga_mode_data_ptr)[mode_index].misc_reg;
+
+#ifdef CONFIG_GN4
+ /*
+ * According to Chrontel the VGA By-pass requires the HSYNC and VSYNC to be
+ * of positive polarity. In the MSR - Miscellaneous Output register
+ * Bit 7 is CRT VSYNC polarity (0 = Positive, 1 = Negative)
+ * Bit 6 is CRT HSYNC polarity (0 = Positive, 1 = Negative)
+ */
+ {
+ igd_display_port_t *port;
+ port = PORT_OWNER(display);
+ if (port->port_type == IGD_PORT_DIGITAL) {
+ msr_temp &= (~(BIT(7)|BIT(6)));
+ }
+ }
+#endif
+ EMGD_WRITE8(msr_temp, EMGD_MMIO(mmio) + 0x3c2);
+
+ if((*vga_mode_data_ptr)[mode_index].misc_reg & 1) {
+ vga_port_offset = 0x20;
+ } else {
+ vga_port_offset = 0;
+ }
+
+ /* Sequencer registers */
+ /*
+ * Note: Most specs say 0 in SR00 scratch bits but in practice seems
+ * that everyone uses 3.
+ */
+ write_vga_reg(mmio, SR_PORT, 0x00, 0x03);
+ /* SR01 is on/off and done in program plane */
+ for (i=2; i<=4; i++) {
+ write_vga_reg(mmio, SR_PORT, i,
+ /* The SR Regs in the table are from SR01-SR04, there is
+ * no SR00 in the table, so -1. */
+ (*vga_mode_data_ptr)[mode_index].sr_regs[i-1]);
+ }
+
+ /* Graphics control registers 0x0-0x8,0x10 */
+ next_gr = 0;
+ for(i=0; i<=0x8; i++) {
+ write_next_gr_reg((*vga_mode_data_ptr)[mode_index].gr_regs[i]);
+ }
+ /*
+ * GR10 is a non-standard register that controls the mapping of
+ * 0xa000 to MMIO or GTT memory.
+ */
+ next_gr = 0x10;
+ write_next_gr_reg(0x0);
+
+ next_ar = 0;
+ for(i=0; i<=0x13; i++) {
+ write_next_ar_reg((*vga_mode_data_ptr)[mode_index].ar_regs[i]);
+ }
+ /* Spec says 0x8 for text modes, not done in practice */
+ write_next_ar_reg(0x00);
+
+ /* Ensure the Pixel Data Mask Register does not mask the pixel data */
+ EMGD_WRITE8(0xFF, EMGD_MMIO(mmio) + 0x3c6);
+
+ /* set DAC data value */
+ EMGD_WRITE8(0, EMGD_MMIO(mmio) + 0x3c8);
+
+ /* Load RAMDAC*/
+ switch(palette_type[mode_index]){
+ case 0:
+ color_bits = p64_color_bits;
+ colors = normal_colors;
+ palette_hack = 0;
+ break;
+ case 1:
+ color_bits = p16_color_bits;
+ colors = normal_colors;
+ palette_hack = 1;
+ break;
+ case 2:
+ color_bits = mono_color_bits;
+ colors = mono_colors;
+ palette_hack = 0;
+ break;
+ default:
+ break;
+ }
+ /* Program the Palette based on the mode. */
+ if (!vga_disable_default_palette_load) {
+ if (color_bits) {
+ set_palette_vga(mmio, 64, color_bits, colors, palette_hack);
+ set_3f_palette(mmio, 192);
+ } else {
+ set_256_palette(mmio);
+ }
+ }
+
+ /* Timings */
+ next_cr = 0;
+ for(i=0; i<=0x18; i++) {
+ write_next_cr_reg((*vga_mode_data_ptr)[mode_index].crtc_regs[i]);
+ }
+
+ return;
+}
+
+/*
+ * The HAL mode numbers match up to VGA modes in this way:
+ * VGA Mode : HAL Mode
+ * 00 00
+ * 01 01
+ * 02 02
+ * 03 03
+ * 04 04
+ * 05 05
+ * 06 06
+ * 07 07
+ * 0d 0d
+ * 0e 0e
+ * 0f 11
+ * 10 12
+ * 00* 13
+ * 01* 14
+ * 02* 15
+ * 03* 16
+ * 00+ 17
+ * 01+ 17
+ * 02+ 18
+ * 03+ 18
+ * 07+ 19
+ * 11 1A
+ * 12 1B
+ * 13 1C
+ */
+
+/* This can not be a static, since the vBIOS will use this as a global */
+vga_mode_data_t VB_CODE_SEG vga_mode_data[] = {
+ /*============================================================================*/
+ /* Modes 00h (Text 40 x 25 Colors 16 gray Font 8 x 8) - Table Entry 00h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x0800, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+ 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 01h (Text 40 x 25 Colors 16 gray Font 8 x 8) - Table Entry 01h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x0800, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+ 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 02h (Text 80 x 25 Colors 16 gray Font 8 x 8) - Table Entry 02h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x08, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 03h (Text 80 x 25 Colors 16 Font 8 x 8) - Table Entry 03h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x08, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 04h (Graphics 320 x 200 Colors 4 Font 8 x 8) - Table Entry 04h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x4000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+ 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xA2,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x03,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 05h (Graphics 320 x 200 Colors 4 gray Font 8 x 8) - Table 05h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x4000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+ 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xA2,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x03,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 06h (Graphics 640 x 200 Colors 2 Font 8 x 8) - Table Entry 06h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x08, /* Text Columns Rows Font */
+ 0x4000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x01,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+ 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xC2,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+ 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+ 0x01,0x00,0x01,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 07h (Text 80 x 25 Colors 2 Font 9 x 14) - Table Entry 07h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x00,0x03,0x00,0x03},
+
+ /* Miscellaneous output register value. */
+ 0xA6,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x28,0x0D,0x63,0xBA,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x0E,0x00,0x0F,0x08},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0A,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 08h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x10, /* Text Columns Rows Font */
+ 0x7D00, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x21,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 09h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x00,0x00,0x00, /* Text Columns Rows Font */
+ 0x0000, /* Page size */
+
+ /* Sequencer register values. */
+ {0x00,0x00,0x00,0x00},
+
+ /* Miscellaneous output register value. */
+ 0x00,
+
+ /* CRT Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00},
+
+ /* Attribute Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 0Ah */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x4000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x00,0x00,0x00,0x03},
+
+ /* Miscellaneous output register value. */
+ 0x23,
+
+ /* CRT Controller register values. */
+ {0x37,0x27,0x2D,0x37,0x31,0x15,0x04,0x11,
+ 0x00,0x47,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0xE1,0x24,0xC7,0x14,0x08,0xE0,0xF0,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 0Bh */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x00,0x00, /* Text Columns Rows Font */
+ 0x0000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x29,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x62,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x0F,0x00,0x00,0x08,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 0Ch */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x00,0x00, /* Text Columns Rows Font */
+ 0x0000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x29,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x0F,0x00,0x00,0x08,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 0Dh (Graphics 320 x 200 Colors 16 Font 8 x 8) - Table Entry 0Dh */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x2000, /* Page size */
+
+ /* Sequencer register values. */
+ {0x09,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+ 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 0Eh (Graphics 640 x 200 Colors 16 Font 8 x 8) - Table Entry 0Eh */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x08, /* Text Columns Rows Font */
+ 0x4000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+ 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 0Fh */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x8000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x05,0x0F,0x00,0x00},
+
+ /* Miscellaneous output register value. */
+ 0xA2,
+
+ /* CRT Controller register values. */
+ {0x60,0x4F,0x56,0x1A,0x50,0xE0,0x70,0x1F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5E,0x2E,0x5D,0x14,0x00,0x5E,0x6E,0x8B,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+ 0x0B,0x00,0x05,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Blank Entry - Table Entry 10h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x8000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x05,0x0F,0x00,0x00},
+
+ /* Miscellaneous output register value. */
+ 0xA7,
+
+ /* CRT Controller register values. */
+ {0x5B,0x4F,0x53,0x17,0x50,0xBA,0x6C,0x1F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5E,0x2B,0x5D,0x14,0x0F,0x5F,0x0A,0x8B,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x00,0x00,0x04,0x07,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x04,0x07,0x00,0x00,
+ 0x01,0x00,0x05,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 0Fh; (Graphics 640 x 350 Colors 2 Font 8 x 14) - Table Entry 11h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x8000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0xA2,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x28,0x0F,0x63,0xBA,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+ 0x0B,0x00,0x05,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 10h; (Graphics 640 x 350 Colors 16 Font 8 x 14) - Table Entry 12h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x8000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0xA3,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x28,0x0F,0x63,0xBA,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 00h; (Text 40 x 25 Colors 16 gray Font 8 x 14) - Table Entry 13h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x0E, /* Text Columns Rows Font */
+ 0x0800, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0xA3,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+ 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x14,0x1F,0x63,0xBA,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 01h; (Text 40 x 25 Colors 16 Font 8 x 14) - Table Entry 14h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x0E, /* Text Columns Rows Font */
+ 0x0800, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x09,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0xA3,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+ 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x14,0x1F,0x63,0xBA,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+// ; Modes 02h; (Text 80 x 25 Colors 16 gray Font 8 x 14) - Table Entry 15h //
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0xA3,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x28,0x1F,0x63,0xBA,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 03h; (Text 80 x 25 Colors 16 Font 8 x 14) - Table Entry 16h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x0E, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0xA3,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5D,0x28,0x1F,0x63,0xBA,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x08,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 00h+ ; 01h+ (Text 40 x 25 Colors 16 Font 9 x 16) - Table 17h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x10, /* Text Columns Rows Font */
+ 0x0800, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x08,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x67,
+
+ /* CRT Controller register values. */
+ {0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+ 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x0C,0x00,0x0F,0x08},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 02h+ ; 03h+ (Text 80 x 25 Colors 16 Font 9 x 16) - Table 18h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x10, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x00,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x67,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x0C,0x00,0x0F,0x08},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 07h+ (Text 80 x 25 Colors 2 Font 9 x 16) - Table Entry 19h */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x18,0x10, /* Text Columns Rows Font */
+ 0x1000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x00,0x03,0x00,0x02},
+
+ /* Miscellaneous output register value. */
+ 0x66,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+ 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x0F,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x0E,0x00,0x0F,0x08},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0A,0x00,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 11h (Graphics 640 x 480 Colors 2 Font 8 x 16) - Table Entry 1Ah */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x1D,0x10, /* Text Columns Rows Font */
+ 0xA000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0xE3,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xC3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ 0x01,0x00,0x01,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 12h (Graphics 640 x 480 Colors 16 Font 8 x 16) - Table Entry 1Bh */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x50,0x1D,0x10, /* Text Columns Rows Font */
+ 0xA000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x06},
+
+ /* Miscellaneous output register value. */
+ 0xE3,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+ 0x01,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+ 0xFF},
+ },
+
+ /*============================================================================*/
+ /* Modes 13h (Graphics 320 x 200 Colors 256 Font 8 x 8) - Table Entry 1Ch */
+ /*----------------------------------------------------------------------------*/
+ {
+ 0x28,0x18,0x08, /* Text Columns Rows Font */
+ 0x2000, /* Page size */
+
+ /* Sequencer register values, SR01-SR04. */
+ {0x01,0x0F,0x00,0x0E},
+
+ /* Miscellaneous output register value. */
+ 0x63,
+
+ /* CRT Controller register values. */
+ {0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+ 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9C,0x8E,0x8F,0x28,0x40,0x96,0xB9,0xA3,
+ 0xFF},
+
+ /* Attribute Controller register values. */
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+ 0x41,0x00,0x0F,0x00},
+
+ /* Graphics Controller register values. */
+ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,
+ 0xFF}
+ },
+};
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
new file mode 100644
index 0000000..f39e9d2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
@@ -0,0 +1,711 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: clocks_plb.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd_mode.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <dsp.h>
+#include <utils.h>
+#include <mode.h>
+#include <pi.h>
+#include <sched.h>
+
+#include "drm_emgd_private.h"
+#include <plb/regs.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*===========================================================================
+; File Global Data
+;--------------------------------------------------------------------------*/
+typedef struct _fixed_clock {
+ unsigned long dclk;
+ unsigned long n;
+ unsigned long m1;
+ unsigned long m2;
+ unsigned long p;
+}fixed_clock_t;
+
+static fixed_clock_t fixed_clock_table[] = {
+ /* Clock N M1 M2 Post Div */
+ { 43163, 0x03, 0x12, 0x06, 0x84}, /* 43.163 GTF for 640x480 @ 100Hz */
+ { 81624, 0x03, 0x18, 0x04, 0x82}, /* 81.624MHz */
+ {0xffffffff, 0x00, 0x00, 0x00, 0x00}
+};
+
+/*!
+ * This function translates from the calculated M value to the M1, M2
+ * register values.
+ *
+ * @param m
+ * @param *m1
+ * @param *m2
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_m1_m2(unsigned long m,
+ unsigned long *m1,
+ unsigned long *m2)
+{
+ unsigned long current_m1, current_m2;
+
+ EMGD_DEBUG("Enter calculate_m1_m2 %d", 1);
+
+ /* ori was in steps of 2*/
+ for(current_m1 = (10+2); current_m1 <= (20+2); current_m1 += 1) {
+ for(current_m2 = (5+2); current_m2 <= (9+2); current_m2++) {
+ if((current_m1 * 5 + current_m2) == m) {
+ *m1 = current_m1 - 2;
+ *m2 = current_m2 - 2;
+ return 0;
+ }
+
+ }
+ }
+
+ EMGD_DEBUG("M1, M2 not found for M == %ld", m);
+ return 1;
+}
+
+#define MAX_M 120 //216
+#define MIN_M 70 //96
+
+#define MAX_N 8 //16
+#define MIN_N 3
+
+#define MAX_P 80 //126
+#define MIN_P 5 //2
+
+#define LVDS_MAX_P 98
+#define LVDS_MIN_P 7
+
+#define FIX_P2_LO 5 //126
+#define FIX_P2_HI 10 //2
+
+#define MAX_P1 8 //126
+#define MIN_P1 1 //2
+
+#define REF_FREQ 96000 //48000
+#define MAX_VCO 2800000 //1400000
+#define MAX_FP 200000
+/* For LVDS port */
+#define LVDS_FIX_P2_LO 7
+#define LVDS_FIX_P2_HI 14
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param m1
+ * @param m2
+ * @param n
+ * @param p
+ * @param min_vco
+ * @param target_error
+ * @param port_type
+ * @param dual_channel
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_clock(unsigned long dclk,
+ unsigned long ref_freq,
+ unsigned long *m1,
+ unsigned long *m2,
+ unsigned long *n,
+ unsigned long *p,
+ unsigned long min_vco,
+ unsigned long target_error,
+ unsigned long port_type,
+ unsigned long dual_channel)
+
+{
+ unsigned long p1;
+ unsigned long p2;
+ /* Parameters */
+ unsigned long freqmult_p2;
+
+ /* Intermidiate variables */
+ unsigned long pdiv;
+ unsigned long target_vco, actual_freq, actual_vco;
+ long freq_error, min_error;
+
+ unsigned long current_m, current_n, current_p1;
+ unsigned long best_m = 0;
+ unsigned long best_n = 0;
+ unsigned long best_p1 = 0;
+
+
+ EMGD_DEBUG("Enter calculate_clock");
+
+ min_error = 100000;
+
+ if (dclk > MAX_FP) {
+ freqmult_p2 = FIX_P2_LO;
+ } else {
+ freqmult_p2 = FIX_P2_HI;
+ }
+
+ /* For LVDS port */
+ if(port_type==IGD_PORT_LVDS){
+ /* Test if we are dual channel */
+ if(dual_channel){
+ freqmult_p2=LVDS_FIX_P2_LO;
+ } else{
+ freqmult_p2=LVDS_FIX_P2_HI;
+ }
+
+ }
+
+ for(current_m = MIN_M; current_m <= MAX_M; current_m++) {
+ for(current_n = MIN_N; current_n < MAX_N; current_n++) {
+ for(current_p1 = MIN_P1; current_p1 <= MAX_P1; current_p1++) {
+
+ pdiv = freqmult_p2 * current_p1;
+ target_vco = dclk * pdiv;
+
+ if ((target_vco <= MAX_VCO) && (target_vco >= min_vco)) {
+ actual_freq = (ref_freq * current_m) /
+ (current_n * pdiv);
+ actual_vco = actual_freq * pdiv;
+ freq_error = 10000 - (dclk * 10000 / actual_freq);
+
+ if (freq_error < 0) {
+ freq_error = -freq_error;
+ }
+ if (freq_error < min_error) {
+ best_n = current_n;
+ best_m = current_m;
+ best_p1 = current_p1;
+ min_error = freq_error;
+ }
+ if (min_error == 0) {
+ break;
+ }
+ }
+ }
+ if (min_error == 0) {
+ break;
+ }
+ }
+ if (min_error == 0) {
+ break;
+ }
+ }
+ /*
+ * No clock found that meets error requirement
+ */
+ if (min_error > (long)target_error) {
+ return 1;
+ }
+
+
+ /* Translate M,N,P to m1,m2,n,p register values */
+ *n = best_n - 2;
+ if(calculate_m1_m2(best_m, m1, m2)) {
+ /* No M1, M2 match for M */
+ return 1;
+ }
+
+ p1 = (1 << (best_p1-1));
+ if((freqmult_p2-5)) {
+ p2 = 0x0;
+ }
+ else {
+ p2 = 0x1;
+ }
+ /* Set p2 for LVDS */
+ if(port_type==IGD_PORT_LVDS){
+ if(dual_channel){
+ p2=0x1;
+ }else{
+ p2=0x0;
+ }
+
+ }
+ *p = ( p1 | (p2<<8) );
+
+ return 0;
+}
+
+#define MIN_VCO_PASS1 2000000 //1000000
+#define MIN_VCO_PASS2 1400000 //930000
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param m1
+ * @param m2
+ * @param n
+ * @param p
+ * @param target_error
+ * @param port_type
+ * @param dual_channel
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int get_clock(unsigned long dclk,
+ unsigned long ref_freq,
+ unsigned long *m1,
+ unsigned long *m2,
+ unsigned long *n,
+ unsigned long *p,
+ unsigned long target_error,
+ unsigned long port_type,
+ unsigned long dual_channel)
+{
+ fixed_clock_t *fixed = fixed_clock_table;
+
+ EMGD_DEBUG("Enter get_clock");
+
+ /*
+ * First check for a fixed clock from the table. These are ones that
+ * can't be calculated correctly.
+ */
+ while(fixed->dclk != 0xffffffff) {
+ if(fixed->dclk == dclk) {
+ EMGD_DEBUG("Using Fixed Clock From table for clock %ld", dclk);
+ *m1 = fixed->m1;
+ *m2 = fixed->m2;
+ *n = fixed->n;
+ *p = fixed->p;
+ return 0;
+ }
+ fixed++;
+ }
+
+
+ /*
+ * No fixed clock found so calculate one.
+ */
+ EMGD_DEBUG("Calculating dynamic clock for clock %ld", dclk);
+
+ /*
+ * First pass try to find a clock with min_vco at 1000000.
+ * If a clock doesn't come out then try 930000.
+ */
+ if(calculate_clock(dclk, ref_freq, m1, m2, n, p, MIN_VCO_PASS1,
+ target_error,port_type,dual_channel)) {
+ if(calculate_clock(dclk, ref_freq, m1, m2, n, p, MIN_VCO_PASS2,
+ target_error,port_type,dual_channel)) {
+ /* No usable clock */
+ EMGD_ERROR("Could not calculate clock %ld, returning default.",
+ dclk);
+ *m1 = 0x14;
+ *m2 = 0xc;
+ *n = 0x3;
+ *p = 0x82;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#define TARGET_ERROR 46
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_plb(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ unsigned long m1, m2, n, p;
+ unsigned long control;
+ unsigned long ref_freq;
+ int ret;
+ unsigned long port_mult, vga_mult;
+ unsigned long dual_channel = 0;
+ unsigned long index;
+ unsigned long pt;
+ struct drm_device *dev = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+
+ EMGD_DEBUG("Enter program_clock");
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ pt = port->port_type;
+ break;
+ }
+ }
+ if (!port) {
+ EMGD_ERROR_EXIT("No port");
+ return -1;
+ }
+
+ if (dclk > 100000) { /* 100-200 MHz */
+
+ port_mult = 1;
+ }
+ else if (dclk > 50000) { /* 50-100 Mhz */
+
+ port_mult = 2;
+ }
+ else { /* 25-50 Mhz */
+
+ port_mult = 4;
+ }
+
+ /*
+ * Clock Multiplier : sDVO ports on all plb chipsets
+ */
+ if (pt == IGD_PORT_DIGITAL) {
+
+ dclk *= port_mult;
+ }
+
+ vga_mult = EMGD_READ32(context->device_context.virt_mmadr + clock->dpll_control) & 0x3;
+
+ /* For Int-LVDS need to find out if its dual channel and pass
+ * that info into caluculating for p2. Apperently halving
+ * of dot-clock is also required by Ch7017 when operating in
+ * dual channel
+ */
+ if (pt == IGD_PORT_LVDS) {
+ /* Find PD_ATTR_ID_2_CHANNEL_PANEL attr value*/
+ pi_pd_find_attr_and_value(port,
+ PD_ATTR_ID_2_CHANNEL_PANEL,
+ 0/*no PD_FLAG for 2_channel*/,
+ NULL,
+ &dual_channel);
+ }
+
+ /* For external clock sources always use ref_clock == dclk */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ref_freq = dclk;
+ } else {
+ ref_freq = 96000;
+ }
+ /* LVDS reference clock can be 96 or 100 MHz. However there
+ * are no mention in the specification to specify which register
+ * to select/set this.
+ */
+
+ /* When the clock source is provided externally by the port driver,
+ * the allowed error range is 0. */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, 0
+ ,pt,dual_channel);
+ } else {
+ ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, TARGET_ERROR
+ ,pt,dual_channel);
+ }
+
+ if(ret) {
+ EMGD_ERROR("Clock %ld could not be programmed", dclk);
+ return ret;
+ }
+
+ /* Disable DPLL, Write an 0x80 into P for saftey */
+ control = 0x10000000 | (0x80<<clock->p_shift) | BIT26 | vga_mult;
+ EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+
+ /* Program N, M1,and M2 */
+ EMGD_WRITE32((n<<16) | (m1<<8) | m2, context->device_context.virt_mmadr + clock->mnp);
+
+ /* Enable DPLL, Disable VGAm Mode and sitck in new P values */
+ if(pt == IGD_PORT_LVDS){
+ /* If LVDS set the appropriate bits for mode select */
+ control = (BIT31 | BIT28 | BIT27 )
+ | (p<<clock->p_shift) | vga_mult;
+
+ if(port->attr_list) {
+
+ for(index = 0; index < port->attr_list->num_attrs; index++) {
+
+ /* Set spread spectrum and pulse phase */
+ if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+
+ /*
+ * Pulse Phase for Poulsbo only has valid values between
+ * 3 and 9
+ */
+ if(port->attr_list->attr[index].value >= 3 &&
+ port->attr_list->attr[index].value <= 9) {
+
+ control |= BIT13 | BIT14;
+ /*
+ * Set the Pulse Phase to the clock phase specified by
+ * the user
+ */
+ control |= (port->attr_list->attr[index].value<<9);
+ }
+ break;
+ }
+ }
+ }
+ } else{
+ /* else DAC/SDVO */
+ control = (BIT31 | BIT28 | BIT26) | (p<<clock->p_shift) | vga_mult;
+ }
+ /*
+ * Poulsbo has high speed clock on always
+ */
+ control |= BIT30;
+
+
+
+ /* Set the clock source correctly based on PD settings */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ control |= port->clock_bits;
+ } else {
+ control |= port->clock_bits & ~0x00006000;
+ }
+
+ /* sDVO Multiplier bits[7:0] */
+ if (pt == IGD_PORT_DIGITAL) {
+
+ if (port_mult == 2) {
+
+ control |= (1 << 4);
+
+ } else if (port_mult == 4) {
+
+ control |= (3 << 4);
+ }
+ }
+
+ EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+
+ /* We must wait for 150 us for the dpll clock to warm up */
+ OS_SLEEP(150);
+ pipe->dclk = dclk;
+
+ return 0;
+}
+
+
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_plb(igd_display_context_t *display,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ unsigned long m1, m2, n, p;
+ unsigned long control;
+ unsigned long ref_freq;
+ int ret;
+ igd_display_port_t *port;
+ unsigned long port_mult, vga_mult;
+ unsigned long dual_channel = 0;
+ unsigned long index;
+
+ EMGD_DEBUG("Enter program_clock");
+
+ port=PORT_OWNER(display);
+
+ if (dclk > 100000) { /* 100-200 MHz */
+
+ port_mult = 1;
+ }
+ else if (dclk > 50000) { /* 50-100 Mhz */
+
+ port_mult = 2;
+ }
+ else { /* 25-50 Mhz */
+
+ port_mult = 4;
+ }
+
+ /*
+ * Clock Multiplier : sDVO ports on all plb chipsets
+ */
+ if (port->port_type == IGD_PORT_DIGITAL) {
+
+ dclk *= port_mult;
+ }
+
+ vga_mult = READ_MMIO_REG(display, clock->dpll_control) & 0x3;
+
+ /* For Int-LVDS need to find out if its dual channel and pass
+ * that info into caluculating for p2. Apperently halving
+ * of dot-clock is also required by Ch7017 when operating in
+ * dual channel
+ */
+ if (port->port_type == IGD_PORT_LVDS) {
+ /* Find PD_ATTR_ID_2_CHANNEL_PANEL attr value*/
+ pi_pd_find_attr_and_value(PORT_OWNER(display),
+ PD_ATTR_ID_2_CHANNEL_PANEL,
+ 0/*no PD_FLAG for 2_channel*/,
+ NULL,
+ &dual_channel);
+ }
+
+ /* For external clock sources always use ref_clock == dclk */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ref_freq = dclk;
+ } else {
+ ref_freq = 96000;
+
+ /* If SSC is enabled, then the reference frequency needs to be
+ * 100000 instead of 96000.
+ */
+ for(index = 0; index < port->attr_list->num_attrs; index++) {
+ if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+ ref_freq = 100000;
+ break;
+ }
+ }
+ }
+ /* LVDS reference clock can be 96 or 100 MHz. However there
+ * are no mention in the specification to specify which register
+ * to select/set this.
+ */
+
+ /* When the clock source is provided externally by the port driver,
+ * the allowed error range is 0. */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, 0
+ ,port->port_type,dual_channel);
+ } else {
+ ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, TARGET_ERROR
+ ,port->port_type,dual_channel);
+ }
+
+ if(ret) {
+ EMGD_ERROR("Clock %ld could not be programmed", dclk);
+ return ret;
+ }
+
+ /* Disable DPLL, Write an 0x80 into P for saftey */
+ control = 0x10000000 | (0x80<<clock->p_shift) | BIT26 | vga_mult;
+ WRITE_MMIO_REG(display, clock->dpll_control, control);
+
+ /* Program N, M1,and M2 */
+ WRITE_MMIO_REG(display, clock->mnp, (n<<16) | (m1<<8) | m2);
+
+ /* Enable DPLL, Disable VGAm Mode and sitck in new P values */
+ if(port->port_type==IGD_PORT_LVDS){
+ /* If LVDS set the appropriate bits for mode select */
+ control = (BIT31 | BIT28 | BIT27 )
+ | (p<<clock->p_shift) | vga_mult;
+
+ if(port->attr_list) {
+
+ for(index = 0; index < port->attr_list->num_attrs; index++) {
+
+ /* Set spread spectrum and pulse phase */
+ if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+
+ /*
+ * Pulse Phase for Poulsbo only has valid values between
+ * 3 and 9
+ */
+ if(port->attr_list->attr[index].value >= 3 &&
+ port->attr_list->attr[index].value <= 9) {
+
+ control |= BIT13 | BIT14;
+ /*
+ * Set the Pulse Phase to the clock phase specified by
+ * the user
+ */
+ control |= (port->attr_list->attr[index].value<<9);
+ }
+ break;
+ }
+ }
+ }
+ } else{
+ /* else DAC/SDVO */
+ control = (BIT31 | BIT28 | BIT26) | (p<<clock->p_shift) | vga_mult;
+ }
+ /*
+ * Poulsbo has high speed clock on always
+ */
+ control |= BIT30;
+
+
+
+ /* Set the clock source correctly based on PD settings */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ control |= port->clock_bits;
+ } else {
+ control |= port->clock_bits & ~0x00006000;
+ }
+
+ /* sDVO Multiplier bits[7:0] */
+ if (port->port_type == IGD_PORT_DIGITAL) {
+
+ if (port_mult == 2) {
+
+ control |= (1 << 4);
+
+ } else if (port_mult == 4) {
+
+ control |= (3 << 4);
+ }
+ }
+
+ WRITE_MMIO_REG(display, clock->dpll_control, control);
+
+ /* We must wait for 150 us for the dpll clock to warm up */
+ OS_SLEEP(150);
+ PIPE(display)->dclk = dclk;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
new file mode 100644
index 0000000..ec1546d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
@@ -0,0 +1,1102 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: kms_mode_plb.c
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#include <igd.h>
+#include <igd_pwr.h>
+#include <vga.h>
+#include <pi.h>
+#include <plb/regs.h>
+#include "drm_emgd_private.h"
+#include "../cmn/mode_dispatch.h"
+#include "../cmn/match.h"
+#include "mode_plb.h"
+#include <math_fix.h>
+#include <memory.h>
+
+
+/*------------------------------------------------------------------------------
+ * Function Prototypes
+ *----------------------------------------------------------------------------*/
+int kms_mode_get_stride_stereo_plb(igd_display_pipe_t *pipe,
+ igd_display_plane_t *plane,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags);
+void kms_program_pipe_vga_plb(emgd_crtc_t *emgd_crtc);
+static void kms_program_pipe_plb(emgd_crtc_t *emgd_crtc);
+static void kms_set_pipe_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static void kms_program_plane_plb(emgd_crtc_t *emgd_crtc, unsigned long status);
+static void kms_set_plane_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static int set_color_correct_plb(emgd_crtc_t *emgd_crtc);
+
+
+extern int kms_program_clock_plb(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock, unsigned long dclk);
+extern int wait_for_vblank_plb(unsigned char *mmio,
+ unsigned long pipe_reg);
+extern void kms_program_pipe_vga(emgd_crtc_t *emgd_crtc,
+ igd_timing_info_t *timings);
+extern void disable_vga_plb(unsigned char *mmio);
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *----------------------------------------------------------------------------*/
+extern mode_data_plb_t device_data_plb[1];
+
+
+/*------------------------------------------------------------------------------
+ * KMS Dispatch Table
+ *----------------------------------------------------------------------------*/
+mode_kms_dispatch_t mode_kms_dispatch_plb = {
+ kms_program_pipe_plb,
+ kms_set_pipe_pwr_plb,
+ kms_program_plane_plb,
+ kms_set_plane_pwr_plb,
+ NULL,
+ NULL,
+ NULL, /* kms_get_vblank_counter */
+ kms_match_mode,
+};
+
+
+/*!
+ * Get the stride and stereo values based on the display. This is also used
+ * by the MI instructions.
+ *
+ * @param pipe Pointer to hardware device instance data
+ * @param plane Pointer to hardware device instance data
+ * @param stride
+ * @param stereo
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int kms_mode_get_stride_stereo_plb(igd_display_pipe_t *pipe,
+ igd_display_plane_t *plane,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags)
+{
+ unsigned long pitch = plane->fb_info->screen_pitch;
+ igd_timing_info_t *timing = pipe->timing;
+ unsigned long base_offset;
+
+ base_offset = plane->fb_info->visible_offset;
+
+ *stride = pitch;
+ *stereo = 0;
+
+ /* For field replication, valid for interlaced modes only
+ * set stereo = fb_base,
+ * stride = pitch
+ */
+ if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+ if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* Interlaced + Line double flags means field replication.
+ * same lines are sent for both fields. Program the
+ * second eye to be same as the first.
+ */
+ *stereo = base_offset;
+ } else {
+ /* Regular interlaced. Second eye starts on line 2.
+ * Skip every other line.
+ */
+ *stereo = base_offset + pitch;
+ *stride = pitch * 2;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_plb(emgd_crtc_t *emgd_crtc)
+{
+ const int MID_PIXEL_VAL = 125;
+ const int MAX_PIXEL_VAL = 255;
+ const int NUM_PALETTE_ENTRIES = 256;
+
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+
+ unsigned int gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+ unsigned int gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+ unsigned int gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+ unsigned int new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+ unsigned int new_gamma_b_24i_8f;
+ unsigned int gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ int brightness_factor_r, brightness_factor_g;
+ int brightness_factor_b;
+ int contrast_factor_r, contrast_factor_g;
+ int contrast_factor_b;
+
+ unsigned int *palette;
+ unsigned int i;
+
+ igd_range_attr_t *gamma_attr = NULL, *contrast_attr = NULL;
+ igd_range_attr_t *brightness_attr = NULL;
+ igd_attr_t *hal_attr_list = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+ if (!port) {
+ EMGD_ERROR_EXIT("No port being used.");
+ return -IGD_ERROR_INVAL;
+ }
+ hal_attr_list = port->attributes;
+
+ /* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+ palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+ /* start with a fresh palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ palette[i] = (i << 16) | (i << 8) | i;
+ }
+
+ /* get a pointer to gamma, contrast, and brightness attr */
+ i = 0;
+
+ while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+ switch (hal_attr_list[i].id) {
+ case PD_ATTR_ID_FB_GAMMA:
+ gamma_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_BRIGHTNESS:
+ brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_CONTRAST:
+ contrast_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ default:
+ break;
+ }
+
+ i++;
+ }
+
+ if(!gamma_attr || !brightness_attr || !contrast_attr) {
+ EMGD_ERROR("Color Correction Atrributes not found!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get the max and min */
+ gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+ gamma_g_max_24i_8f = ((gamma_attr->max >> 8) & 0xFF) << 3;
+ gamma_b_max_24i_8f = (gamma_attr->max & 0xFF) << 3;
+
+ gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+ gamma_g_min_24i_8f = ((gamma_attr->min >> 8) & 0xFF) << 3;
+ gamma_b_min_24i_8f = (gamma_attr->min & 0xFF) << 3;
+
+ /* The new gamma values are in 3i.5f format, but we must convert it
+ * to 24i.8f format before passing it to OS_POW_FIX
+ */
+ new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+ new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+ new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+ /* make sure the new gamma is within range */
+ new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+ new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+ gamma_normal_r_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+ gamma_normal_g_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+ gamma_normal_b_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ unsigned int new_gamma;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* Note that we do not try to calculate the gamma if it
+ * is 1.0, e.g. 0x100. This is to avoid round-off errors
+ */
+
+ /* red: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_r_24i_8f) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+ palette[i] &= 0x00FFFF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_g_24i_8f) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+ palette[i] &= 0xFF00FF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_b_24i_8f) {
+ cur_color = cur_palette & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+ palette[i] &= 0xFFFF00;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+ }
+ }
+
+
+ /* Brightness correction */
+ brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+ brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+ brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+ /* The factors are offset by 0x80 because 0x80 is 0 correction */
+ brightness_factor_r -= 0x80;
+ brightness_factor_g -= 0x80;
+ brightness_factor_b -= 0x80;
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_r;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+ /* green: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_g;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+ /* blue: calculate and make sure the result is within range */
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_b;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00;
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+
+
+ /* contrast correction */
+ contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+ contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+ contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+ /* make sure values are within range */
+ contrast_factor_r -= 0x80;
+ contrast_factor_g -= 0x80;
+ contrast_factor_b -= 0x80;
+
+
+ /* We're doing integer division in this loop using 16i.16f
+ * integers. The result will then be converted back into a
+ * regular, 32-bit integer
+ */
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ if (0 != contrast_factor_r ) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF; /* clear out the R color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0 != contrast_factor_g ) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF; /* clear out the G color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0 != contrast_factor_b) {
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00; /* clear out the B color */
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+ }
+
+
+ /* write the new values in the palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ EMGD_WRITE32(palette[i], context->device_context.virt_mmadr +
+ pipe->palette_reg + i*4);
+ }
+ OS_FREE(palette);
+
+ return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc Pointer to hardware device instance data
+ *
+ * @return void
+ */
+void kms_program_pipe_vga_plb(
+ emgd_crtc_t *emgd_crtc)
+{
+ struct drm_device *dev = NULL;
+ igd_timing_info_t *timing = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ igd_display_port_t *port = NULL;
+ unsigned long vga_control;
+ unsigned long upscale = 0;
+ int centering = 1;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+
+#ifdef CONFIG_MICRO
+ /*
+ * We cannot set a VGA mode unless the display planes are turned off.
+ * This becomes evident during a Windows BSOD. Since neither Windows
+ * nor IEGD got a chance to turn off these registers, and the VGA mode was
+ * set by the VBIOS, the screen gets corrupted. In order to fix this
+ * problem, we will turn the cursor and display planes here.
+ *
+ * Note: Removing previous partial-fix in favor of this complete one.
+ */
+ /* Cursor A */
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70080);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70084);
+ /* Cursor B */
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x700C0);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x700C4);
+ /* Display A */
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70180);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70184);
+ /* Display B */
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x71180);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x71184);
+ /* Display C */
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x72180);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x72184);
+#endif
+
+ /*
+ * VGA Plane can attach to only one pipe at a time. LVDS can
+ * only attach to pipe B. We need to use the display passed to
+ * determine the pipe number to use. (Plba is same as Alm).
+ */
+
+ /*
+ * We can come here with following cases:
+ * 1. magic->vga CRT, DVI type displays
+ * 2. native->vga int-lvds, and up-scaling lvds displays
+ * 3. pipe->vga TV and other unscaled-lvds displays
+ */
+ vga_control = EMGD_READ32(context->device_context.virt_mmadr + 0x71400);
+ vga_control &= 0x18e3ff00;
+ vga_control |= 0x8e;
+
+ timing = pipe->timing;
+ if(!timing->extn_ptr) {
+ EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb");
+ return;
+ }
+
+ if (port) {
+ /* Find UPSCALING attr value*/
+ pi_pd_find_attr_and_value(port,
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ /* this PI func will not modify value of upscale if attr does not exist */
+ }
+
+ /* magic->vga or native->vga cases */
+ if ((timing->width == 720 && timing->height == 400) || upscale) {
+ centering = 0;
+ }
+
+ /* Enable border */
+ if((timing->width >= 800) && !upscale) {
+ EMGD_DEBUG("Enable VGA Border");
+ vga_control |= (1L<<26);
+ }
+
+ if(timing->width == 640) {
+ EMGD_DEBUG("Enable Nine Dot Disable");
+ vga_control |= (1L<<18);
+ }
+
+ if(centering) {
+ EMGD_DEBUG("Enable VGA Center Centering");
+ vga_control |= 1L<<24;
+
+ if(timing->height >= 960) {
+ if(timing->width >= 1280) {
+ EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+ vga_control |= (1L<<30) | (1L<<18);
+ }
+ }
+ } else {
+ if (port) {
+ if(port->port_type == IGD_PORT_LVDS) {
+ EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+ vga_control |= (1L<<25 | (1L<<18));
+ } else if (upscale) {
+ EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+ vga_control |= 1L<<25;
+ }
+ }
+ }
+
+ if(pipe->pipe_num) {
+ vga_control |= 1L<<29;
+ }
+
+ kms_program_pipe_vga(emgd_crtc, (igd_timing_info_t *)timing->extn_ptr);
+ EMGD_WRITE32(vga_control, context->device_context.virt_mmadr + 0x71400);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+/**
+ * kms_set_pipe_pwr_plb
+ *
+ * Turns the pipe ON or OFF depending on the input
+ *
+ * @param emgd_crtc (IN) specifies the pipe to change
+ * @param enable (IN) TRUE to enable pipe, FALSE to disable
+ *
+ * @return
+ */
+static void kms_set_pipe_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+ unsigned long pipe_conf;
+ struct drm_device *dev;
+ igd_display_pipe_t *pipe;
+ igd_context_t *context;
+
+
+ EMGD_TRACE_ENTER;
+
+
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ pipe = emgd_crtc->igd_pipe;
+ pipe_conf = device_data_plb->pipe_preserve &
+ EMGD_READ32(context->device_context.virt_mmadr + pipe->pipe_reg);
+
+
+ /* Do nothing if current power state is same as what we want to set */
+ /* The PIPE_ENABLE bit is at bit-position 31 */
+ if ( (enable << 31) == (pipe_conf & PIPE_ENABLE) ){
+
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+
+ if (!enable) {
+ /* Disable pipe */
+ EMGD_WRITE32(pipe_conf & ~PIPE_ENABLE,
+ context->device_context.virt_mmadr + pipe->pipe_reg);
+
+ EMGD_DEBUG("Set Pipe Power: OFF");
+
+ } else {
+ /* Enable pipe */
+ EMGD_WRITE32(pipe_conf | PIPE_ENABLE,
+ context->device_context.virt_mmadr + pipe->pipe_reg);
+
+ EMGD_DEBUG("Set Pipe Power: ON");
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param emgd_crtc
+ * @param status
+ *
+ * @return void
+ */
+static void kms_program_pipe_plb(emgd_crtc_t *emgd_crtc)
+{
+ unsigned long timing_reg;
+ unsigned long pipe_conf;
+ unsigned long hactive, vactive;
+ igd_timing_info_t *pTimings;
+ unsigned long temp;
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_display_port_t *port = NULL;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+ pipe_conf = device_data_plb->pipe_preserve &
+ EMGD_READ32(context->device_context.virt_mmadr + pipe->pipe_reg);
+
+ /* Reset the plane of this pipe back to NULL, it will be set on the
+ * call to program_plane, which is ok, since program_pipe occurs
+ * before program_plane */
+ pipe->plane = NULL;
+
+ pTimings = pipe->timing;
+
+ /*
+ * If the mode is VGA and the PD says it handles all VGA modes without
+ * reprogramming then just set the mode and leave centering off.
+ */
+ if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ /* Pipe timings and clocks are not used but it must be on anyway */
+ EMGD_WRITE32(pipe_conf | 0x80000000,
+ context->device_context.virt_mmadr + pipe->pipe_reg);
+
+ kms_program_pipe_vga_plb(emgd_crtc);
+ return;
+ }
+ }
+
+ /* Program dot clock divisors. */
+ kms_program_clock_plb(emgd_crtc, pipe->clock_reg, pTimings->dclk);
+
+ /* Program timing registers for the pipe */
+ timing_reg = pipe->timing_reg;
+ if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ hactive = (unsigned long)pTimings->width*2 - 1;
+ } else {
+ hactive = (unsigned long)pTimings->width - 1;
+ }
+
+ if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
+ if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ vactive = (unsigned long)pTimings->height - 1;
+ } else {
+ vactive = (unsigned long)pTimings->height*2 - 1;
+ }
+ } else {
+ if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ vactive = (unsigned long)pTimings->height/2 - 1;
+ } else {
+ vactive = (unsigned long)pTimings->height - 1;
+ }
+ }
+
+ /*
+ * DPLL should be on at this point which is required for touching
+ * the palette.
+ */
+ /* reset the palette */
+ for (i = 0; i < 256; i++) {
+ EMGD_WRITE32(((i<<16) | (i<<8) | i),
+ context->device_context.virt_mmadr + pipe->palette_reg + i*4);
+ }
+
+ /* apply color correction */
+ for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+ if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) {
+
+ set_color_correct_plb(emgd_crtc);
+ }
+ }
+
+
+ /*
+ * NOTE: For size reasons the timng table contains unsigned short
+ * values. Don't shift them past 16. Use a temp instead.
+ * All register offsets and bit shift are verified for Napa
+ */
+ temp = ((unsigned long)pTimings->htotal << 16) | hactive;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg);
+
+ temp = ((unsigned long)pTimings->hblank_end << 16) |
+ (unsigned long)pTimings->hblank_start;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x04);
+
+ temp = ((unsigned long)pTimings->hsync_end << 16) |
+ (unsigned long)pTimings->hsync_start;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x08);
+
+ temp = ((unsigned long)pTimings->vtotal << 16) | vactive;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x0C);
+
+ temp = ((unsigned long)pTimings->vblank_end << 16) |
+ (unsigned long)pTimings->vblank_start;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x10);
+
+ temp = ((unsigned long)pTimings->vsync_end << 16) |
+ (unsigned long)pTimings->vsync_start;
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x14);
+
+ /*
+ * If there is a linked mode it is either the VGA or a scaled
+ * mode. If it is scaled then we need to use it as the source size.
+ */
+ if(pTimings->extn_ptr) {
+ igd_timing_info_t *scaled_timings =
+ (igd_timing_info_t *)pTimings->extn_ptr;
+ if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+ (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+ temp = (hactive << 16) | vactive;
+ } else {
+ temp = (unsigned long)scaled_timings->width - 1;
+ temp = (temp << 16) |
+ (unsigned long)(scaled_timings->height - 1);
+ }
+ } else {
+ temp = (hactive << 16) | vactive;
+ }
+ EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x1C);
+
+ /* Set other registers */
+
+ /*
+ * FIXME: max_dclk needs to be determined from core clock
+ * at init time. 915 etc has several skus with different
+ * clocks for the same device ID.
+ *
+ */
+
+ /* These values are derived from the Poulsbo B-Spec as
+ * the suggested values */
+ EMGD_WRITE32(device_data_plb->fw_blc1,
+ context->device_context.virt_mmadr + FW_BLC1);
+ EMGD_WRITE32(device_data_plb->fw_blc2,
+ context->device_context.virt_mmadr + FW_BLC2);
+ EMGD_WRITE32(device_data_plb->fw_blc3,
+ context->device_context.virt_mmadr + FW_BLC3);
+ EMGD_WRITE32(device_data_plb->fw_self,
+ context->device_context.virt_mmadr + FW_BLC_SELF);
+ EMGD_WRITE32(device_data_plb->dsp_arb,
+ context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+
+ /* The SGX 2D engine can saturate the memory bus and starve
+ * the display engine causing visible screen tearing.
+ * This reduces the priority of the SGX vs. display engine
+ */
+ temp = EMGD_READ32(context->device_context.virt_mmadr + G_DEBUG);
+ EMGD_WRITE32((temp | (1 << 11)),
+ context->device_context.virt_mmadr + G_DEBUG);
+
+ EMGD_WRITE32(pipe_conf,
+ context->device_context.virt_mmadr + pipe->pipe_reg);
+
+ /*
+ * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+ * mode can be accessed through 0xa0000 in a 16bit world.
+ */
+ WRITE_AR(context->device_context.virt_mmadr, 0x10, 0xb);
+ WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x06, 0x5);
+ WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x10, 0x1);
+
+ if(pTimings->extn_ptr) {
+ /* This means either internal scaling (LVDS) or centered VGA */
+ pTimings = pTimings->extn_ptr;
+ if(pTimings->extn_ptr) {
+ /* This is both the scaled and centered VGA */
+ pTimings = pTimings->extn_ptr;
+ }
+ if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ kms_program_pipe_vga_plb(emgd_crtc);
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+/*!
+ * kms_set_plane_pwr_plb
+ *
+ * Enables or disables the plane associated with the given CRTC
+ *
+ * @param enable [IN] turns the plane on or off
+ *
+ * @return void
+ */
+static void kms_set_plane_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+ unsigned long plane_control;
+ unsigned long plane_reg;
+ struct drm_device *dev = NULL;
+ igd_display_plane_t *plane = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Plane: %s", enable?"ENABLE":"DISABLE");
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ plane = PLANE(pipe->owner);
+
+ if (!plane) {
+ EMGD_ERROR_EXIT("Trying to set power to a plane that is not tied "
+ " to a crtc.");
+ return;
+ }
+
+ /* In case a plane update is already in progress */
+ wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+ /* Get the current value of the plane control register */
+ plane_reg = plane->plane_reg;
+ plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+
+ if(plane->plane_reg == DSPACNTR) {
+ plane_control &= device_data_plb->plane_a_preserve;
+ } else { /* if it's plane b or plane c */
+ plane_control &= device_data_plb->plane_b_c_preserve;
+ }
+
+
+ if((enable == FALSE) ||
+ (context->device_context.power_state != IGD_POWERSTATE_D0)) {
+
+ /*
+ * Note: The vga programming code does not have an "off". So
+ * when programming the plane to off we make sure VGA is off
+ * as well.
+ */
+ disable_vga_plb(context->device_context.virt_mmadr);
+
+ /*
+ * To turn off plane A or B, the program have to trigger the plane A
+ * or B start register. Or else, it will not work.
+ */
+ plane_control &= 0xEFFFFFFF;
+
+ EMGD_WRITE32(plane_control,
+ context->device_context.virt_mmadr + plane_reg);
+
+ EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+ plane_reg + DSP_START_OFFSET),
+ context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+ } else {
+ /* Enable Pipe */
+ plane_control |= 0x80000000;
+
+ EMGD_WRITE32(plane_control,
+ context->device_context.virt_mmadr + plane_reg);
+ }
+
+
+ wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+ EMGD_TRACE_EXIT;
+
+ return;
+}
+
+
+
+/*!
+ * Program Display Plane Values.
+ *
+ * @param emgd_crtc Pointer to hardware device instance data
+ *
+ * @return void
+ */
+static void kms_program_plane_plb(emgd_crtc_t *emgd_crtc,
+ unsigned long status)
+{
+ unsigned long stereo;
+ unsigned long stride;
+ unsigned long size;
+ unsigned long plane_control;
+ unsigned long plane_reg;
+ unsigned long start_addr_reg;
+ igd_timing_info_t *timing = NULL;
+ struct drm_device *dev = NULL;
+ igd_display_plane_t *plane = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ igd_framebuffer_info_t *fb_info = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ plane = PLANE(pipe->owner);
+ fb_info = plane->fb_info;
+ plane_reg = plane->plane_reg;
+ start_addr_reg = DSPAADDR;
+
+ EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+ wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+ plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+ if(plane->plane_reg == DSPACNTR) {
+ plane_control &= device_data_plb->plane_a_preserve;
+ }
+ else { /* if it's plane b or plane c */
+ plane_control &= device_data_plb->plane_b_c_preserve;
+ start_addr_reg = 0x71184;
+ }
+
+ if((status == FALSE) ||
+ (context->device_context.power_state != IGD_POWERSTATE_D0)) {
+
+ /*
+ * Note: The vga programming code does not have an "off". So
+ * when programming the plane to off we make sure VGA is off
+ * as well.
+ */
+ disable_vga_plb(context->device_context.virt_mmadr);
+
+ /*
+ * To turn off plane A or B, the program have to triger the plane A or B
+ * start register. Or else, it will not work.
+ */
+ EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+ EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr + start_addr_reg),
+ context->device_context.virt_mmadr + start_addr_reg);
+
+ wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+ return;
+ }
+ /*
+ * Note: The very first pass through this function will be with
+ * status false and timings == NULL. Don't use the timings before
+ * the check above.
+ */
+ timing = pipe->timing;
+ /* There is a special case code for legacy VGA modes */
+ while (timing->extn_ptr) {
+ timing = (igd_timing_info_t *)timing->extn_ptr;
+ }
+ if(MODE_IS_VGA(timing)) {
+ kms_program_plane_vga(context->device_context.virt_mmadr, timing);
+ return;
+ }
+
+ disable_vga_plb(context->device_context.virt_mmadr);
+
+ size = (((unsigned long)timing->height - 1)<<16) |
+ (unsigned long)(timing->width - 1);
+
+ /* enable plane, select pipe, enable gamma correction logic */
+ plane_control |= 0x80000000 | (pipe->pipe_num<<24);
+ pipe->plane = plane;
+#ifndef CONFIG_MICRO
+ plane_control |= (1<<30);
+#endif
+
+ /* Here the settings:
+ * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+ * If line dbling only, set 21,20 to 11b
+ * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply
+ * If no doubling, set 21,20 to 00b (no Horz Multiply)
+ * For pixel doubling
+ * --> both progressive/interlaced modes
+ * For Line doubling
+ * --> progressive modes only
+ */
+
+ if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+ /* Line doubling in progressive mode requires special bits */
+ if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* BIT 20 for line & pixel doubling*/
+ plane_control |= BIT20;
+ /* check later, if no pixel doubling, set bit 21 too*/
+ }
+ }
+ if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ /* Horz pixel multiply must be set for double */
+ plane_control |= BIT11;
+ /* TODO -> Plba can more than double,
+ It can 3X, 4X etc. These arent exposed now */
+ }
+ else if(plane_control & BIT20){
+ /* For line ONLY doubling, set bit 21 also '1' */
+ plane_control |= BIT21;
+ }
+
+ kms_mode_get_stride_stereo_plb(pipe, plane, &stride, &stereo, 0);
+
+ /* set color depth */
+ switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+ case PF_DEPTH_8:
+ plane_control |= BIT27 | BIT30;
+ break;
+ case PF_DEPTH_16:
+ plane_control |= BIT28 | BIT26;
+ break;
+ default:
+ case PF_DEPTH_32:
+ plane_control |= BIT28 | BIT27;
+ break;
+ }
+
+ if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+ plane_control |= (BIT30);
+ }
+
+ EMGD_DEBUG(" Plane Control = 0x%lx", plane_control);
+ EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset);
+ EMGD_DEBUG(" Plane Pitch = 0x%lx", stride);
+ EMGD_DEBUG(" Plane Size = 0x%lx", size);
+
+ EMGD_WRITE32(stride, context->device_context.virt_mmadr + plane_reg + DSP_STRIDE_OFFSET);
+ /*
+ * In reality this only exists for plane B. It doesn't seem to hurt
+ * plane A so just do it anyway and save us another case.
+ */
+ EMGD_WRITE32(size, context->device_context.virt_mmadr + plane_reg + DSP_SIZE_OFFSET);
+
+ /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);
+ - This register is Reserved ON plba */
+ EMGD_WRITE32(fb_info->visible_offset,
+ context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+
+ /* It seems we need push or trigger plane A/B to start to work
+ * on Poulsbo, especially for sDVO port. Let's write plane control
+ * register and start address register at last.
+ */
+ EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+ EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr + start_addr_reg),
+ context->device_context.virt_mmadr + start_addr_reg);
+
+ wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
new file mode 100644
index 0000000..9d69f8d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
@@ -0,0 +1,1391 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_mode_plb.c
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Napa Core implementations for the mode dispatch functions.
+ * NOTE: This file is designed to produce tiny code and is used in the
+ * vbios port. Make sure that all MMIO reads and writes do all mmio
+ * calculation within the OS_READ and OS_WRITE macros so that this code
+ * will be correctly removed.
+ * This is OK -> EMGD_READ32( MMIO(display) + foo_offset )
+ * This is NOT OK -> mmio = MMIO(display)
+ * EMGD_READ32(mmio + foo_offset)
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd.h>
+#include <igd_pwr.h>
+
+#include <context.h>
+#include <rb.h>
+#include <mode.h>
+#include <utils.h>
+#include <dsp.h>
+#include <vga.h>
+#include <intelpci.h>
+#include <mode_access.h>
+#include <pi.h>
+#include <dispatch.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+#include <plb/mi.h>
+#include "drm_emgd_private.h"
+
+#include "../cmn/match.h"
+#include "../cmn/mode_dispatch.h"
+#include "mode_plb.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+#ifdef CONFIG_PLB
+
+/*
+ * Exports from the other components of this module.
+ */
+
+extern int program_clock_plb(igd_display_context_t *display,
+ igd_clock_t *clock, unsigned long dclk);
+extern mode_full_dispatch_t mode_full_dispatch_plb;
+
+static unsigned long gpio_plb[] = {
+ 0x5010,
+ 0x5014,
+ 0x5018,
+ 0x501c,
+ 0x5020,
+ 0x5024,
+ 0x5028
+};
+
+mode_data_plb_t device_data_plb[1] = {
+ {
+ 0x000b0000, /* plane a preservation */
+ 0x00000000, /* plane b/c preservation */
+ 0x01000000, /* pipe preservation */
+ 0, /* port preservation */
+ 0x490A010A, /* watermark/burst length 1 */
+ 0x14100D0A, /* watermark/burst length 2*/
+ 0x00007770, /* watermark/burst length 3 */
+ 0x0B0C9812, /* watermark/burst length self */
+ 0, /* mem_mode */
+ 0x00001D9C, /* dsp arb */
+ }
+};
+
+/*!
+ *
+ * @param mmio
+ *
+ * @return void
+ */
+void disable_vga_plb (unsigned char *mmio)
+{
+ unsigned long temp;
+ unsigned char sr01;
+
+ EMGD_TRACE_ENTER;
+
+ /* Disable VGA plane if it is enabled. */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL);
+ if ((temp & BIT31) == 0) {
+ /* Read SR01 */
+ READ_VGA(mmio, SR_PORT, 0x01, sr01);
+
+ /* Turn on SR01 bit 5 */
+ WRITE_VGA(mmio, SR_PORT, 0x01, sr01|BIT(5));
+ /* Wait for 30us */
+ OS_SLEEP(30);
+
+ temp |= BIT31; /* set bit 31 to disable */
+ temp &= ~BIT30; /* clear bit 30 to get VGA display in normal size */
+ EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL);
+ }
+ /*
+ * When turing off the VGA plane the palette sometimes gets stuck.
+ * if we do a couple reads to the palette it will unstuck.
+ */
+ if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEA_CONF )) {
+ EMGD_DEBUG("VGA Palette workaround");
+ EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A);
+ EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A);
+ }
+ if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEB_CONF )) {
+ EMGD_DEBUG("VGA Palette workaround");
+ EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B);
+ EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_set_palette_entry_plb(
+ igd_display_h display_handle,
+ unsigned long palette_entry,
+ unsigned long palette_color)
+{
+ /* Too Slow For Tracing */
+
+ /* Return if Pipe is not on */
+ if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) +
+ PIPE(display_handle)->pipe_reg))) {
+ return -IGD_INVAL;
+ }
+ /*
+ EMGD_DEBUG("%x : %ld : %lx", display_handle,
+ palette_entry, palette_color);
+ */
+ EMGD_WRITE32(palette_color, MMIO(display_handle) +
+ PIPE(display_handle)->palette_reg + palette_entry * 4);
+
+ return 0;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_get_palette_entry_plb(
+ igd_display_h display_handle,
+ unsigned long palette_entry,
+ unsigned long *palette_color)
+{
+ /* Too Slow For Tracing */
+
+ /* Return if Pipe is not on */
+ if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) +
+ PIPE(display_handle)->pipe_reg))) {
+ return -IGD_INVAL;
+ }
+
+ *palette_color = 0xffffff & EMGD_READ32(MMIO(display_handle) +
+ PIPE(display_handle)->palette_reg + palette_entry * 4);
+ return 0;
+}
+
+/*!
+ *
+ * @param mmio
+ * @param pipe_reg
+ * @param time_interval
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int wait_for_vblank_timeout_plb(
+ unsigned char *mmio,
+ unsigned long pipe_reg,
+ unsigned long time_interval)
+{
+ int ret;
+ unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET;
+ unsigned long tmp;
+ os_alarm_t timeout;
+ unsigned long request_for;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: MMIO = %p, pipe_reg = %lx, time_interval = %lx",
+ mmio, pipe_reg, time_interval);
+
+ /* If pipe is off then just return */
+ if(!((1L<<31) & EMGD_READ32(EMGD_MMIO(mmio) + pipe_reg))) {
+ EMGD_DEBUG("Pipe disabled/Off");
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ /*
+ * When VGA plane is on the normal wait for vblank won't work
+ * so just skip it.
+ */
+ if(!(EMGD_READ32(EMGD_MMIO(mmio) + 0x71400) & 0x80000000)) {
+ EMGD_DEBUG("VGA Plane On");
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ /* 1. Request the interrupt handler to record the next VBlank: */
+ request_for = VBINT_REQUEST(VBINT_WAIT,
+ (pipe_status_reg == PIPEA_STAT) ? VBINT_PORT2 : VBINT_PORT4);
+ mode_context->dispatch->full->request_vblanks(request_for, mmio);
+
+ /* 2. Wait & poll for the next VBlank: */
+ timeout = OS_SET_ALARM(time_interval);
+ do {
+ OS_SCHEDULE();
+ tmp = mode_context->dispatch->full->vblank_occured(request_for);
+ } while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout)));
+ if (tmp == 0) {
+ EMGD_ERROR_EXIT("Timeout waiting for VBLANK");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+ /* 3. End our request for the next VBlank: */
+ mode_context->dispatch->full->end_request(request_for, mmio);
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* wait_for_vblank_timeout_plb */
+
+/*!
+ *
+ * @param mmio
+ * @param pipe_reg
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int wait_for_vblank_plb(unsigned char *mmio,
+ unsigned long pipe_reg)
+{
+ return wait_for_vblank_timeout_plb(mmio, pipe_reg, 100);
+} /* wait_for_vblank_plb */
+
+
+/*!
+ * This procedure waits for the next vertical blanking (vertical retrace)
+ * period. If the display is already in a vertical blanking period, this
+ * procedure exits.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param display_handle
+ *
+ * @return FALSE if timed out
+ */
+static int igd_wait_vblank_plb(igd_display_h display_handle)
+{
+
+ return wait_for_vblank_plb(MMIO(display_handle),
+ PIPE(display_handle)->pipe_reg);
+
+} /* wait_vblank */
+
+
+/*!
+ * Get the stride and stereo values based on the display. This is also used
+ * by the MI instructions.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param stride
+ * @param stereo
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+static int mode_get_stride_stereo_plb(igd_display_context_t *display,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags)
+{
+ unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
+ igd_timing_info_t *timing = PIPE(display)->timing;
+ unsigned long base_offset;
+
+ base_offset = PLANE(display)->fb_info->visible_offset;
+
+ *stride = pitch;
+ *stereo = 0;
+
+ /* For field replication, valid for interlaced modes only
+ * set stereo = fb_base,
+ * stride = pitch
+ */
+ if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+ if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* Interlaced + Line double flags means field replication.
+ * same lines are sent for both fields. Program the
+ * second eye to be same as the first.
+ */
+ *stereo = base_offset;
+ } else {
+ /* Regular interlaced. Second eye starts on line 2.
+ * Skip every other line.
+ */
+ *stereo = base_offset + pitch;
+ *stride = pitch * 2;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ *
+ * @param display Pointer to hardware device instance data
+ *
+ * @return void
+ */
+static void program_pipe_vga_plb(
+ igd_display_context_t *display)
+{
+ igd_timing_info_t *timing;
+ unsigned long vga_control;
+ unsigned long upscale = 0;
+ int centering = 1;
+
+ EMGD_TRACE_ENTER;
+
+#ifdef CONFIG_MICRO
+ /*
+ * We cannot set a VGA mode unless the display planes are turned off.
+ * This becomes evident during a Windows BSOD. Since neither Windows
+ * nor IEGD got a chance to turn off these registers, and the VGA mode was
+ * set by the VBIOS, the screen gets corrupted. In order to fix this
+ * problem, we will turn the cursor and display planes here.
+ *
+ * Note: Removing previous partial-fix in favor of this complete one.
+ */
+ /* Cursor A */
+ WRITE_MMIO_REG(display, 0x70080, 0);
+ WRITE_MMIO_REG(display, 0x70084, 0);
+ /* Cursor B */
+ WRITE_MMIO_REG(display, 0x700C0, 0);
+ WRITE_MMIO_REG(display, 0x700C4, 0);
+ /* Display A */
+ WRITE_MMIO_REG(display, 0x70180, 0);
+ WRITE_MMIO_REG(display, 0x70184, 0);
+ /* Display B */
+ WRITE_MMIO_REG(display, 0x71180, 0);
+ WRITE_MMIO_REG(display, 0x71184, 0);
+ /* Display C */
+ WRITE_MMIO_REG(display, 0x72180, 0);
+ WRITE_MMIO_REG(display, 0x72184, 0);
+#endif
+
+ /*
+ * VGA Plane can attach to only one pipe at a time. LVDS can
+ * only attach to pipe B. We need to use the display passed to
+ * determine the pipe number to use. (Plba is same as Alm).
+ */
+
+ /*
+ * We can come here with following cases:
+ * 1. magic->vga CRT, DVI type displays
+ * 2. native->vga int-lvds, and up-scaling lvds displays
+ * 3. pipe->vga TV and other unscaled-lvds displays
+ */
+ vga_control = READ_MMIO_REG(display, 0x71400);
+ vga_control &= 0x18e3ff00;
+ vga_control |= 0x8e;
+
+ timing = PIPE(display)->timing;
+ if(!timing->extn_ptr) {
+ EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb");
+ return;
+ }
+
+ /* Find UPSCALING attr value*/
+ pi_pd_find_attr_and_value(PORT_OWNER(display),
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ /* this PI func will not modify value of upscale if attr does not exist */
+
+ /* magic->vga or native->vga cases */
+ if ((timing->width == 720 && timing->height == 400) || upscale) {
+ centering = 0;
+ }
+
+ /* Enable border */
+ if((timing->width >= 800) && !upscale) {
+ EMGD_DEBUG("Enable VGA Border");
+ vga_control |= (1L<<26);
+ }
+
+ if(timing->width == 640) {
+ EMGD_DEBUG("Enable Nine Dot Disable");
+ vga_control |= (1L<<18);
+ }
+
+ if(centering) {
+ EMGD_DEBUG("Enable VGA Center Centering");
+ vga_control |= 1L<<24;
+
+ if(timing->height >= 960) {
+ if(timing->width >= 1280) {
+ EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+ vga_control |= (1L<<30) | (1L<<18);
+ }
+ }
+ } else {
+ if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
+ EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+ vga_control |= (1L<<25 | (1L<<18));
+ } else if (upscale) {
+ EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+ vga_control |= 1L<<25;
+ }
+ }
+
+ if(PIPE(display)->pipe_num) {
+ vga_control |= 1L<<29;
+ }
+
+ program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
+ WRITE_MMIO_REG(display, 0x71400, vga_control);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ * Program Display Plane Values.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param status
+ *
+ * @return void
+ */
+static void program_plane_plb(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long stereo;
+ unsigned long stride;
+ unsigned long size;
+ unsigned long plane_control;
+ igd_timing_info_t *timing;
+ igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
+ unsigned long plane_reg = PLANE(display)->plane_reg;
+ unsigned long start_addr_reg = DSPAADDR;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ igd_wait_vblank_plb((igd_display_h)display);
+
+ plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+ if(PLANE(display)->plane_reg == DSPACNTR) {
+ plane_control &= device_data_plb->plane_a_preserve;
+ }
+ else { /* if it's plane b or plane c */
+ plane_control &= device_data_plb->plane_b_c_preserve;
+ start_addr_reg = 0x71184;
+ }
+
+ if((status == FALSE) ||
+ (GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {
+
+ /*
+ * Note: The vga programming code does not have an "off". So
+ * when programming the plane to off we make sure VGA is off
+ * as well.
+ */
+ disable_vga_plb(MMIO(display));
+
+ /*
+ * To turn off plane A or B, the program have to triger the plane A or B
+ * start register. Or else, it will not work.
+ */
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
+ MMIO(display) + start_addr_reg);
+
+ igd_wait_vblank_plb((igd_display_h)display);
+ return;
+ }
+ /*
+ * Note: The very first pass through this function will be with
+ * status false and timings == NULL. Don't use the timings before
+ * the check above.
+ */
+ timing = PIPE(display)->timing;
+ /* There is a special case code for legacy VGA modes */
+ while (timing->extn_ptr) {
+ timing = (igd_timing_info_t *)timing->extn_ptr;
+ }
+ if(MODE_IS_VGA(timing)) {
+ program_plane_vga(display, timing);
+ return;
+ }
+
+ disable_vga_plb(MMIO(display));
+
+ size = (((unsigned long)timing->height - 1)<<16) |
+ (unsigned long)(timing->width - 1);
+
+ /* enable plane, select pipe, enable gamma correction logic */
+ plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
+ PIPE(display)->plane = PLANE(display);
+#ifndef CONFIG_MICRO
+ plane_control |= (1<<30);
+#endif
+
+ /* Here the settings:
+ * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+ * If line dbling only, set 21,20 to 11b
+ * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply
+ * If no doubling, set 21,20 to 00b (no Horz Multiply)
+ * For pixel doubling
+ * --> both progressive/interlaced modes
+ * For Line doubling
+ * --> progressive modes only
+ */
+
+ if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+ /* Line doubling in progressive mode requires special bits */
+ if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* BIT 20 for line & pixel doubling*/
+ plane_control |= BIT20;
+ /* check later, if no pixel doubling, set bit 21 too*/
+ }
+ }
+ if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ /* Horz pixel multiply must be set for double */
+ plane_control |= BIT11;
+ /* TODO -> Plba can more than double,
+ It can 3X, 4X etc. These arent exposed now */
+ }
+ else if(plane_control & BIT20){
+ /* For line ONLY doubling, set bit 21 also '1' */
+ plane_control |= BIT21;
+ }
+
+ mode_get_stride_stereo_plb(display, &stride, &stereo, 0);
+
+ /* set color depth */
+ switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+ case PF_DEPTH_8:
+ plane_control |= BIT27 | BIT30;
+ break;
+ case PF_DEPTH_16:
+ plane_control |= BIT28 | BIT26;
+ break;
+ default:
+ case PF_DEPTH_32:
+ plane_control |= BIT28 | BIT27;
+ break;
+ }
+
+ if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+ plane_control |= (BIT30);
+ }
+
+ EMGD_DEBUG(" Plane Control = 0x%lx", plane_control);
+ EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset);
+ EMGD_DEBUG(" Plane Pitch = 0x%lx", stride);
+ EMGD_DEBUG(" Plane Size = 0x%lx", size);
+
+ EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
+ /*
+ * In reality this only exists for plane B. It doesn't seem to hurt
+ * plane A so just do it anyway and save us another case.
+ */
+ EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);
+
+ /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);
+ - This register is Reserved ON plba */
+ EMGD_WRITE32(fb_info->visible_offset,
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+ /* It seems we need push or trigger plane A/B to start to work
+ * on Poulsbo, especially for sDVO port. Let's write plane control
+ * register and start address register at last.
+ */
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg),
+ MMIO(display) + start_addr_reg);
+
+ igd_wait_vblank_plb((igd_display_h)display);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param display
+ * @param status
+ *
+ * @return void
+ */
+static void program_pipe_plb(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long timing_reg;
+ unsigned long pipe_conf;
+ unsigned long hactive, vactive;
+ igd_timing_info_t *pTimings;
+ unsigned long temp;
+#ifndef CONFIG_MICRO
+ igd_display_port_t *port;
+ int i;
+#endif
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ pipe_conf = device_data_plb->pipe_preserve &
+ EMGD_READ32(MMIO(display) + PIPE(display)->pipe_reg);
+
+ /* Reset the plane of this pipe back to NULL, it will be set on the
+ * call to program_plane, which is ok, since program_pipe occurs
+ * before program_plane */
+ PIPE(display)->plane = NULL;
+
+ if((status == FALSE) ||
+ (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
+ /* Disable pipe */
+ EMGD_WRITE32(pipe_conf & (~0x80000000),
+ MMIO(display) + PIPE(display)->pipe_reg);
+
+ return;
+ }
+
+ pTimings = PIPE(display)->timing;
+
+ /*
+ * If the mode is VGA and the PD says it handles all VGA modes without
+ * reprogramming then just set the mode and leave centering off.
+ */
+ if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ /* Pipe timings and clocks are not used but it must be on anyway */
+ EMGD_WRITE32(pipe_conf | 0x80000000,
+ MMIO(display) + PIPE(display)->pipe_reg);
+ program_pipe_vga_plb(display);
+ return;
+ } else {
+#ifdef CONFIG_MICRO
+ set_256_palette(MMIO(display));
+#endif
+ }
+ }
+
+ /* Program dot clock divisors. */
+ program_clock_plb(display, PIPE(display)->clock_reg, pTimings->dclk);
+
+ /* Program timing registers for the pipe */
+ timing_reg = PIPE(display)->timing_reg;
+ if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ hactive = (unsigned long)pTimings->width*2 - 1;
+ } else {
+ hactive = (unsigned long)pTimings->width - 1;
+ }
+
+ if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
+ if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ vactive = (unsigned long)pTimings->height - 1;
+ } else {
+ vactive = (unsigned long)pTimings->height*2 - 1;
+ }
+ } else {
+ if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ vactive = (unsigned long)pTimings->height/2 - 1;
+ } else {
+ vactive = (unsigned long)pTimings->height - 1;
+ }
+ }
+
+ /*
+ * DPLL should be on at this point which is required for touching
+ * the palette.
+ */
+#ifndef CONFIG_MICRO
+ /* reset the palette */
+ for (i = 0; i < 256; i++) {
+ EMGD_WRITE32(((i<<16) | (i<<8) | i),
+ MMIO(display) + PIPE(display)->palette_reg + i*4);
+ }
+
+ /* apply color correction */
+ port = PORT_OWNER(display);
+ for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+ if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) {
+
+ mode_context->dispatch->full->set_color_correct(display);
+ }
+ }
+#endif
+
+ /*
+ * NOTE: For size reasons the timng table contains unsigned short
+ * values. Don't shift them past 16. Use a temp instead.
+ * All register offsets and bit shift are verified for Napa
+ */
+ temp = ((unsigned long)pTimings->htotal << 16) | hactive;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg);
+
+ temp = ((unsigned long)pTimings->hblank_end << 16) |
+ (unsigned long)pTimings->hblank_start;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x04);
+
+ temp = ((unsigned long)pTimings->hsync_end << 16) |
+ (unsigned long)pTimings->hsync_start;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x08);
+
+ temp = ((unsigned long)pTimings->vtotal << 16) | vactive;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x0C);
+
+ temp = ((unsigned long)pTimings->vblank_end << 16) |
+ (unsigned long)pTimings->vblank_start;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x10);
+
+ temp = ((unsigned long)pTimings->vsync_end << 16) |
+ (unsigned long)pTimings->vsync_start;
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x14);
+
+ /*
+ * If there is a linked mode it is either the VGA or a scaled
+ * mode. If it is scaled then we need to use it as the source size.
+ */
+ if(pTimings->extn_ptr) {
+ igd_timing_info_t *scaled_timings =
+ (igd_timing_info_t *)pTimings->extn_ptr;
+ if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+ (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+ temp = (hactive << 16) | vactive;
+ } else {
+ temp = (unsigned long)scaled_timings->width - 1;
+ temp = (temp << 16) |
+ (unsigned long)(scaled_timings->height - 1);
+ }
+ } else {
+ temp = (hactive << 16) | vactive;
+ }
+ EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x1C);
+
+ /* Set other registers */
+
+ /*
+ * FIXME: max_dclk needs to be determined from core clock
+ * at init time. 915 etc has several skus with different
+ * clocks for the same device ID.
+ *
+ */
+
+ /* These values are derived from the Poulsbo B-Spec as
+ * the suggested values */
+ WRITE_MMIO_REG (display, FW_BLC1, device_data_plb->fw_blc1);
+ WRITE_MMIO_REG (display, FW_BLC2, device_data_plb->fw_blc2);
+ WRITE_MMIO_REG (display, FW_BLC3, device_data_plb->fw_blc3);
+ WRITE_MMIO_REG (display, FW_BLC_SELF, device_data_plb->fw_self);
+ WRITE_MMIO_REG (display, PIPEA_DISP_ARB_CTRL, device_data_plb->dsp_arb);
+
+ /* The SGX 2D engine can saturate the memory bus and starve
+ * the display engine causing visible screen tearing.
+ * This reduces the priority of the SGX vs. display engine
+ */
+ temp = READ_MMIO_REG (display, G_DEBUG);
+ WRITE_MMIO_REG (display, G_DEBUG, (temp | (1 << 11)));
+
+ pipe_conf |= PIPE_ENABLE;
+ WRITE_MMIO_REG(display, PIPE(display)->pipe_reg, pipe_conf);
+
+ /*
+ * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+ * mode can be accessed through 0xa0000 in a 16bit world.
+ */
+ WRITE_AR(MMIO(display), 0x10, 0xb);
+ WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
+ WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);
+
+ if(pTimings->extn_ptr) {
+ /* This means either internal scaling (LVDS) or centered VGA */
+ pTimings = pTimings->extn_ptr;
+ if(pTimings->extn_ptr) {
+ /* This is both the scaled and centered VGA */
+ pTimings = pTimings->extn_ptr;
+ }
+ if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ program_pipe_vga_plb(display);
+ } else {
+#ifdef CONFIG_MICRO
+ set_256_palette(MMIO(display));
+#endif
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void reset_plane_pipe_ports_plb(igd_context_t *context)
+{
+ igd_plane_t *plane;
+ igd_display_pipe_t *pipe;
+ igd_display_port_t *port,*tv_port=NULL;
+ unsigned long temp;
+ unsigned long i;
+ unsigned char *mmio;
+ inter_module_dispatch_t *md;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Disable all plane, pipe and port registers because the
+ * bios may have been using a different set. Only unset the
+ * enable bit.
+ */
+ mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ md = &context->mod_dispatch;
+
+ disable_vga_plb(EMGD_MMIO(mmio));
+
+ /* Turn off ports */
+ port = NULL;
+ while((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
+ /* if the port is TV, then don't set the power to S3 as this causes
+ * blank screen on analog port after killx or cosole mode,
+ * probably because the external clock needs to be on till the pipes and
+ * DPLLs are off
+ */
+ if (port->pd_driver) {
+#ifndef CONFIG_FASTBOOT
+ if(port->pd_type == PD_DISPLAY_TVOUT) {
+ tv_port = port;
+ }else {
+
+ /* for CH7036: Code fix Meego hang after killall X
+ * Basicall, when X enters ACPI D1 state, we want to pass that info to port device (Ch7036)
+ * from reset_plane_pipe_ports_xxx().
+ */
+ if(context->device_context.power_state == IGD_POWERSTATE_D1) {
+ /* D1 power state for graphics is requested
+ * Then the power_state status will pass to pd
+ */
+ port->pd_driver->set_power(port->pd_context,context->device_context.power_state);
+ }
+ else {
+ port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3);
+ }
+ }
+#endif
+ }
+
+ /* Disable WRITE protection on PIPE B for parts with Int-LVDS*/
+ /* This should never happen as the panel power was set to D3 above */
+ if (port->port_reg == LVDSCNTR) {
+ if(EMGD_READ32(EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL) & 0x1) {
+ EMGD_WRITE32(0xABCD0000, EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL);
+ i=0;
+ while(i++ < 0x10) {
+ OS_SLEEP(10);
+ if((EMGD_READ32(EMGD_MMIO(mmio)+LVDS_PNL_PWR_STS)&BIT(31))==0) {
+ break;
+ }
+ }
+ }
+ }
+
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + port->port_reg);
+ EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + port->port_reg);
+ }
+
+ /* disable plane C */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + DSPCCNTR);
+ if(temp & BIT31) {
+ EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR);
+ EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR + DSP_START_OFFSET);
+ }
+
+ plane = NULL;
+ while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) {
+ /* Only display display planes.
+ * Leave cursor, VGA, overlay, sprite planes alone since they will
+ * need a different disable bit/sequence.
+ */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg);
+ if ((plane->plane_features & IGD_PLANE_DISPLAY)) {
+ if ( temp & BIT31 ) {
+ if(plane->plane_reg == DSPACNTR) {
+ EMGD_WRITE32((temp & device_data_plb->plane_a_preserve),
+ EMGD_MMIO(mmio) + plane->plane_reg);
+ }
+ else { /* if it's plane b or plane c */
+ EMGD_WRITE32((temp & device_data_plb->plane_b_c_preserve),
+ EMGD_MMIO(mmio) + plane->plane_reg);
+ }
+ EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
+ }
+ } else if ((plane->plane_features & IGD_PLANE_CURSOR)) {
+ EMGD_WRITE32((temp & 0xffffffe8),
+ EMGD_MMIO(mmio) + plane->plane_reg);
+ EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
+ }
+ }
+
+ /* Turn off pipes */
+ pipe = NULL;
+ while ((pipe = md->dsp_get_next_pipe(context, pipe, 0))) {
+ wait_for_vblank_plb(EMGD_MMIO(mmio), pipe->pipe_reg);
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + pipe->pipe_reg);
+ if ( temp & BIT31 ) {
+ EMGD_WRITE32((temp & device_data_plb->pipe_preserve),
+ EMGD_MMIO(mmio) + pipe->pipe_reg);
+ }
+ }
+ /* pipes and DPLLs are off, now set the power for TV */
+ if(tv_port && tv_port->pd_driver) {
+ tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3);
+ }
+ EMGD_TRACE_EXIT;
+
+} /* end reset_plane_pipe_ports */
+
+/*!
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int program_port_plb(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ unsigned long pipe_number;
+ unsigned long port_control;
+ unsigned long port_control_analog = 0;
+ unsigned long mult_port_control;
+ unsigned long pd_powerstate = 0;
+ unsigned long upscale = 0;
+ pd_timing_t *timing;
+ pd_timing_t local_timing;
+ unsigned long port_type;
+ int ret;
+
+ /* get the pipe number */
+ pipe_number = PIPE(display)->pipe_num;
+
+ /* get the timings */
+ timing = PIPE(display)->timing;
+
+ /* keep the port type as local as we access it frequently */
+ port_type = PORT(display, port_number)->port_type;
+
+ /* Reading the preservation bits */
+ port_control = PORT(display, port_number)->preserve &
+ READ_MMIO_REG(display, PORT(display, port_number)->port_reg);
+
+ /* Reading the preservation bits for SDVO Gang Mode */
+ mult_port_control = PORT(display, port_number)->mult_preserve &
+ READ_MMIO_REG(display, PORT(display, port_number)->port_reg);
+
+ /* If status is false, quickly disable the display */
+ if(status == FALSE) {
+ ret = PORT(display, port_number)->pd_driver->set_power(
+ PORT(display, port_number)->pd_context, PD_POWER_MODE_D3);
+
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_power() returned: 0x%x", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(port_type == IGD_PORT_DIGITAL) {
+ WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
+ port_control);
+
+ if(PORT(display, port_number)->mult_port) {
+ /* either gang mode or RGBA */
+ WRITE_MMIO_REG(display,
+ PORT(display, port_number)->mult_port->port_reg,
+ mult_port_control);
+ }
+ } else if (port_type == IGD_PORT_ANALOG) {
+ port_control |= (BIT11 | BIT10); /* put in D3 state */
+ WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
+ port_control);
+
+ return 0;
+ }
+ return 0;
+ }
+
+ EMGD_DEBUG("status isn't false, Check port enabled");
+
+ if(! (PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ return 0;
+ }
+
+ /*
+ * Is this is the magic mode then turn on VGA syncs
+ */
+ EMGD_DEBUG("Check vga_sync");
+ if(PORT(display, port_number)->vga_sync == 1) {
+ /*
+ * Is this is the magic mode then turn on VGA syncs
+ */
+ EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
+ if((timing->width == 720) && (timing->height == 400)) {
+ EMGD_DEBUG("Modify port control and multi_port_control");
+ port_control |= (1L<<15);
+ mult_port_control |= (1L<<15);
+ }
+ }
+
+ EMGD_DEBUG("Check analog port");
+ if(port_type == IGD_PORT_ANALOG) {
+ port_control |= (0x80000000 | (pipe_number<<30));
+ if(timing->mode_info_flags & IGD_VSYNC_HIGH) {
+ port_control |= (1L<<4);
+ }
+ if(timing->mode_info_flags & IGD_HSYNC_HIGH) {
+ port_control |= (1L<<3);
+ }
+ /* To differentiate between analog and other ports */
+ port_control_analog = port_control;
+ }
+
+ EMGD_DEBUG("Get power state");
+ EMGD_DEBUG("power state = %ld ", GET_DISPLAY_POWER_STATE(display, port_number));
+ switch(GET_DISPLAY_POWER_STATE(display, port_number)) {
+ case IGD_POWERSTATE_D0:
+ EMGD_DEBUG("Power State is D0");
+ pi_pd_find_attr_and_value(PORT(display, port_number),
+ PD_ATTR_ID_PANEL_FIT,
+ 0, /*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ if(port_type == IGD_PORT_DIGITAL) {
+ /* Reach the end timing if upscaling is enabled */
+ if (timing->extn_ptr && upscale) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+
+ local_timing = *timing;
+ if (upscale) {
+ /* For timings smaller than width 360 and height 200,
+ * double the size. This is because the active area of the mode
+ * is double the size of the resolution for these modes
+ * - Very tricky huh */
+ if (local_timing.width <= 360) {
+ local_timing.width <<= 1;
+ }
+ if (local_timing.height <= 200) {
+ local_timing.height <<= 1;
+ }
+ }
+
+ ret = PORT(display, port_number)->pd_driver->set_mode(
+ PORT(display, port_number)->pd_context, &local_timing, 0);
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_mode returned: 0x%x", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* in Plba B-Speecs, there are no bits, *
+ * for the polarity of the H-sync/V-sync */
+
+ /* in Plba B-Speecs, there are no bits, *
+ * for data ordering/format for DVO data */
+ /* Gang-Mode and RGBA models are "exclusive-or" */
+ if((PORT(display, port_number)->pd_driver->flags) &
+ PD_FLAG_GANG_MODE) {
+ mult_port_control |= (1L<<16);
+ } else if(PORT(display, port_number)->pd_type == PD_DISPLAY_RGBA) {
+ mult_port_control |= (1L<<2);
+ }
+
+ timing = PIPE(display)->timing;
+
+ if(timing->dclk > 100000) {
+ /* 100MPs < pixel rate < 200MPs */
+ /* SDVO clock rate multiplier = 1x */
+ /*
+ port_control &= ~BIT23;
+ mult_port_control |= ~BIT23;
+ redundant code since BIT23 is
+ already 0 at this point
+ */
+ } else if(timing->dclk > 50000) {
+ /* 50MPs < pixel rate < 100MPs */
+ /* SDVO clock rate multiplier = 2x */
+ port_control |= (1L<<23);
+ mult_port_control |= (1L<<23);
+ } else {
+ /* 25MPs < pixel rate < 50MPs */
+ /* SDVO clock rate multiplier = 4x */
+ port_control |= (3L<<23);
+ mult_port_control |= (3L<<23);
+ }
+
+ /*
+ * BIT7 = enable the border
+ * Do we need to disable the SDVO border for native
+ * VGA timings(i.e., use DE)?
+ * BIT22->BIT19 = setup the clock phase-9
+ * BIT29 = enable the stall
+ * Only set stall on DVO-B for gang mode
+ * BIT30 = pipe number
+ * BIT31 = port enable
+ */
+ port_control |= ( ( pipe_number<<30 ) | (BIT31) | ((0x9l) << 19) |
+ (BIT29) | (BIT7) );
+ mult_port_control |= ( (BIT31) | ((0x9l) << 19) | (BIT7) );
+
+ WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
+ port_control);
+
+ if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
+ WRITE_MMIO_REG(display,
+ PORT(display, port_number)->mult_port->port_reg,
+ mult_port_control);
+ }
+ return 0;
+ } else if(port_type == IGD_PORT_LVDS) {
+ /*
+ * There is a special case for LVDS scaling. If the timing is
+ * the native one and the extension points to another non-vga
+ * mode then send the extension pointer.
+ */
+ /* Reach the end timing to get user requested mode */
+ if(timing->extn_ptr) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+ }
+ /* set mode will take care of port control */
+ ret = PORT(display, port_number)->pd_driver->set_mode(
+ PORT(display, port_number)->pd_context, (pd_timing_t *)timing,
+ 1<<PIPE(display)->pipe_num);
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_mode returned: 0x%x",ret);
+ return -IGD_INVAL;
+ }
+ break;
+ case IGD_POWERSTATE_D1:
+ port_control_analog &= ~0x80000000;
+ port_control_analog |= 0x00000800 &
+ ~(PORT(display, port_number)->preserve);
+ pd_powerstate =PD_POWER_MODE_D1;
+ break;
+ case IGD_POWERSTATE_D2:
+ port_control_analog &= ~0x80000000;
+ port_control_analog |= 0x00000400 &
+ ~(PORT(display, port_number)->preserve);
+ pd_powerstate = PD_POWER_MODE_D2;
+ break;
+ case IGD_POWERSTATE_D3:
+ port_control_analog &= ~0x80000000;
+ port_control_analog |= 0x00003c00 &
+ ~(PORT(display, port_number)->preserve);
+ pd_powerstate = PD_POWER_MODE_D3;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid power state: 0x%lx",
+ GET_DISPLAY_POWER_STATE(display, port_number));
+ return -IGD_ERROR_INVAL;
+ }
+
+ ret = PORT(display, port_number)->pd_driver->set_power(
+ PORT(display, port_number)->pd_context, pd_powerstate);
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_power returned: 0x%x", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(port_type == IGD_PORT_DIGITAL) {
+ EMGD_DEBUG("Port_control = 0x%lx", port_control);
+
+ WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
+ port_control);
+ if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
+ WRITE_MMIO_REG(display,
+ PORT(display, port_number)->mult_port->port_reg,
+ mult_port_control);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Status is currently not used
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int post_program_port_plb(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ int ret;
+ igd_display_port_t *port;
+ igd_timing_info_t *timings;
+ unsigned long portreg;
+
+ EMGD_TRACE_ENTER;
+
+ port = PORT(display, port_number);
+ timings = PIPE(display)->timing;
+
+ /*
+ * Writing the sDVO control register here works around a problem
+ * where the sDVO port is not turning on when using a CH7308
+ * card in a 915 GM based system and the port order is 5200.
+ *
+ * In addition, post_set_mode() below, will report that the
+ * "inputs are not trained", however, this does not seem to
+ * have any negative effects.
+ */
+ portreg = READ_MMIO_REG(display, port->port_reg);
+ WRITE_MMIO_REG(display, port->port_reg, (portreg & ~BIT31));
+ WRITE_MMIO_REG(display, port->port_reg, portreg);
+
+ /* Reenable/Redisable other port */
+ if (port->port_reg == 0x61140) {
+ WRITE_MMIO_REG(display, 0x61160, READ_MMIO_REG(display,
+ 0x61160));
+ } else {
+ WRITE_MMIO_REG(display, 0x61140,
+ READ_MMIO_REG(display, 0x61140));
+ }
+
+ /*
+ * Added for Lakeport A0
+ * Port clock multiplier bits 4-7, needs to be rewritten
+ */
+ WRITE_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control,
+ READ_MMIO_REG(display, PIPE(display)->clock_reg->dpll_control));
+
+ /* We must wait for 150 us for the dpll clock to warm up */
+ OS_SLEEP(150);
+
+ ret = 0;
+ /* call post_set_mode() if exists */
+ if (port->pd_driver->post_set_mode) {
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ 1<<PIPE(display)->pipe_num);
+ if (ret) {
+ EMGD_ERROR("PD post_set_mode returned: 0x%x", ret);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+int program_cdvo_plb(void)
+{
+ return TRUE;
+}
+
+/*!
+ *
+ * @param gpio
+ *
+ * @return size
+ */
+static unsigned long get_gpio_sets_plb(unsigned long **gpio)
+{
+ *gpio = gpio_plb;
+ return sizeof(gpio_plb)/sizeof(unsigned long);
+}
+
+/*!
+ *
+ * @param context
+ * @param in_list
+ *
+ * @return void - To small to trace
+ */
+static void filter_modes_plb(igd_context_t *context, igd_display_port_t *port,
+ pd_timing_t *in_list)
+{
+
+ return;
+}
+
+#ifndef CONFIG_MICRO
+int check_display_plb(igd_display_context_t *display,
+ unsigned short port_number, unsigned long status){
+ /* For poulsbo display should be working fine */
+ return TRUE;
+}
+#endif
+
+mode_dispatch_t mode_dispatch_plb = {
+ igd_set_palette_entry_plb,
+ igd_get_palette_entry_plb,
+ igd_wait_vblank_plb,
+ program_plane_plb,
+ program_pipe_plb,
+ program_port_plb,
+ post_program_port_plb,
+ program_clock_plb,
+ program_cdvo_plb,
+ reset_plane_pipe_ports_plb,
+ get_gpio_sets_plb,
+ filter_modes_plb,
+ OPT_MICRO_VALUE(&check_display_plb, NULL),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ OPT_MICRO_VALUE(&mode_full_dispatch_plb, NULL),
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
new file mode 100644
index 0000000..55a90cc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
@@ -0,0 +1,1963 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_plb.c
+ * $Revision: 1.34 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Almador Core implementations for the mode dispatch functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd.h>
+#include <igd_pwr.h>
+
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+#include <dsp.h>
+#include <intelpci.h>
+#include <mode_access.h>
+#include <rb.h>
+#include <pi.h>
+#include <math_fix.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+#include <plb/mi.h>
+#include <plb/cmd.h>
+
+#include "drm_emgd_private.h"
+#include "../cmn/match.h"
+#include "../cmn/mode_dispatch.h"
+
+#include "emgd_shared.h"
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <drm/drmP.h>
+
+
+/* Registered VBlank interrupt callbacks (one-per-pipe): */
+static emgd_vblank_callback_t interrupt_callbacks_plb[IGD_MAX_PORTS] =
+ {{NULL,NULL,0},{NULL,NULL,1},{NULL,NULL,2},{NULL,NULL,3},{NULL,NULL,4}};
+
+/* This variable contains a number of bits, which tell whether the interrupt
+ * code has enabled interrupts, and if so, for what software and for what
+ * port(s); and whether certain events have happened.
+ */
+static unsigned long vblank_interrupt_state = 0;
+
+/* This variables keeps track of the number of clients currently using
+ * the vblank interrupt
+ */
+static int vblank_interrupt_ref_cnt_port2 = 0;
+static int vblank_interrupt_ref_cnt_port4 = 0;
+
+/* Spin lock for synchronization of the vblank_interrupt_state variable,
+ * between the VBlank interrupt handler and the non-interrupt handler code:
+ */
+DEFINE_SPINLOCK(vblank_lock_plb);
+
+
+
+int set_flip_pending_plb(unsigned char *mmio, unsigned long pipe_status_reg);
+int check_flip_pending_plb(unsigned char *mmio, unsigned long pipe_status_reg);
+
+unsigned long get_port_control_plb(unsigned long port_num, unsigned long port_reg);
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+int wait_for_vblank_plb(unsigned char *mmio, unsigned long pipe_reg);
+
+void notify_userspace_vblank(struct drm_device *dev, int port);
+
+/*!
+ *
+ * @param display
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_plb(igd_display_context_t *display)
+{
+ const int MID_PIXEL_VAL = 125;
+ const int MAX_PIXEL_VAL = 255;
+ const int NUM_PALETTE_ENTRIES = 256;
+
+ unsigned int gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+ unsigned int gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+ unsigned int gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+ unsigned int new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+ unsigned int new_gamma_b_24i_8f;
+ unsigned int gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ int brightness_factor_r, brightness_factor_g;
+ int brightness_factor_b;
+ int contrast_factor_r, contrast_factor_g;
+ int contrast_factor_b;
+
+ unsigned int *palette;
+ unsigned int i;
+
+ igd_range_attr_t *gamma_attr = NULL, *contrast_attr = NULL;
+ igd_range_attr_t *brightness_attr = NULL;
+ igd_attr_t *hal_attr_list = PORT_OWNER(display)->attributes;
+
+
+ /* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+ palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+ /* start with a fresh palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ palette[i] = (i << 16) | (i << 8) | i;
+ }
+
+ /* get a pointer to gamma, contrast, and brightness attr */
+ i = 0;
+
+ while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+ switch (hal_attr_list[i].id) {
+ case PD_ATTR_ID_FB_GAMMA:
+ gamma_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_BRIGHTNESS:
+ brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_CONTRAST:
+ contrast_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ default:
+ break;
+ }
+
+ i++;
+ }
+
+ if(!gamma_attr || !brightness_attr || !contrast_attr) {
+ EMGD_ERROR("Color Correction Atrributes not found!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get the max and min */
+ gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+ gamma_g_max_24i_8f = ((gamma_attr->max >> 8) & 0xFF) << 3;
+ gamma_b_max_24i_8f = (gamma_attr->max & 0xFF) << 3;
+
+ gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+ gamma_g_min_24i_8f = ((gamma_attr->min >> 8) & 0xFF) << 3;
+ gamma_b_min_24i_8f = (gamma_attr->min & 0xFF) << 3;
+
+ /* The new gamma values are in 3i.5f format, but we must convert it
+ * to 24i.8f format before passing it to OS_POW_FIX
+ */
+ new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+ new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+ new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+ /* make sure the new gamma is within range */
+ new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+ new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+ gamma_normal_r_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+ gamma_normal_g_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+ gamma_normal_b_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ unsigned int new_gamma;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* Note that we do not try to calculate the gamma if it
+ * is 1.0, e.g. 0x100. This is to avoid round-off errors
+ */
+
+ /* red: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_r_24i_8f) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+ palette[i] &= 0x00FFFF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_g_24i_8f) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+ palette[i] &= 0xFF00FF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_b_24i_8f) {
+ cur_color = cur_palette & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+ palette[i] &= 0xFFFF00;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+ }
+ }
+
+
+ /* Brightness correction */
+ brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+ brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+ brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+ /* The factors are offset by 0x80 because 0x80 is 0 correction */
+ brightness_factor_r -= 0x80;
+ brightness_factor_g -= 0x80;
+ brightness_factor_b -= 0x80;
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_r;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+ /* green: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_g;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+ /* blue: calculate and make sure the result is within range */
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_b;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00;
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+
+
+ /* contrast correction */
+ contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+ contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+ contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+ /* make sure values are within range */
+ contrast_factor_r -= 0x80;
+ contrast_factor_g -= 0x80;
+ contrast_factor_b -= 0x80;
+
+
+ /* We're doing integer division in this loop using 16i.16f
+ * integers. The result will then be converted back into a
+ * regular, 32-bit integer
+ */
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ if (0 != contrast_factor_r ) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF; /* clear out the R color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0 != contrast_factor_g ) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF; /* clear out the G color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0 != contrast_factor_b) {
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00; /* clear out the B color */
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+ }
+
+
+ /* write the new values in the palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ EMGD_WRITE32(palette[i], MMIO(display) +
+ PIPE(display)->palette_reg + i*4);
+ }
+ OS_FREE(palette);
+
+ return 0;
+}
+
+/*!
+ * Note: When panning in clone mode, the clone must be panned seperatly
+ * because it may (probably does) have a different x,y offset.
+ *
+ * @param display
+ * @param fb
+ * @param x
+ * @param y
+ *
+ * @return 0
+ */
+static int set_display_base_plb(igd_display_context_t *display,
+ igd_framebuffer_info_t *fb, unsigned long *x, unsigned long *y)
+{
+ unsigned long base;
+
+ /* FIXME/TODO: Compare the difference between the plb/tnc versions of this
+ * function, as the plb code adds-in the offset of the frame buffer.
+ */
+ base = fb->visible_offset;
+
+ base += ((*y * fb->screen_pitch) + (*x * IGD_PF_BYPP(fb->pixel_format)));
+
+ WRITE_MMIO_REG(display, PLANE(display)->plane_reg
+ + DSP_START_OFFSET, base);
+
+#if 0
+ /* If this plane is a mirrored plane, then update the other plane offset */
+ if (PLANE(display)->mirror) {
+ WRITE_MMIO_REG(display, PLANE(display)->mirror->plane_reg
+ + DSP_START_OFFSET, base);
+ }
+#endif
+
+ return 0;
+}
+
+/*!
+ * This function alters the position parameters associated with a cursor.
+ *
+ * @param display_handle
+ * @param cursor_info
+ *
+ * @return 0
+ */
+static int igd_alter_cursor_pos_plb(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info)
+{
+ unsigned long cursor_reg;
+ unsigned long new_pos;
+ unsigned long cursor_base;
+
+ igd_display_context_t *display = (igd_display_context_t *) display_handle;
+ cursor_reg = PIPE(display)->cursor->cursor_reg;
+
+ if (0x27 & READ_MMIO_REG(display, cursor_reg)) {
+ /* unlike almador, for plba, u must program the base offset
+ to trigger the position update. However, this also means we
+ accidentally enable an invalid cursor surface if the cursor
+ was not enabled already. So do this check first */
+
+ /*
+ * Encode the cursor position in the format required for the
+ * cursor position register.
+ */
+ if(cursor_info->y_offset >= 0) {
+ new_pos = (cursor_info->y_offset << 16);
+ } else {
+ new_pos = ((-(cursor_info->y_offset)) << 16) | 0x80000000;
+ }
+ if(cursor_info->x_offset >= 0) {
+ new_pos |= (cursor_info->x_offset);
+ } else {
+ new_pos |= (-(cursor_info->x_offset)) | 0x00008000;
+ }
+
+ cursor_base = READ_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET);
+
+ WRITE_MMIO_REG(display, cursor_reg + CUR_POS_OFFSET, new_pos);
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+ }
+
+ return 0;
+}
+
+/*!
+ * The assumption here is that palette_colors points to index 0 and
+ * this function indexes into the palette_colors array by start_index
+ *
+ * @param display_handle
+ * @param palette_colors
+ * @param start_index
+ * @param count
+ *
+ * @return 0
+ */
+static int igd_set_palette_entries_plb(
+ igd_display_h display_handle,
+ unsigned long *palette_colors,
+ unsigned int start_index,
+ unsigned int count)
+{
+ unsigned int i;
+
+ for(i=start_index; i<start_index+count; i++) {
+ EMGD_WRITE32(palette_colors[i],
+ MMIO(display_handle) + PIPE(display_handle)->palette_reg + i*4);
+ }
+
+ return 0;
+}
+
+/*!
+ * This procedure waits for the next vertical sync
+ * period. If the display is already in a vertical sync period, this
+ * procedure exits.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param display_handle
+ * @param palette_colors
+ * @param start_index
+ * @param count
+ *
+ * @return FALSE - if timed out
+ */
+static int igd_wait_vsync_plb(igd_display_h display_handle)
+{
+ long i = 0; /* General counter */
+ unsigned long tmp;
+ unsigned char *Status_Reg;
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned char *mmio = MMIO(display);
+
+ Status_Reg = mmio + PIPE(display)->pipe_reg + PIPE_STATUS_OFFSET;
+
+ /* If pipe is off then just return */
+ if(!((1<<31) & EMGD_READ32(mmio + PIPE(display)->pipe_reg))) {
+ return 1;
+ }
+
+ /* 1. Disable VSync interrupt */
+ tmp = EMGD_READ32(Status_Reg);
+ /* The sticky status bits are cleared by writing a 1, so zero them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32 (tmp & ~(1<<25), Status_Reg);
+
+ /* 2. Clear interrupt status (by writing a 1) */
+ tmp = EMGD_READ32(Status_Reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32 (tmp | (1<<9), Status_Reg);
+
+ /* 3. Enable VSync interrupt */
+ tmp = EMGD_READ32(Status_Reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32 (tmp | (1<<25), Status_Reg);
+
+ /* 4. Wait for VSync */
+ while ((i++ < 0x1000000) && /* Check for timeout */
+ ((EMGD_READ32(Status_Reg) & (1<<9)) == 0x00)) {
+ ;
+ }
+
+ /* 5. Disable VSync interrupt */
+ tmp = EMGD_READ32(Status_Reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32 (tmp & ~(1<<25), Status_Reg);
+
+ /* 6. Clear interrupt status (by writing a 1) */
+ tmp = EMGD_READ32(Status_Reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32 (tmp | (1<<9), Status_Reg);
+
+ if (i >= 0x10000000)
+ return (0);
+
+ return (1);
+} /* igd_wait_vsync*/
+
+
+/*!
+ *
+ * @param display_handle
+ * @param scanline
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+
+static int igd_get_scanline_plb(igd_display_h display_handle, int *scanline)
+{
+ unsigned int tmp;
+ unsigned char *reg;
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned long fb_height = PLANE(display)->fb_info->height;
+ unsigned long dp_height = PIPE(display)->timing->height;
+
+ /* Scanline reg is -8 from control reg */
+ reg = MMIO(display) + PIPE(display)->pipe_reg - 0x8;
+
+ tmp = EMGD_READ32(reg);
+
+ if(!(PORT_OWNER(display)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ tmp = (tmp * fb_height) / dp_height;
+
+ if(tmp >= fb_height) {
+ *scanline = IGD_IN_VBLANK;
+ } else {
+ *scanline = (int)tmp;
+ }
+ return 0;
+} /* end igd_get_scanline() */
+
+/*!
+ *
+ * @param display_handle
+ *
+ * @return 1 if TRUE
+ * @return 0 if FALSE
+ */
+static int igd_query_in_vblank_plb(igd_display_h display_handle)
+{
+ int sl;
+
+ igd_get_scanline_plb(display_handle, &sl);
+ if (sl == IGD_IN_VBLANK) {
+ return 1; /*TRUE*/
+ } else {
+ return 0; /*FALSE*/
+ }
+}
+
+/*!
+ * This function programs the cursor registers for Grantsdale
+ *
+ * @param display
+ * @param status
+ *
+ * @return void
+ */
+static void program_cursor_plb(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long cursor_reg;
+ unsigned long cursor_control = 0x00000000;
+ unsigned long cursor_pos;
+ unsigned long cursor_base;
+ igd_cursor_info_t *cursor_info;
+ int i;
+
+ EMGD_DEBUG("Enter program_cursor: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ if (!(PIPE(display)->cursor)) {
+ return;
+ }
+
+ cursor_reg = PIPE(display)->cursor->cursor_reg;
+ cursor_info = PIPE(display)->cursor->cursor_info;
+
+ /* Turn off cursor before changing anything */
+ cursor_base = READ_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET);
+
+ WRITE_MMIO_REG(display, cursor_reg, cursor_control);
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+
+ if(cursor_info->flags & IGD_CURSOR_GAMMA) {
+ cursor_control |= BIT26;
+ }
+
+ cursor_info->argb_pitch = 64*4;
+ cursor_info->xor_pitch = 16;
+
+ /* Setting the cursor format/pitch */
+ switch(cursor_info->pixel_format) {
+ case IGD_PF_ARGB32:
+ cursor_control |= BIT5 | 0x7;
+ break;
+ case IGD_PF_RGB_XOR_2:
+ cursor_control |= 0x5;
+ break;
+ case IGD_PF_RGB_T_2:
+ cursor_control |= 0x4;
+ break;
+ case IGD_PF_RGB_2:
+ cursor_control |= 0x6;
+ break;
+ default:
+ return;
+ }
+
+ switch(cursor_info->pixel_format) {
+ case IGD_PF_ARGB32:
+ if(display->context->dispatch.gmm_virt_to_phys(
+ cursor_info->argb_offset, &cursor_base)) {
+ EMGD_ERROR("No Phys pointer available for ARGB cursor");
+ return;
+ }
+ break;
+ default:
+ if(display->context->dispatch.gmm_virt_to_phys(
+ cursor_info->xor_offset, &cursor_base)) {
+ EMGD_ERROR("No Phys pointer available for XOR cursor");
+ return;
+ }
+ break;
+ }
+
+ /* If status is FALSE return with the cursor off */
+ if((!status) ||
+ (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
+ return;
+ }
+
+ if(cursor_info->y_offset >= 0) {
+ cursor_pos = cursor_info->y_offset << 16;
+ } else {
+ cursor_pos = ((-(cursor_info->y_offset)) << 16) | 0x80000000;
+ }
+ if(cursor_info->x_offset >= 0) {
+ cursor_pos |= cursor_info->x_offset;
+ } else {
+ cursor_pos |= (-(cursor_info->x_offset)) | 0x00008000;
+ }
+
+ WRITE_MMIO_REG(display, cursor_reg + CUR_POS_OFFSET,
+ cursor_pos);
+
+ for(i=0; i<4; i++) {
+ WRITE_MMIO_REG(display, cursor_reg + CUR_PAL0_OFFSET + i*4,
+ cursor_info->palette[i]);
+ }
+
+ WRITE_MMIO_REG(display, cursor_reg,
+ cursor_control | (PIPE(display)->pipe_num<<28));
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param type
+ * @param surface
+ * @param appcontext
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_get_surface_plb(igd_display_h display_handle,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext)
+{
+#if 0
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ state3d_plb_t *state = STATE3D_PLB(appcontext);
+
+ if(!surface) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch(type) {
+ case IGD_BUFFER_DISPLAY:
+ surface->offset = PLANE(display)->fb_info->visible_offset;
+ surface->pitch = PLANE(display)->fb_info->screen_pitch;
+ surface->width = PLANE(display)->fb_info->width;
+ surface->height = PLANE(display)->fb_info->height;
+ surface->u_offset = 0;
+ surface->u_pitch = 0;
+ surface->v_offset = 0;
+ surface->v_pitch = 0;
+ surface->pixel_format = PLANE(display)->fb_info->pixel_format;
+ surface->palette_info = 0;
+ surface->flags = PLANE(display)->fb_info->flags;
+ surface->logic_ops = 0;
+ surface->render_ops = 0;
+ surface->alpha = 0;
+ surface->diffuse = 0;
+ surface->chroma_high = 0;
+ surface->chroma_low = 0;
+ return 0;
+ case IGD_BUFFER_COLOR:
+ OS_MEMCPY(surface, &state->color_buffer,
+ sizeof(igd_surface_t));
+ return 0;
+ case IGD_BUFFER_DEPTH:
+ OS_MEMCPY(surface, &state->depth_buffer,
+ sizeof(igd_surface_t));
+ return 0;
+ default:
+ EMGD_ERROR("Invalid type in get_surface");
+ break;
+ }
+
+ return -IGD_ERROR_INVAL;
+#else
+ return 0;
+#endif
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param type
+ * @param surface
+ * @param appcontext
+ * @param flags
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_set_surface_plb(igd_display_h display_handle,
+ int priority,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext,
+ unsigned long flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned int dsp_current;
+ unsigned long plane_reg;
+ unsigned long plane_control;
+ unsigned long surface_offset;
+
+ EMGD_TRACE_ENTER;
+ if(!surface) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch(type) {
+ case IGD_BUFFER_DISPLAY:
+ if(! (surface->flags & IGD_SURFACE_DISPLAY)) {
+ EMGD_ERROR_EXIT("Surface is not a display surface");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (PLANE(display)->plane_reg == DSPACNTR) {
+ EMGD_DEBUG("About to flip a buffer for display/pipe A");
+ dsp_current = 0;
+ } else {
+ EMGD_DEBUG("About to flip a buffer for display/pipe B");
+ dsp_current = 1;
+ }
+
+ if(flags & IGD_BUFFER_WAIT) {
+ /* If this is just a wait for flip, so return */
+ return 0;
+ }
+
+ /*
+ * Async flips only work when the offset is on a 256kb boundary.
+ */
+ if(PLANE(display)->fb_info->visible_offset & 0x3ffff) {
+ EMGD_ERROR("FB offset must be 256kb aligned in Poulsbo");
+ }
+
+ /* Save new fb_info */
+ PLANE(display)->fb_info->visible_offset = surface->offset;
+ PLANE(display)->fb_info->screen_pitch = surface->pitch;
+ PLANE(display)->fb_info->width = surface->width;
+ PLANE(display)->fb_info->height = surface->height;
+ PLANE(display)->fb_info->pixel_format = surface->pixel_format;
+ PLANE(display)->fb_info->flags = surface->flags;
+
+ /* Get the correct stride and stereo */
+ /* TODO - Does Poulsbo flip need to handle stereo mode? */
+ /*mode_get_stride_stereo_plb(display, &stride, &stereo, 0);*/
+
+ /* calculate the real offset, taking panning into account */
+ surface_offset = surface->offset;
+ surface_offset +=
+ (PORT_OWNER(display)->pt_info->y_offset * surface->pitch) +
+ (PORT_OWNER(display)->pt_info->x_offset *
+ IGD_PF_BYPP(surface->pixel_format));
+ EMGD_DEBUG("surface_offset = 0x%08lx", surface_offset);
+
+ plane_reg = PLANE(display)->plane_reg;
+ plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+
+ /* Perform the flip by doing the following:
+ *
+ * Write the current plane_control value to the plane_reg
+ * Write the surface offset to either:
+ * 1) the plane_reg - 4 if async
+ * 2) plane_reg + DSP_START_OFFSET (+4) if not async
+ */
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(surface_offset,
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_COLOR:
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_DEPTH:
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_SAVE:
+ PLANE(display)->fb_info->saved_offset = surface->offset;
+ EMGD_DEBUG("saving surface_offset = 0x%08lx", surface->offset);
+ EMGD_TRACE_EXIT;
+ return 0;
+ default:
+ EMGD_ERROR("Invalid type in set_surface");
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/* Poulsbo does not support a flip pending, since there is no
+ * Display Buffer Info instruction. So this must be done with vBlank.
+ * However, a wait_for_vblank can be given while a flip is also in
+ * progress, so a semaphore is required when changing flip_pending or
+ * when modifying the vBlank interrupt bits.
+ *
+ * This function should only be called with a flip_mutex around it */
+int set_flip_pending_plb(unsigned char *mmio, unsigned long pipe_status_reg)
+{
+ platform_context_plb_t *plb_context =
+ (platform_context_plb_t *)mode_context->context->platform_context;
+ unsigned long request_for;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT((pipe_status_reg == PIPEA_STAT) ||
+ (pipe_status_reg == PIPEB_STAT), "Invalid pipe_status_reg", 0);
+
+ if (pipe_status_reg == PIPEA_STAT) {
+ plb_context->flip_pending |= PLB_FLIP_PIPE_A_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2);
+ } else {
+ plb_context->flip_pending |= PLB_FLIP_PIPE_B_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4);
+ }
+ mode_context->dispatch->full->request_vblanks(request_for, mmio);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/* This function should only be called with a flip_mutex around it */
+int check_flip_pending_plb(unsigned char *mmio,
+ unsigned long pipe_status_reg)
+{
+ platform_context_plb_t *plb_context =
+ (platform_context_plb_t *)mode_context->context->platform_context;
+ unsigned long request_for;
+ unsigned int flip_pending;
+
+ EMGD_TRACE_ENTER;
+ EMGD_ASSERT((pipe_status_reg == PIPEA_STAT) ||
+ (pipe_status_reg == PIPEB_STAT), "Invalid pipe_status_reg", 0);
+
+ if (pipe_status_reg == PIPEA_STAT) {
+ flip_pending = plb_context->flip_pending & PLB_FLIP_PIPE_A_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2);
+ } else {
+ flip_pending = plb_context->flip_pending & PLB_FLIP_PIPE_B_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4);
+ }
+
+ if (flip_pending) {
+ if (mode_context->dispatch->full->vblank_occured(request_for)) {
+ /* VBlank occured, flip complete */
+ plb_context->flip_pending &= ~flip_pending;
+ mode_context->dispatch->full->end_request(request_for, mmio);
+ EMGD_DEBUG("VBlank occured--returning 0");
+ return 0;
+ } else {
+ /* VBlank not done, flip still in progress */
+ EMGD_DEBUG("VBlank hasn't yet occured--returning 1");
+ return 1;
+ }
+ } else {
+ /* No flip pending, so it must have completed */
+ EMGD_DEBUG("returning 0");
+ return 0;
+ }
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param event
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_query_event_plb(igd_display_h display_handle,
+ igd_event_t event, unsigned long *status)
+{
+ platform_context_plb_t *plb_context =
+ (platform_context_plb_t *)mode_context->context->platform_context;
+ unsigned char *mmio = MMIO(display_handle);
+ unsigned long pipe_status_reg =
+ (PLANE(display_handle)->plane_reg == DSPACNTR) ? 0x70024 : 0x71024;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("mmio=0x%p, pipe_status_reg=0x%08lx", mmio, pipe_status_reg);
+
+ switch (event) {
+ case IGD_EVENT_FLIP_PENDING:
+ ret = OS_PTHREAD_MUTEX_LOCK(&plb_context->flip_mutex);
+ *status = check_flip_pending_plb(mmio, pipe_status_reg);
+ OS_PTHREAD_MUTEX_UNLOCK(&plb_context->flip_mutex);
+ break;
+ default:
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Returning status=%lu", *status);
+ return IGD_SUCCESS;
+}
+
+/*!
+ * Function gets the width, height and pitch of the framebuffer.
+ *
+ * @param void
+ *
+ * @return 0
+ */
+static int get_plane_info_plb(void)
+{
+ igd_framebuffer_info_t *buffer_info;
+ unsigned char* mmio = NULL;
+ unsigned long plane_control = 0;
+ unsigned long reg = 0;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ /* Check that plane A is active and process it */
+ plane_control = EMGD_READ32(mmio + DSPACNTR);
+ if(plane_control & PLANE_ENABLE){
+ buffer_info = &mode_context->fw_info->fb_info[0];
+
+ /* get the DSPASIZE register value */
+ reg = (unsigned long)EMGD_READ32(mmio + DSPACNTR + DSP_SIZE_OFFSET);
+ buffer_info[0].height = (reg >> 16) & 0xFFF;
+ buffer_info[0].width = reg & 0xFFF;
+
+ /* get the DSPASTRIDE register value */
+ buffer_info[0].screen_pitch =
+ (unsigned int)EMGD_READ32(mmio + DSPACNTR + DSP_STRIDE_OFFSET);
+
+ /* Following are NOT offset by 1 in fb info */
+ buffer_info[0].width++;
+ buffer_info[0].height++;
+ }
+
+ /* Check that plane B is active and process it */
+ plane_control = EMGD_READ32(mmio + DSPBCNTR);
+ if(plane_control & PLANE_ENABLE){
+ buffer_info = &mode_context->fw_info->fb_info[0];
+
+ /* get the DSPBSIZE register value */
+ reg = (unsigned long)EMGD_READ32(mmio + DSPBCNTR + DSP_SIZE_OFFSET);
+ buffer_info[1].height = (reg >> 16) & 0xFFF;
+ buffer_info[1].width = reg & 0xFFF;
+
+ /* get the DSPBSTRIDE register value */
+ buffer_info[1].screen_pitch =
+ (unsigned int)EMGD_READ32(mmio + DSPBCNTR + DSP_STRIDE_OFFSET);
+
+ /* Following are NOT offset by 1 in fb info */
+ buffer_info[1].width++;
+ buffer_info[1].height++;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param void
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int get_pipe_info_plb(igd_display_h *display)
+{
+ unsigned char *mmio = NULL;
+ unsigned long pipe_conf = 0;
+ igd_display_info_t *timing;
+ unsigned long reg = 0;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ pipe_conf = EMGD_READ32(mmio + PIPEA_CONF);
+
+ if(pipe_conf & BIT(31)) { /* pipe A is active */
+ timing = &mode_context->fw_info->timing_arr[0];
+
+ reg = EMGD_READ32(mmio + HTOTAL_A);
+ timing[0].htotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[0].width = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + HBLANK_A);
+ timing[0].hblank_start = (unsigned short)reg & 0x1FFF;
+ timing[0].hblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + HSYNC_A);
+ timing[0].hsync_start = (unsigned short)reg & 0x1FFF;
+ timing[0].hsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + VTOTAL_A);
+ timing[0].vtotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[0].height = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + VBLANK_A);
+ timing[0].vblank_start = (unsigned short)reg & 0x1FFF;
+ timing[0].vblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + VSYNC_A);
+ timing[0].vsync_start = (unsigned short)reg & 0x1FFF;
+ timing[0].vsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ /* Following are not offset by 1 in ptinfo */
+ timing[0].width++;
+ timing[0].height++;
+
+ EMGD_DEBUG("Pipe A timing width = %d", timing[0].width);
+ EMGD_DEBUG("Pipe A timing width = %d", timing[0].height);
+
+ {
+ /* Calculate the firmware programmed dot clock */
+ unsigned long dplla, fpa0, fpa1;
+ unsigned long ma1, ma2, na, pa1, pa2, plla_select;
+ unsigned long ref_freq = 0, dclk;
+ unsigned long temp; /* To store intermediate values b4 dclk */
+ int j;
+
+ dplla = EMGD_READ32(mmio + DPLLACNTR);
+ fpa0 = EMGD_READ32(mmio + FPA0);
+ fpa1 = EMGD_READ32(mmio + FPA1);
+
+ if(dplla & BIT(31)) {
+
+ ma1 = (fpa0 >> 8) & 0x3F; /* M1 is bits 13:8 */
+ ma2 = (fpa0) & 0x1F; /* M1 is bits 5:0 */
+ na = (fpa0 >> 16) & 0x3F; /* N is bits 21:16 */
+ pa1 = (dplla >> 16) & 0xFF; /* P1 is bits 23:16 */
+
+ /* Check for illegal values of P1
+ * The bit representation MUST be power of 2
+ * All other values are illegal including zero.
+ */
+ if( (pa1 == 0) ||
+ ( (pa1 & (pa1-1)) != 0 ) ) {
+
+ EMGD_ERROR("Invalid P1 bits set");
+ return -IGD_ERROR_INVAL;
+ }
+ for(j = 0; j < 8; j++) {
+ if(pa1 & BIT(j)) { /* P1 is divide by 1 to 8 */
+ pa1 = j+1;
+ break;
+ }
+ }
+ pa2 = (dplla >> 24) & 0x3; /* P2 is bits 25:24 */
+
+ /* The post divisor values are different if the
+ * attached port is internal LVDS. Since Pipe A
+ * does not support internal LVDS, we just follow
+ * the normal divisor values
+ */
+ if(pa2 == 0) {
+ pa2 = 10;
+ } else if(pa2 == 1) {
+ pa2 = 5;
+ } else {
+ EMGD_ERROR("Invalid P2 bits set = 0x%lx", pa2);
+ }
+ plla_select = (dplla >> 13) & 0x3; /* PLL Ref I/P Select */
+
+ /* Equation that calculates the dot clk
+ * -------------------------------------
+ *
+ * pll_freq_factor = ((float)(5 * (ma1+2)+(ma2+2))/(na+2))/
+ * ((pa1*pa2));
+ *
+ * fdclk = pll_freq_factor * ref_freq * 1000000;
+ *
+ * Support for FPU in Kernel Code is not straightforward
+ * we will just stick to int operations. We will just re-
+ * arrange the factors.
+ */
+ if(plla_select == 0) {
+ ref_freq = 96; /* 96MHz */
+ } else if( (plla_select == 1) || (plla_select == 3) ) {
+
+ EMGD_ERROR("Invalid PLL Reference Input Select Reserved");
+ return -IGD_ERROR_INVAL;
+
+ } else if(plla_select == 2) {
+ EMGD_DEBUG("PLL ref is SDVO TV CLK");
+ /* TODO: How to handle this value? */
+ ref_freq = 0;
+ }
+
+ /* First let's multiply by 1000 * 1000
+ * so that we don't get zero during integer
+ * division
+ */
+ temp = 1000 * 1000;
+ temp = temp * (5 * (ma1+2) + (ma2+2));
+ temp = temp/(na+2);
+ temp = temp/(pa1*pa2);
+
+ /* dclk = temp * ref_freq; */
+
+ /* FIXME: This is a workaround to get dclk. We are supposed
+ * to be calculating this based on the formula, but DPLL
+ * is somehow locked and does not return the programmed
+ * p1 value. Once this is fixed, we no longer need to have
+ * igd_display_handle in the parameter of get_pipe_info
+ */
+ if (NULL != display) {
+ /*igd_display_context_t *display_context =
+ (igd_display_context_t *) display;*/
+
+ /* dclk = ref_freq * m / (p1 * p2); */
+
+ /* PIPE(display)->dclk is in KHhz */
+ dclk = PIPE(display)->dclk * 1000;
+
+ } else {
+ dclk = 0;
+ }
+
+ if( (dclk == 0) || (ref_freq == 0) ) {
+ EMGD_ERROR(" Dot Clock/Ref Frequency is Zero!!!");
+ return -IGD_ERROR_INVAL;
+ }
+ EMGD_DEBUG("Ref frequency = %lu", ref_freq);
+ EMGD_DEBUG("Pipe A constructed Dot clock is = %lu", dclk);
+ timing[0].dclk = dclk/1000; /* Make it to KHz */
+ EMGD_DEBUG("Pipe A Dot clock in KHz = %lu", timing[0].dclk);
+
+ timing[0].refresh = (unsigned short)(dclk/
+ ((timing[0].htotal+1)*(timing[0].vtotal+1)));
+
+ EMGD_DEBUG("Pipe A refresh = %u", timing[0].refresh);
+ } /* if DPLL A active */
+ } /* dot clock code block */
+ } /* if Pipe A active */
+
+ pipe_conf = EMGD_READ32(mmio + PIPEB_CONF);
+
+ if(pipe_conf & BIT(31)) { /* pipe B is active */
+ timing = &mode_context->fw_info->timing_arr[0];
+
+ reg = EMGD_READ32(mmio + HTOTAL_B);
+ timing[1].htotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[1].width = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + HBLANK_B);
+ timing[1].hblank_start = (unsigned short)reg & 0x1FFF;
+ timing[1].hblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + HSYNC_B);
+ timing[1].hsync_start = (unsigned short)reg & 0x1FFF;
+ timing[1].hsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + VTOTAL_B);
+ timing[1].vtotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[1].height = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + VBLANK_B);
+ timing[1].vblank_start = (unsigned short)reg & 0x1FFF;
+ timing[1].vblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ EMGD_READ32(mmio + VSYNC_B);
+ timing[1].vsync_start = (unsigned short)reg & 0x1FFF;
+ timing[1].vsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ /* Following are not offset by 1 in ptinfo */
+ timing[1].width++;
+ timing[1].height++;
+
+ EMGD_DEBUG("Pipe B timing width = %d", timing[1].width);
+ EMGD_DEBUG("Pipe B timing width = %d", timing[1].height);
+
+ {
+ /* Calculate the firmware programmed dot clock */
+ unsigned long dpllb, fpb0, fpb1;
+ unsigned long mb1, mb2, nb, pb1, pb2, pllb_select;
+ unsigned long ref_freq = 0, dclk;
+ unsigned long temp; /* To store intermediate values b4 dclk */
+ int j;
+ unsigned long lvds_port;
+
+ dpllb = EMGD_READ32(mmio + DPLLBCNTR);
+ fpb0 = EMGD_READ32(mmio + FPB0);
+ fpb1 = EMGD_READ32(mmio + FPB1);
+ /* Note: Only Pipe B supports LVDS */
+ lvds_port = EMGD_READ32(mmio + LVDSCNTR);
+
+ if(dpllb & BIT(31)) {
+
+ mb1 = (fpb0 >> 8) & 0x3F; /* M1 is bits 13:8 */
+ mb2 = (fpb0) & 0x1F; /* M1 is bits 5:0 */
+ nb = (fpb0 >> 16) & 0x3F; /* N is bits 21:16 */
+ pb1 = (dpllb >> 16) & 0xFF; /* P1 is bits 23:16 */
+
+ /* Check for illegal values of P1
+ * The bit representation MUST be power of 2
+ * All other values are illegal including zero.
+ */
+ if( (pb1 == 0) ||
+ ( (pb1 & (pb1-1)) != 0 ) ) {
+ EMGD_ERROR("Invalid P1 bits set");
+ return -IGD_ERROR_INVAL;
+ }
+
+ for(j = 0; j < 8; j++) {
+ if(pb1 & BIT(j)) { /* P1 is divide by 1 to 8 */
+ pb1 = j+1;
+ break;
+ }
+ }
+
+ pb2 = (dpllb >> 24) & 0x3; /* P2 is bits 25:24 */
+
+ /* For LVDS port, the post divisor factors are different */
+ if((lvds_port & 0xC0000000) == 0xC0000000) {
+ /* Pipe is used for LVDS port */
+ if(pb2 == 0) {
+ pb2 = 14;
+ } else if(pb2 == 1) {
+ pb2 = 7;
+ } else {
+ EMGD_ERROR("Invalid P2 bits set = 0x%lx", pb2);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ } else {
+ /* Pipe is used for Non-LVDS port */
+ if(pb2 == 0) {
+ pb2 = 10;
+ } else if(pb2 == 1) {
+ pb2 = 5;
+ } else {
+ EMGD_ERROR(":Invalid P2 bits set = 0x%lx", pb2);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ }
+
+ pllb_select = (dpllb >> 13) & 0x3; /* PLL Ref I/P Select */
+
+ /* Equation that calculates the dot clk
+ * -------------------------------------
+ *
+ * pll_freq_factor = ((float)(5 * (mb1+2)+(mb2+2))/(nb+2))/
+ * ((pb1*pb2));
+ *
+ * fdclk = pll_freq_factor * ref_freq * 1000000;
+ *
+ * Support for FPU in Kernel Code is not straightforward
+ * we will just stick to int operations. We will just re-
+ * arrange the factors.
+ */
+ if(pllb_select == 0) {
+ ref_freq = 96; /* 96MHz */
+
+ } else if( (pllb_select == 1) || (pllb_select == 3) ) {
+
+ EMGD_ERROR("Invalid PLL Reference Input Select Reserved");
+ return -IGD_ERROR_INVAL;
+
+ } else if(pllb_select == 2) {
+ EMGD_DEBUG("PLL ref is SDVO TV CLK");
+ /* TODO: How to handle this value? */
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* First let's multiply by 1000 * 1000
+ * so that we don't end up in zero during
+ * integer division
+ */
+ temp = 1000 * 1000;
+ temp = temp * (5 * (mb1+2) + (mb2+2));
+ temp = temp /(nb+2);
+ dclk = temp/(pb1*pb2);
+
+ /* dclk = temp * ref_freq; */
+ /* FIXME: This is a workaround to get dclk. We are supposed
+ * to be calculating this based on the formula, but DPLL
+ * is somehow locked and does not return the programmed
+ * p1 value. Once this is fixed, we no longer need to have
+ * igd_display_handle in the parameter of get_pipe_info
+ */
+ if (NULL != display) {
+ /*igd_display_context_t *display_context =
+ (igd_display_context_t *) display;*/
+
+ /* dclk = ref_freq * m / (p1 * p2); */
+
+ /* PIPE(display)->dclk is in KHhz */
+ dclk = PIPE(display)->dclk * 1000;
+
+ } else {
+ dclk = 0;
+ }
+
+
+ if( (dclk == 0) || (ref_freq == 0) ) {
+ EMGD_ERROR("Dot Clock/Ref Frequency is Zero!!!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Ref frequency = %lu", ref_freq);
+ EMGD_DEBUG("Pipe B constructed Dot clock is = %lu", dclk);
+ timing[1].dclk = dclk/1000; /* Make it to KHz */
+ EMGD_DEBUG("Pipe B Dot clock in KHz = %lu", timing[1].dclk);
+
+ timing[1].refresh = (unsigned short) (dclk/
+ ((timing[1].htotal+1)*(timing[1].vtotal+1)));
+
+ EMGD_DEBUG("Pipe B refresh = %u", timing[1].refresh);
+ } /* if DPLL B active */
+ } /* dot clock code block */
+ } /* if Pipe B is active */
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param void
+ *
+ * @return 0
+ */
+static int get_port_info_plb(void)
+{
+ /* TODO: Any port related info that needs to be populated ? */
+ EMGD_TRACE_ENTER;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+/*******************************************************************************
+ *
+ * The following code provides VBlank interrupt support both within and without
+ * the EMGD HAL.
+ *
+ ******************************************************************************/
+
+/*!
+ * Interrupt handler for VBlanks.
+ *
+ * @param irq (IN). Unused.
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return A value to tell the kernel whether or not we handled the interrupt.
+ */
+static irqreturn_t interrupt_handler_plb(int irq, void* mmio)
+{
+ unsigned long iir;
+ unsigned long lock_flags;
+ unsigned long tmp;
+ unsigned long port2_interrupt = 0;
+ unsigned long port4_interrupt = 0;
+ emgd_vblank_callback_t *cb;
+
+ EMGD_TRACE_ENTER;
+
+
+ iir = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+
+ /* Detect whether a vblank interrupt occured, and if so, what type of
+ * processing is needed (do the simple processing now):
+ */
+ spin_lock_irqsave(&vblank_lock_plb, lock_flags);
+ if ((port2_interrupt = iir & BIT7 /* Port 2/Pipe A/SDVO-B */) != 0) {
+ if ((tmp = vblank_interrupt_state & VBLANK_INT4_PORT2) != 0) {
+ /* Record "answers" for all requestors: */
+ vblank_interrupt_state |= VBINT_ANSWER4_REQUEST(tmp);
+ }
+ }
+ if ((port4_interrupt = iir & BIT5 /* Port 4/Pipe B/Int-LVDS */) != 0) {
+ if ((tmp = vblank_interrupt_state & VBLANK_INT4_PORT4) != 0) {
+ /* Record "answers" for all requestors: */
+ vblank_interrupt_state |= VBINT_ANSWER4_REQUEST(tmp);
+ }
+ }
+ spin_unlock_irqrestore(&vblank_lock_plb, lock_flags);
+
+
+ if (port4_interrupt) {
+ if (mode_context->batch_blits[IGD_PORT_TYPE_LVDS - 1]) {
+ notify_userspace_vblank(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_LVDS);
+ }
+ }
+ else if (port2_interrupt) {
+ if (mode_context->batch_blits[IGD_PORT_TYPE_SDVOB - 1]) {
+ notify_userspace_vblank(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_SDVOB);
+ }
+ }
+
+ /* Call any registered/enabled callbacks for this interrupt: */
+ cb = &interrupt_callbacks_plb[2];
+ if (port2_interrupt && cb->callback &&
+ (vblank_interrupt_state & VBINT_ANSWER(VBINT_CB, VBINT_PORT2))) {
+ /* Clear the state to indicate the vblank has occured prior to
+ * invoking the callback.
+ */
+ vblank_interrupt_state &= ~VBINT_ANSWER(VBINT_CB, VBINT_PORT2);
+ cb->callback(cb->priv);
+ }
+ cb = &interrupt_callbacks_plb[4];
+ if (port4_interrupt && cb->callback &&
+ (vblank_interrupt_state & VBINT_ANSWER(VBINT_CB, VBINT_PORT4))) {
+ /* Clear the state to indicate the vblank has occured prior to
+ * invoking the callback.
+ */
+ vblank_interrupt_state &= ~VBINT_ANSWER(VBINT_CB, VBINT_PORT4);
+ cb->callback(cb->priv);
+ }
+
+ /* Clear interrupt status registers: */
+ if (port2_interrupt || port4_interrupt) {
+ /* Clear the corresponding bits in the PIPE{A|B}_STAT register(s): */
+ if (port2_interrupt) {
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS), EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ }
+ if (port4_interrupt) {
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS), EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ }
+
+ /* Clear the corresponding bits in the IIR register: */
+ EMGD_WRITE32((port2_interrupt | port4_interrupt), EMGD_MMIO(mmio)+IIR);
+
+
+ EMGD_DEBUG("EXIT--IRQ_HANDLED");
+ return IRQ_HANDLED;
+ } else {
+ EMGD_DEBUG("EXIT--IRQ_NONE");
+ return IRQ_NONE;
+ }
+}
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to request VBlank interrupts for a particular purpose & port.
+ * Based upon the outstanding requests, this function decides whether to
+ * touch registers, register the interrupt handler, etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+int request_vblanks_plb(unsigned long request_for, unsigned char *mmio)
+{
+ unsigned long lock_flags;
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: request_for=0x%lx, mmio=0x%p", request_for, mmio);
+
+ /* Perform error checking--ensure a valid bit was set: */
+ if (!(request_for & (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4))) {
+ EMGD_ERROR_EXIT("Invalid parameter, request_for=0x%lx",
+ request_for);
+ return -1;
+ }
+
+ /* If we're just enabling interrupts, register the interrupt handler: */
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ struct drm_device *drm_device = mode_context->context->drm_dev;
+
+ EMGD_DEBUG("Registering interrupt_handler_plb()");
+ if (request_irq(drm_device->pdev->irq, interrupt_handler_plb,
+ IRQF_SHARED, EMGD_DRIVER_NAME, mmio)) {
+ EMGD_ERROR_EXIT("Failed to register interrupt_handler_plb()");
+ return -1;
+ } else {
+ EMGD_DEBUG("Successfully registered interrupt_handler_plb()");
+ }
+ }
+
+ /* Lock here to stop the interrupt handler until after changing bits: */
+ spin_lock_irqsave(&vblank_lock_plb, lock_flags);
+
+ /* Enable interrupts for the requested purpose/port, actually touching the
+ * hardware registers if newly enabling interrupts for the given port/pipe:
+ */
+ if (request_for & VBLANK_INT4_PORT2) {
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT2) {
+ /* 1. Change Pipe Display Status Register for this pipe: set the
+ * Vertical Blank Interrupt Enable bit & clear (by setting) the
+ * Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS_EN | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+
+ /* 2. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IIR);
+
+ /* 3. Clear the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp & (~BIT7)), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Set the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IER);
+ }
+ vblank_interrupt_state |= request_for;
+ vblank_interrupt_ref_cnt_port2++;
+ } else /* if (request_for & VBLANK_INT4_PORT4) */ {
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT4) {
+ /* 1. Change Pipe Display Status Register for this pipe: set the
+ * Vertical Blank Interrupt Enable bit & clear (by setting) the
+ * Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS_EN | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+
+ /* 2. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IIR);
+
+ /* 3. Clear the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp & (~BIT5)), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Set the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IER);
+ }
+ vblank_interrupt_state |= request_for;
+ vblank_interrupt_ref_cnt_port4++;
+ }
+
+ /* Unlock to allow the interrupt handler to proceed: */
+ spin_unlock_irqrestore(&vblank_lock_plb, lock_flags);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to end a previous request VBlank interrupts for a particular
+ * purpose & port. Based upon the outstanding requests, this function
+ * decides whether to touch registers, unregister the interrupt handler,
+ * etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+int end_request_plb(unsigned long request_for, unsigned char *mmio)
+{
+ unsigned long lock_flags;
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: request_for=0x%lx, mmio=0x%p", request_for, mmio);
+
+ /* Perform error checking--ensure a valid bit was set: */
+ if (!(request_for & (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4)) ||
+ !(vblank_interrupt_state & request_for)) {
+ EMGD_ERROR_EXIT("Invalid parameter, request_for=0x%lx", request_for);
+ return -1;
+ }
+
+ /* Lock here to stop the interrupt handler until after changing bits: */
+ spin_lock_irqsave(&vblank_lock_plb, lock_flags);
+
+ /* Disable interrupts for the requested purpose/port, actually touching the
+ * hardware registers no software wants interrupts for the given port/pipe:
+ */
+ if (request_for & VBLANK_INT4_PORT2) {
+ /* Decrement reference count */
+ vblank_interrupt_ref_cnt_port2--;
+ if (0 > vblank_interrupt_ref_cnt_port2) {
+ EMGD_DEBUG("WARNING: Disabled vblank INT too many times.");
+ vblank_interrupt_ref_cnt_port2 = 0;
+ }
+
+ if (0 == vblank_interrupt_ref_cnt_port2) {
+ /* Turn off both the request and the answer bits: */
+ tmp = request_for & VBLANK_INT4_PORT2;
+ vblank_interrupt_state &= ~(tmp | VBINT_ANSWER4_REQUEST(tmp));
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT2) {
+ /* 1. Change Pipe Display Status Register for this pipe: clear
+ * the Vertical Blank Interrupt Enable bit & clear (by
+ * setting) the Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ /* Clear bits that are written by a 1, so don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32(((tmp & (~VBLANK_STS_EN)) | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+
+ /* 2. Clear the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp & (~BIT7)), EMGD_MMIO(mmio) + IER);
+
+ /* 3. Set the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IIR);
+ }
+ }
+ }
+
+ if (request_for & VBLANK_INT4_PORT4) {
+ /* Decrement reference count */
+ vblank_interrupt_ref_cnt_port4--;
+ if (0 > vblank_interrupt_ref_cnt_port4) {
+ EMGD_DEBUG("WARNING: Disabled vblank INT too many times.");
+ vblank_interrupt_ref_cnt_port4 = 0;
+ }
+
+ if (0 == vblank_interrupt_ref_cnt_port4) {
+ /* Turn off both the request and the answer bits: */
+ tmp = request_for & VBLANK_INT4_PORT4;
+ vblank_interrupt_state &= ~(tmp | VBINT_ANSWER4_REQUEST(tmp));
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT4) {
+ /* 1. Change Pipe Display Status Register for this pipe: clear
+ * the Vertical Blank Interrupt Enable bit & clear (by
+ * setting the Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ /* Clear bits that are written by a 1, so don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32(((tmp & (~VBLANK_STS_EN)) | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+
+ /* 2. Clear the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp & (~BIT5)), EMGD_MMIO(mmio) + IER);
+
+ /* 3. Set the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IIR);
+ }
+ }
+ }
+
+ /* Unlock to allow the interrupt handler to proceed: */
+ spin_unlock_irqrestore(&vblank_lock_plb, lock_flags);
+
+ /* If we've completely disabled all causes for interrupts, unregister the
+ * interrupt handler:
+ */
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ struct drm_device *drm_device = mode_context->context->drm_dev;
+
+ EMGD_DEBUG("Unregistering interrupt_handler_plb()");
+ free_irq(drm_device->pdev->irq, mmio);
+ EMGD_DEBUG("Successfully unregistered interrupt_handler_plb()");
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to check whether a requested VBlank interrupt occured.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @return Non-zero if the requested VBlank occured, zero if not.
+ */
+int vblank_occured_plb(unsigned long request_for)
+{
+ return (vblank_interrupt_state & VBINT_ANSWER4_REQUEST(request_for));
+}
+
+/*!
+ * Registers a VBlank interrupt callback function (and its parameter) to
+ * call when a VBlank interrupt occurs for a given port.
+ *
+ * @param callback (IN). A callback (function pointer) to a non-HAL
+ * function that processes a VBlank interrupt.
+ *
+ * @param priv (IN). An opaque pointer to a non-HAL data structure.
+ * This pointer is passed as a parameter of the callback function.
+ *
+ * @param port_number (IN). The EMGD port number to register a VBlank
+ * interrupt callback for.
+ *
+ * @return A handle that uniquely identifies this callback/port
+ * combination, or NULL if a failure.
+ */
+emgd_vblank_callback_h register_vblank_callback_plb(
+ emgd_process_vblank_interrupt_t callback,
+ void *priv,
+ unsigned long port_number)
+{
+ EMGD_TRACE_ENTER;
+
+ if (!callback || !priv ||
+ !((port_number == 2) || (port_number == 4))) {
+ EMGD_ERROR_EXIT("Invalid parameter amongst the following:\n"
+ " process_interrupt=0x%p, priv=0x%p, port_number=%lu",
+ callback, priv, port_number);
+ return NULL;
+ }
+
+ interrupt_callbacks_plb[port_number].callback = callback;
+ interrupt_callbacks_plb[port_number].priv = priv;
+
+ EMGD_TRACE_EXIT;
+ return &interrupt_callbacks_plb[port_number];
+}
+
+/*!
+ * Unregisters a previously-registered VBlank interrupt callback function
+ * for a given port.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies the VBlank
+ * interrupt callback to unregister.
+ */
+void unregister_vblank_callback_plb(emgd_vblank_callback_h callback_h)
+{
+ emgd_vblank_callback_t *cb = (emgd_vblank_callback_t *) callback_h;
+
+ EMGD_TRACE_ENTER;
+
+ cb->callback = NULL;
+ cb->priv = NULL;
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * Enable delivering VBlank interrupts to the callback function for the
+ * registered callback/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to enable.
+ *
+ * @return Zero if successful, non-zero if a failure.
+ */
+int enable_vblank_callback_plb(emgd_vblank_callback_h callback_h)
+{
+ emgd_vblank_callback_t *cb = (emgd_vblank_callback_t *) callback_h;
+ unsigned long enable_for = VBINT_REQUEST(VBINT_CB,
+ (cb->port_number == 2) ? VBINT_PORT2 : VBINT_PORT4);
+ unsigned char* mmio =
+ EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: callback_h=0x%p", callback_h);
+
+ ret = request_vblanks_plb(enable_for, mmio);
+
+ EMGD_DEBUG("Return %d", ret);
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ * Disable delivering VBlank interrupts to the callback function for the
+ * registered function/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to disable.
+ */
+void disable_vblank_callback_plb(emgd_vblank_callback_h callback_h)
+{
+ unsigned long lock_flags;
+ unsigned long enable_for;
+ unsigned char* mmio =
+ EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: callback_h=0x%p", callback_h);
+
+ if (callback_h == ALL_PORT_CALLBACKS) {
+ /* Need to do some push-ups in order to get interrupts disabled: */
+ spin_lock_irqsave(&vblank_lock_plb, lock_flags);
+ enable_for = (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4);
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ /* Nothing has enabled interrupts, so there's no interrupt handler
+ * to unregister. Therefore, use a special value to prevent that:
+ */
+ vblank_interrupt_state = (VBLANK_INT4_PORT2 |
+ VBLANK_INT4_PORT4 | VBLANK_DISABLE_HW_ONLY);
+ } else {
+ vblank_interrupt_state = (VBLANK_INT4_PORT2 |
+ VBLANK_INT4_PORT4);
+ }
+ spin_unlock_irqrestore(&vblank_lock_plb, lock_flags);
+
+ end_request_plb(enable_for, mmio);
+
+ spin_lock_irqsave(&vblank_lock_plb, lock_flags);
+ vblank_interrupt_state = 0;
+ spin_unlock_irqrestore(&vblank_lock_plb, lock_flags);
+ } else {
+ emgd_vblank_callback_t *cb =
+ (emgd_vblank_callback_t *) callback_h;
+ enable_for = VBINT_REQUEST(VBINT_CB,
+ (cb->port_number == 2) ? VBINT_PORT2 : VBINT_PORT4);
+
+ end_request_plb(enable_for, mmio);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * checks if the port is enabled
+ */
+unsigned long get_port_control_plb(unsigned long port_num, unsigned long port_reg)
+{
+ unsigned long port_value=0;
+ unsigned char* mmio = NULL;
+
+ EMGD_TRACE_ENTER;
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ port_value = EMGD_READ32(mmio+port_reg);
+
+ EMGD_TRACE_EXIT;
+ return port_value;
+}
+
+mode_full_dispatch_t mode_full_dispatch_plb = {
+ igd_alter_cursor_pos_plb,
+ igd_set_palette_entries_plb,
+ igd_wait_vsync_plb,
+ igd_query_in_vblank_plb,
+ igd_get_scanline_plb,
+ set_display_base_plb,
+ program_cursor_plb,
+ set_color_correct_plb,
+ igd_get_surface_plb,
+ igd_set_surface_plb,
+ igd_query_event_plb,
+ set_flip_pending_plb,
+ check_flip_pending_plb,
+ get_plane_info_plb,
+ get_pipe_info_plb,
+ get_port_info_plb,
+ register_vblank_callback_plb,
+ unregister_vblank_callback_plb,
+ enable_vblank_callback_plb,
+ disable_vblank_callback_plb,
+ request_vblanks_plb,
+ end_request_plb,
+ vblank_occured_plb,
+ get_port_control_plb,
+};
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
new file mode 100644
index 0000000..0c42d29
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
@@ -0,0 +1,47 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_plb.h
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#ifdef CONFIG_PLB
+
+typedef struct _mode_data_plb {
+ unsigned long plane_a_preserve;
+ unsigned long plane_b_c_preserve;
+ unsigned long pipe_preserve;
+ unsigned long port_preserve;
+ unsigned long fw_blc1;
+ unsigned long fw_blc2;
+ unsigned long fw_blc3;
+ unsigned long fw_self;
+ unsigned long mem_mode;
+ unsigned long dsp_arb;
+}mode_data_plb_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
new file mode 100644
index 0000000..8e58723
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
@@ -0,0 +1,1184 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: clocks_tnc.c
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Clock programming for Atom E6xx
+ * program clocks used for LVDS port based on Lincroft
+ * program clocks used for SDVO port based on Atom E6xx overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+#include <sched.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+
+#include <context.h>
+#include <dsp.h>
+#include <utils.h>
+#include <mode.h>
+#include <pi.h>
+#include <intelpci.h>
+#include "drm_emgd_private.h"
+
+#include <tnc/regs.h>
+
+#include <tnc/igd_tnc_wa.h> /* needed for vbios for register defines */
+
+#ifdef CONFIG_DEBUG
+#define FLAG(a) a
+/* Debug flag to turn off CDVO reset sequence */
+static int flag_enable_cdvo_reset = 1;
+#else
+/* Turn all workaround for release driver */
+#define FLAG(a) 1
+#endif
+
+extern unsigned long get_port_type(int crtc_id);
+static void wait_dpll(void);
+
+int program_cdvo_tnc(void);
+static int kms_program_cdvo(emgd_crtc_t *emgd_crtc);
+
+static cdvo_regs_t cdvo_reset[] = {
+ /*turn off the SDVO port*/
+ {0x61140, 0},
+ /*turn off the stall register*/
+ {0x6102C, 0},
+ /*disable SDVO*/
+ {0x61170, 0},
+ /*programmable cdvo stall*/
+ {0x6102c, 0xf},
+ {0x7000, 0x40},
+ /*reset*/
+ {0x7000, 0x51},
+ {0x7000, 0x50},
+ /*High*/
+ {0x7014, 0x00004800},
+ /*strobe data tuning default*/
+ {0x700c, 0x000BB4FF},
+ /*enable sdvo*/
+ {0x61170, 0x20022160},
+ {0x7010, 0x06000200},
+ /* -- Begin Sequence of 3 pixel signal --*/
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*reset*/
+ {0x7000, 0x51},
+ {0x7000, 0x50},
+ /*High*/
+ {0x7014, 0x00004800},
+ /*strobe data tuning default*/
+ {0x700c, 0x000BB4FF},
+ /*enable sdvo*/
+ {0x61170, 0x20022160},
+ {0x7010, 0x06000200},
+ /* -- Begin Sequence of 3 pixel signal --*/
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Low*/
+ {0x700c, 0x00008000},
+ {0x700c, 0x0008B400},
+ /*High*/
+ {0x700c, 0x0008B4FF},
+ /*Reset*/
+ {0x7000, 0x51},
+ {0x7000, 0x50},
+ {0x7010, 0x02000200}, /*gtl gtl*/
+ {0x7014, 0x00004000}, /*ODT*/
+ {0x61170, 0x20022160}, /*enable SDVO*/
+ {0x7010, 0x02000200}, /*gtl gtl*/
+ {0x7014, 0x00000800},
+ {0x7014, 0x00004800}, /*rcomp*/
+ {0x7014, 0x00000000},
+ {0x7000, 0x40}, /*enable cdvo*/
+ {0x7000, 0x50}, /*enable cdvo*/
+ {0x7014, 0x00004000}, /*ODT*/
+ {0x61170, 0x20022160}, /*enable SDVO*/
+ {0,0}
+};
+
+
+
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Enable this if calculated values are wrong and required fixed table */
+#define CONFIG_FIXED_TABLE 0
+
+#ifdef CONFIG_TNC
+
+extern int program_clock_sdvo_tnc(igd_display_context_t *display,
+ igd_clock_t *clock, unsigned long dclk);
+
+/*===========================================================================
+; File Global Data
+;--------------------------------------------------------------------------*/
+#if CONFIG_FIXED_TABLE
+typedef struct _fixed_clock {
+ unsigned long dclk;
+ unsigned long n;
+ unsigned long m;
+ unsigned long p1;
+} fixed_clock_t;
+
+/* set mmio register required values */
+static fixed_clock_t lvds_fixed_clock_table[] = {
+ /* Clock N M P1 */
+ { 65000, 0x01, 0x00, 0x00 },
+ { 0xffffffff, 0x01, 0x00, 0x00}
+};
+
+/* set mmio register required values */
+static fixed_clock_t sdvo_fixed_clock_table[] = {
+ /* Clock N M P1 */
+ { 65000, 0x00, 0x00, 0x00 },
+ { 0xffffffff, 0x00, 0x00, 0x00}
+};
+#endif
+
+#define LVDS_M_MIN 10
+
+/* This table is also used by mode_tnc.c */
+const unsigned long lvds_m_converts[] = {
+ 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,
+ 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,
+ 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,
+};
+
+const unsigned long LVDS_M_CONVERTS_LEN=26; /* Length of the array above*/
+
+#define TARGET_ERROR 46
+
+typedef const struct _tnc_limits {
+ unsigned long ref_freq;
+ unsigned long min_m;
+ unsigned long max_m;
+
+ unsigned long min_n;
+ unsigned long max_n;
+
+ unsigned long min_p1;
+ unsigned long max_p1;
+
+ unsigned long min_p2;
+ unsigned long max_p2;
+
+ unsigned long min_vco;
+ unsigned long max_vco;
+} tnc_limits_t;
+
+/* m, n, p value limits:
+ * source: http://moss.amr.ith.intel.com/sites/LCD/LNC/HAS/Secured
+ * %20Documents/LNC%20HAS%20work%20area/Lincroft%20DPLL_1.2_ww31_08.docx
+ *
+ * Note:
+ * VCO range for 100L is not given: so put a range big enough to go through
+ * calculations for the for loop.
+ */
+static tnc_limits_t tnc_lvds_limits[] =
+{
+ /* reffreq m n p1 p2 vco */
+ { 200000, 10, 17, 1, 1, 2, 8, 14, 14, 2000000, 3400000}, /* SKU 100 */
+ { 100000, 20, 34, 1, 1, 2, 8, 14, 14, 1000000, 3400000}, /* SKU 100L */
+ { 166000, 12, 20, 1, 1, 2, 7, 14, 14, 2000000, 3333333}, /* SKU 83 */
+};
+
+static tnc_limits_t tnc_sdvo_limits[] =
+{
+ /* reffreq m n p1 p2 vco */
+ { 96000, 80,137, 3, 7, 1, 2, 10, 10, 1400000, 2800000}, /* SDVO */
+};
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param limits
+ * @param m
+ * @param n
+ * @param p
+ * @param target_error
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_clock(unsigned long dclk,
+ unsigned long ref_freq,
+ tnc_limits_t *l,
+ unsigned long *m,
+ unsigned long *n,
+ unsigned long *p1,
+ unsigned long target_error,
+ unsigned long *actual_dclk,
+ unsigned long port_type,
+ unsigned long pd_type)
+{
+ unsigned long pdiv;
+ unsigned long target_vco, actual_freq;
+ long freq_error, min_error;
+ unsigned long dclk_10000;
+
+ unsigned long current_m, current_n, current_p1;
+
+ EMGD_TRACE_ENTER;
+
+ min_error = 100000;
+
+ *m = 0;
+ *n = 0;
+ *p1 = 0;
+
+ /* dclk * 10000, so it does not have to be calculated within the
+ * loop */
+ dclk_10000 = dclk * 10000;
+
+ for(current_m = l->min_m; current_m <= l->max_m; current_m++) {
+ for(current_n = l->min_n; current_n <= l->max_n; current_n++) {
+ for(current_p1 = l->min_p1; current_p1 <= l->max_p1; current_p1++) {
+
+ /* For both LVDS/SDVO ports min_p2 and max_p2 are same,
+ * so assign use either min/max p2 */
+ pdiv = current_p1 * l->min_p2;
+ target_vco = dclk * pdiv;
+
+ if (target_vco > l->max_vco) {
+ /* target_vco continues to increase, so start with
+ * next current_n */
+ break;
+ }
+
+ if (target_vco >= l->min_vco) {
+ /* Frequency calculations for SDVO and LVDS are different
+ * SDVO Dotclock_frequency = (Reference Frequency * (M+2)) / (N*(P1*P2))
+ * LVDS DotClk_Frequency = (ReferenceFrequency * M)/ (P1* P2)
+ * need to find a way to differentiate SDVO and LVDS
+ * Works for now but signal generated will be different */
+ actual_freq = (ref_freq * current_m) / (current_n*pdiv);
+ freq_error = 10000 - (dclk_10000 / actual_freq);
+
+ if (freq_error < -min_error) {
+ /* freq_error continues to decrease once this
+ * point is reached, so start with next
+ * current_n */
+ break;
+ }
+
+ if (freq_error < 0) {
+ freq_error = -freq_error;
+ }
+ if (freq_error < min_error) {
+ *n = current_n;
+ *m = current_m;
+ *p1 = current_p1;
+ min_error = freq_error;
+ *actual_dclk = actual_freq;
+ }
+ }
+ }
+ }
+ if (min_error == 0) {
+ break;
+ }
+ }
+
+ if (pd_type == PD_DISPLAY_TVOUT) {
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+ /*
+ * No clock found that meets error requirement
+ */
+ if (min_error > (long)target_error) {
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ EMGD_DEBUG("dclk = (ref*m)/(n*p1*p2) => %lu = (%lu*%lu)/(%lu*%lu*%lu) = %lu",
+ dclk, ref_freq, *m, *n, *p1, l->min_p2,
+ (ref_freq*(*m))/((*n)*(*p1)*l->min_p2));
+ EMGD_DEBUG("min_error:%ld", min_error);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param limits
+ * @param m
+ * @param n
+ * @param p
+ * @param target_error
+ * @param port_type
+ * @param pd_type
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int get_clock(unsigned long dclk,
+ unsigned long ref_freq,
+ tnc_limits_t *l,
+ unsigned long *m,
+ unsigned long *n,
+ unsigned long *p1,
+ unsigned long target_error,
+ unsigned long port_type,
+ unsigned long *actual_dclk,
+ unsigned long pd_type)
+{
+
+#if CONFIG_FIXED_TABLE
+ fixed_clock_t *fixed;
+ EMGD_TRACE_ENTER;
+ /* Enable this if calculated values are wrong and required fixed table */
+ if (port_type == IGD_PORT_LVDS) {
+ fixed = lvds_fixed_clock_table;
+ } else {
+ fixed = sdvo_fixed_clock_table;
+ }
+
+ /* First check for a fixed clock from the table. These are ones that
+ * can't be calculated correctly. */
+ while (fixed->dclk != 0xffffffff) {
+ if (fixed->dclk == dclk) {
+ EMGD_DEBUG("Using Fixed Clock From table for clock %ld", dclk);
+ *m = fixed->m;
+ *n = fixed->n;
+ *p1 = fixed->p1;
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+ fixed++;
+ }
+#endif
+
+ EMGD_TRACE_ENTER;
+ /* No fixed clock found so calculate one. */
+ EMGD_DEBUG("Calculating dynamic clock for clock %ld", dclk);
+
+ if (calculate_clock(dclk, ref_freq, l, m, n, p1, target_error, actual_dclk, port_type, pd_type)) {
+ /* No usable clock. Cannot use 640x480 at 60 as default, because
+ * there are several vcos and several reference clocks. */
+ EMGD_ERROR("Could not calculate clock %ld, returning default.", dclk);
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ if (pd_type == PD_DISPLAY_TVOUT) {
+ *p1 = 2;
+ *m = 100;
+ *n = 5;
+ }
+
+ /* Translate returned values to m,n,p1 register values */
+ /* No change required for *n value */
+ if (port_type == IGD_PORT_SDVO) {
+ *p1 = (1L << (*p1 - 1));
+ *m -= 2;
+ *n = (1L << (*n -1));
+ } else {
+ *p1 = (1L << (*p1 - 2));
+ *m = lvds_m_converts[*m - LVDS_M_MIN];
+ }
+
+ EMGD_DEBUG("reg m=%lu n=%lu p1=%lu p2=%lu", *m, *n, *p1, l->min_p2);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_lvds_tnc(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ struct drm_device *dev = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ unsigned long pt;
+ int ret;
+ unsigned long m, n, p1;
+ unsigned long control;
+ unsigned long ref_freq;
+ tnc_limits_t *l = NULL;
+ unsigned long count;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ pt = get_port_type(emgd_crtc->crtc_id);
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+
+
+ /* LNC ref_freq is determined by SKU, convert to KHz */
+#if 0
+ ref_freq = display->context->device_context.gfx_freq * 1000L;
+#else
+ ref_freq = context->device_context.core_freq;
+ ref_freq = ref_freq * 1000;
+#endif
+
+#if 0
+ /* Find m,n,p,vco limits */
+ if (ref_freq == 200000) {
+ l = &tnc_lvds_limits[0];
+ } else if (ref_freq == 100000) {
+ l = &tnc_lvds_limits[1];
+ } else if (ref_freq == 166000) {
+ l = &tnc_lvds_limits[2];
+ }
+#endif
+
+ for(count=0; count<3; count++){
+ if (tnc_lvds_limits[count].ref_freq == ref_freq){
+ l = &tnc_lvds_limits[count];
+ break;
+ }
+ }
+
+/* PO Debug */
+#if 0
+ /* WRITE_PORT80(0xED); */
+
+ if(ref_freq == 166000){
+ WRITE_PORT80(0xEF);
+ }
+
+ if (!l){
+ /* FATAL ERROR */
+ DEAD_LOOP(0xDD);
+ }
+#endif
+
+ /* Per UMG, there is no defined target_error for LVDS, it supposed to
+ * work for all expected dclks. */
+#if 1
+ if (port) {
+ ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, dclk /* target_error */,
+ port->port_type, &clock->actual_dclk, port->pd_driver->type);
+ } else {
+ ret = 1;
+ }
+ if (ret) {
+ EMGD_ERROR_EXIT("Clock %ld could not be programmed", dclk);
+ /* DEAD_LOOP(0xFF); */
+ return ret;
+ }
+#else
+ /* Hard code the values for now */
+ m = 0x2D; // ITP uses 0x2E, should change
+ p1 = 2;
+
+#endif
+
+#if 0
+ /* If clocks are already running at required clocks, just return */
+ if (PIPE(display)->dclk == dclk) {
+ return 0;
+ }
+#endif
+
+ /* Disable DPLL */
+#if 0
+ control = BIT28 | (1<<clock->p_shift); //Why are we shifting 1 to P1, GMA carry over???
+#else
+ control = BIT28;
+#endif
+ EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Program M */
+ EMGD_WRITE32((m<<8), context->device_context.virt_mmadr + clock->mnp);
+
+ EMGD_WRITE32((m<<8), context->device_context.virt_mmadr + 0xF044); //BUGBUG
+
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->mnp, (m<<8));
+
+ /* Enable DPLL */
+ control = (BIT31 | BIT28 | BIT27) | (p1<<clock->p_shift);
+
+/* PO Debug..*/
+#if 0
+ /* set VCO select */
+ if (ref_freq == 166000) {
+ control |= BIT16;
+ }
+#endif
+
+
+ EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Wait 150us for the DPLL to stabilize */
+ OS_SLEEP(150);
+ pipe->dclk = dclk;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_lvds_tnc(igd_display_context_t *display,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ int ret;
+ unsigned long m, n, p1;
+ unsigned long control;
+ unsigned long ref_freq;
+ igd_display_port_t *port;
+ tnc_limits_t *l = NULL;
+ unsigned long count;
+
+ EMGD_TRACE_ENTER;
+
+ port = PORT_OWNER(display);
+
+ /* LNC ref_freq is determined by SKU, convert to KHz */
+#if 0
+ ref_freq = display->context->device_context.gfx_freq * 1000L;
+#else
+ ref_freq = display->context->device_context.core_freq;
+ ref_freq = ref_freq * 1000;
+#endif
+
+#if 0
+ /* Find m,n,p,vco limits */
+ if (ref_freq == 200000) {
+ l = &tnc_lvds_limits[0];
+ } else if (ref_freq == 100000) {
+ l = &tnc_lvds_limits[1];
+ } else if (ref_freq == 166000) {
+ l = &tnc_lvds_limits[2];
+ }
+#endif
+
+ for(count=0; count<3; count++){
+ if (tnc_lvds_limits[count].ref_freq == ref_freq){
+ l = &tnc_lvds_limits[count];
+ break;
+ }
+ }
+
+/* PO Debug */
+#if 0
+ /* WRITE_PORT80(0xED); */
+
+ if(ref_freq == 166000){
+ WRITE_PORT80(0xEF);
+ }
+
+ if (!l){
+ /* FATAL ERROR */
+ DEAD_LOOP(0xDD);
+ }
+#endif
+
+ /* Per UMG, there is no defined target_error for LVDS, it supposed to
+ * work for all expected dclks. */
+#if 1
+ ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, dclk /* target_error */,
+ port->port_type, &clock->actual_dclk, port->pd_driver->type);
+ if (ret) {
+ EMGD_ERROR_EXIT("Clock %ld could not be programmed", dclk);
+ /* DEAD_LOOP(0xFF); */
+ return ret;
+ }
+#else
+ /* Hard code the values for now */
+ m = 0x2D; // ITP uses 0x2E, should change
+ p1 = 2;
+
+#endif
+
+#if 0
+ /* If clocks are already running at required clocks, just return */
+ if (PIPE(display)->dclk == dclk) {
+ return 0;
+ }
+#endif
+
+ /* Disable DPLL */
+#if 0
+ control = BIT28 | (1<<clock->p_shift); //Why are we shifting 1 to P1, GMA carry over???
+#else
+ control = BIT28;
+#endif
+ WRITE_MMIO_REG(display, clock->dpll_control, control);
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Program M */
+ WRITE_MMIO_REG(display, clock->mnp, (m<<8));
+
+ WRITE_MMIO_REG(display, 0xF044, (m<<8)); //BUGBUG
+
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->mnp, (m<<8));
+
+ /* Enable DPLL */
+ control = (BIT31 | BIT28 | BIT27) | (p1<<clock->p_shift);
+
+/* PO Debug..*/
+#if 0
+ /* set VCO select */
+ if (ref_freq == 166000) {
+ control |= BIT16;
+ }
+#endif
+
+
+ WRITE_MMIO_REG(display, clock->dpll_control, control);
+ EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Wait 150us for the DPLL to stabilize */
+ OS_SLEEP(150);
+ PIPE(display)->dclk = dclk;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_sdvo_tnc(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ struct drm_device *dev = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ unsigned long pt;
+ int ret;
+ unsigned long m, n, p1;
+ unsigned long control;
+ unsigned long ref_freq;
+ unsigned long port_mult, vga_mult;
+ unsigned long target_error, actual_dclk;
+ tnc_limits_t *l;
+
+ EMGD_DEBUG("Enter program_clock");
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ pt = get_port_type(emgd_crtc->crtc_id);
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+ if (!port) {
+ EMGD_ERROR_EXIT("No port");
+ return -1;
+ }
+
+ /* FIXME: No info available in EAS and waiting for info. */
+ if (dclk > 100000) { /* 100-200 MHz */
+ port_mult = 1;
+ } else if (dclk > 50000) { /* 50-100 Mhz */
+ port_mult = 2;
+ } else { /* 25-50 Mhz */
+ port_mult = 4;
+ }
+
+ dclk *= port_mult;
+
+ l = &tnc_sdvo_limits[0];
+ ref_freq = l->ref_freq;
+
+ vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control) & 0x3;
+
+ target_error = TARGET_ERROR;
+
+ /* For external clock sources always use ref_clock == dclk */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ref_freq = dclk;
+ /* When clock source sdvo device, allowed error is 0. */
+ target_error = 0;
+ }
+
+ if (port) {
+ ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, target_error,
+ IGD_PORT_SDVO, &actual_dclk, port->pd_driver->type);
+ } else {
+ ret = 1;
+ }
+
+ clock->actual_dclk = actual_dclk/port_mult;
+
+ if (ret) {
+ EMGD_ERROR("Clock %ld could not be programmed", dclk);
+ return ret;
+ }
+
+ /* Disable DPLL, Write 2 into P for saftey */
+ control = BIT28 | (2<<clock->p_shift) | vga_mult;
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Program N, M */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->mnp, (n<<16) | m);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->mnp, (n<<16)|m);
+
+ /* Enable DPLL, Disable VGA mode and sitck in new P values */
+ control = BIT31 | BIT30 | BIT28 | (p1<<clock->p_shift) | vga_mult;
+
+ /* Set the clock source correctly based on PD settings */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ control |= port->clock_bits;
+ }
+
+ /* sDVO Multiplier bits[7:0] */
+ if (port_mult == 2) {
+ control |= (1 << 4);
+ } else if (port_mult == 3) {
+ control |= (2 << 4);
+ } else if (port_mult == 4) {
+ control |= (3 << 4);
+ }
+
+ /* Double buffered */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* We must wait for 150 us for the dpll clock to warm up */
+ //OS_SLEEP(150);
+ wait_dpll();
+
+ kms_program_cdvo(emgd_crtc);
+
+ return 0;
+}
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_sdvo_tnc(igd_display_context_t *display,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ int ret;
+ unsigned long m, n, p1;
+ unsigned long control;
+ unsigned long ref_freq;
+ unsigned long port_mult, vga_mult;
+ unsigned long target_error, actual_dclk;
+ igd_display_port_t *port;
+ tnc_limits_t *l;
+
+ EMGD_DEBUG("Enter program_clock");
+
+ port = PORT_OWNER(display);
+
+ /* FIXME: No info available in EAS and waiting for info. */
+ if (dclk > 100000) { /* 100-200 MHz */
+ port_mult = 1;
+ } else if (dclk > 50000) { /* 50-100 Mhz */
+ port_mult = 2;
+ } else { /* 25-50 Mhz */
+ port_mult = 4;
+ }
+
+ dclk *= port_mult;
+
+ l = &tnc_sdvo_limits[0];
+ ref_freq = l->ref_freq;
+
+ vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control) & 0x3;
+
+ target_error = TARGET_ERROR;
+
+ /* For external clock sources always use ref_clock == dclk */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ ref_freq = dclk;
+ /* When clock source sdvo device, allowed error is 0. */
+ target_error = 0;
+ }
+
+ ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, target_error,
+ IGD_PORT_SDVO, &actual_dclk, port->pd_driver->type);
+
+ clock->actual_dclk = actual_dclk/port_mult;
+
+ if (ret) {
+ EMGD_ERROR("Clock %ld could not be programmed", dclk);
+ return ret;
+ }
+
+ /* Disable DPLL, Write 2 into P for saftey */
+ control = BIT28 | (2<<clock->p_shift) | vga_mult;
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* Program N, M */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->mnp, (n<<16) | m);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->mnp, (n<<16)|m);
+
+ /* Enable DPLL, Disable VGA mode and sitck in new P values */
+ control = BIT31 | BIT30 | BIT28 | (p1<<clock->p_shift) | vga_mult;
+
+ /* Set the clock source correctly based on PD settings */
+ if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+ control |= port->clock_bits;
+ }
+
+ /* sDVO Multiplier bits[7:0] */
+ if (port_mult == 2) {
+ control |= (1 << 4);
+ } else if (port_mult == 3) {
+ control |= (2 << 4);
+ } else if (port_mult == 4) {
+ control |= (3 << 4);
+ }
+
+ /* Double buffered */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+ EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+ clock->dpll_control, control);
+
+ /* We must wait for 150 us for the dpll clock to warm up */
+ //OS_SLEEP(150);
+ wait_dpll();
+
+ program_cdvo_tnc();
+
+ return 0;
+}
+
+int kms_program_clock_tnc(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ EMGD_TRACE_ENTER;
+
+ if (get_port_type(emgd_crtc->crtc_id) == IGD_PORT_LVDS) {
+ EMGD_TRACE_EXIT;
+ return kms_program_clock_lvds_tnc(emgd_crtc, clock, dclk);
+ } else {
+ EMGD_TRACE_EXIT;
+ return kms_program_clock_sdvo_tnc(emgd_crtc, clock, dclk);
+ }
+}
+
+int program_clock_tnc(igd_display_context_t *display,
+ igd_clock_t *clock,
+ unsigned long dclk)
+{
+ EMGD_TRACE_ENTER;
+
+ if (PORT_TYPE(display) == IGD_PORT_LVDS) {
+ EMGD_TRACE_EXIT;
+ return program_clock_lvds_tnc(display, clock, dclk);
+ } else {
+ EMGD_TRACE_EXIT;
+ return program_clock_sdvo_tnc(display, clock, dclk);
+ }
+}
+
+
+/*!
+ * Poll for DPLL register lock. This is only valid for DPLLB
+ *
+ * @return void
+ */
+static void wait_dpll(void)
+{
+#ifndef CONFIG_MICRO
+ unsigned long temp;
+ os_alarm_t timeout;
+
+ EMGD_TRACE_ENTER;
+
+ /* Wait for DPLL lock, about 50 msec (20Hz). */
+ timeout = OS_SET_ALARM(50);
+ do {
+ OS_SCHEDULE();
+ /* Check for Bit16, 1 means DPLL is locked (TNC EAS Ver 2.0) */
+ temp = (READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x606C) & 0x10000) >> 16;
+
+ /* Check for timeout */
+ } while ((!temp) && (!OS_TEST_ALARM(timeout)));
+
+ if (!temp) {
+ EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable");
+ }
+
+ EMGD_TRACE_EXIT;
+#else
+ /* to save space in VBIOS, we use to old method of waiting for the DPLL
+ * to warm up */
+ OS_SLEEP(150);
+#endif
+ return;
+}
+
+
+/* This is the initialization code for B0 stepping */
+static int kms_program_cdvo(emgd_crtc_t *emgd_crtc)
+{
+ int counter = 0;
+ igd_display_pipe_t *pipe = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+
+ #ifndef CONFIG_MICRO
+ /*
+ * CDVO reset has been done. Check that offset 0x7000 has the value 0x50
+ * and this would mean that reset has been done. We only need to do cdvo
+ * reset once per warm reset
+ */
+ if((READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) == 0x50) ||
+ !FLAG(flag_enable_cdvo_reset)){
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+
+ #endif
+
+ /* pipe_temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg); */
+
+ /* Disable pipe */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg, 0);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, pipe->pipe_reg, 0);
+
+ /* Sleep for a while to wait for the pipe to disable. There are no
+ * status bits to check if pipe B has been enable */
+ OS_SLEEP(25);
+
+ #if 0
+ /* Disable DPLL */
+ vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control) & 0x3;
+ control = BIT28 | (2<<PIPE(display)->clock_reg->p_shift) | vga_mult;
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control, control);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control, control);
+ #endif
+
+ /* the checking is needed for VBIOS but not needed for driver */
+ do{
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, cdvo_reset[counter].reg,
+ cdvo_reset[counter].value);
+ counter++;
+ }while(cdvo_reset[counter].reg != 0);
+
+ /* Enable sDVOB port */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140,
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140) | 0xC0000018 );
+
+
+ EMGD_TRACE_EXIT;
+
+ return TRUE;
+}
+
+/* This is the initialization code for B0 stepping */
+int program_cdvo_tnc(void)
+{
+ int counter = 0;
+ unsigned long pipe_temp;
+
+ EMGD_TRACE_ENTER;
+
+ #ifndef CONFIG_MICRO
+ /*
+ * CDVO reset has been done. Check that offset 0x7000 has the value 0x50
+ * and this would mean that reset has been done. We only need to do cdvo
+ * reset once per warm reset
+ */
+ if((READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) == 0x50) ||
+ !FLAG(flag_enable_cdvo_reset)){
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+
+ #endif
+
+ pipe_temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF);
+
+ /* Disable pipe */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPEB_CONF, 0);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF, 0);
+
+ /* Sleep for a while to wait for the pipe to disable. There are no
+ * status bits to check if pipe B has been enable */
+ OS_SLEEP(25);
+
+#if 0
+ /* Disable DPLL */
+ vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control) & 0x3;
+ control = BIT28 | (2<<PIPE(display)->clock_reg->p_shift) | vga_mult;
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control, control);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PIPE(display)->clock_reg->dpll_control, control);
+#endif
+
+ /* the checking is needed for VBIOS but not needed for driver */
+ do{
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, cdvo_reset[counter].reg,
+ cdvo_reset[counter].value);
+ counter++;
+ }while(cdvo_reset[counter].reg != 0);
+
+ /* Enable sDVOB port */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140,
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140) | 0xC0000018 );
+
+ /* Restore Pipe B configuration value */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPEB_CONF, pipe_temp);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF, pipe_temp);
+
+ EMGD_TRACE_EXIT;
+
+ return TRUE;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
new file mode 100644
index 0000000..4f3e672
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
@@ -0,0 +1,1746 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: kms_mode_tnc.c
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <igd_pwr.h>
+#include <utils.h>
+#include <vga.h>
+#include <pi.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/mi.h>
+#include <tnc/instr.h>
+#include <tnc/igd_tnc_wa.h>
+#include "drm_emgd_private.h"
+
+#include "../cmn/mode_dispatch.h"
+#include "../cmn/match.h"
+#include "mode_tnc.h"
+#include <math_fix.h>
+#include <memory.h>
+
+
+/*------------------------------------------------------------------------------
+ * Function Prototypes
+ *----------------------------------------------------------------------------*/
+int kms_mode_get_stride_stereo_tnc(igd_display_pipe_t *pipe,
+ igd_display_plane_t *plane,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags);
+void kms_program_pipe_vga_tnc(emgd_crtc_t *emgd_crtc);
+static void kms_program_pipe_tnc(emgd_crtc_t *emgd_crtc);
+static void kms_set_pipe_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static void kms_program_plane_tnc(emgd_crtc_t *emgd_crtc, unsigned long status);
+static void kms_set_plane_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static int kms_program_port_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+static int kms_program_port_lvds_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+static int kms_program_port_sdvo_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+static int kms_post_program_port_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status);
+static u32 kms_get_vblank_counter_tnc(emgd_crtc_t *emgd_crtc);
+
+
+static int set_color_correct_tnc(emgd_crtc_t *emgd_crtc);
+
+extern unsigned long get_port_type(int crtc_id);
+extern void wait_pipe(unsigned long pt, unsigned long pipe_reg, unsigned long check_on_off);
+extern void disable_vga_tnc (unsigned char *mmio);
+extern int write_bunit_tnc(unsigned long reg, unsigned long val);
+extern int read_bunit_tnc(unsigned long reg, unsigned long *val);
+extern int kms_program_clock_tnc(emgd_crtc_t *emgd_crtc,
+ igd_clock_t *clock, unsigned long dclk);
+extern int wait_for_vblank_tnc(unsigned long pipe_reg);
+extern void initialize_ST_bridge(igd_context_t *context,
+ igd_display_port_t *port);
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *----------------------------------------------------------------------------*/
+extern int flag_basic_htotal_formula_wa;
+extern int flag_turn_off_port_wa;
+extern int flag_enable_tuning_wa;
+extern unsigned long ports_tnc[2];
+extern int vphase;
+extern tnc_wa_timing_t tune;
+extern mode_data_tnc_t device_data_tnc[1];
+
+
+/*------------------------------------------------------------------------------
+ * KMS Dispatch Table
+ *----------------------------------------------------------------------------*/
+mode_kms_dispatch_t mode_kms_dispatch_tnc = {
+ kms_program_pipe_tnc,
+ kms_set_pipe_pwr_tnc,
+ kms_program_plane_tnc,
+ kms_set_plane_pwr_tnc,
+ kms_program_port_tnc,
+ kms_post_program_port_tnc,
+ kms_get_vblank_counter_tnc,
+ kms_match_mode,
+};
+
+
+
+/*!
+ * Get the stride and stereo values based on the display.
+ *
+ * @param plane Pointer to hardware device instance data
+ * @param pipe Pointer to hardware device instance data
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int kms_mode_get_stride_stereo_tnc(igd_display_pipe_t *pipe,
+ igd_display_plane_t *plane,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags)
+{
+ unsigned long pitch = plane->fb_info->screen_pitch;
+ igd_timing_info_t *timing = pipe->timing;
+ unsigned long base_offset;
+
+ EMGD_TRACE_ENTER;
+
+ base_offset = plane->fb_info->visible_offset;
+ *stride = pitch;
+ *stereo = 0;
+
+ /* For field replication, valid for interlaced modes only
+ * set stereo = fb_base
+ * stride = pitch
+ */
+ if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+ if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* Interlaced + Line double flags means field replication.
+ * same lines are sent for both fields. Program the
+ * second eye to be same as the first
+ */
+ *stereo = base_offset;
+ } else {
+ /* Regular interlaced. Second eye starts on line 2.
+ * Skip every other line.
+ */
+ *stereo = base_offset + pitch;
+ *stride = pitch << 1;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_tnc(emgd_crtc_t *emgd_crtc)
+{
+ const int MID_PIXEL_VAL = 125;
+ const int MAX_PIXEL_VAL = 255;
+ const int NUM_PALETTE_ENTRIES = 256;
+
+ igd_display_port_t *port = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+
+ unsigned int gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+ unsigned int gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+ unsigned int gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+ unsigned int new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+ unsigned int new_gamma_b_24i_8f;
+ unsigned int gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ int brightness_factor_r, brightness_factor_g;
+ int brightness_factor_b;
+ int contrast_factor_r, contrast_factor_g;
+ int contrast_factor_b;
+
+ unsigned int *palette;
+ unsigned int i;
+ struct drm_device *dev = NULL;
+
+ igd_range_attr_t *gamma_attr = NULL, *contrast_attr = NULL;
+ igd_range_attr_t *brightness_attr = NULL;
+ igd_attr_t *hal_attr_list = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+ if (!port) {
+ EMGD_ERROR_EXIT("No port being used.");
+ return -IGD_ERROR_INVAL;
+ }
+ hal_attr_list = port->attributes;
+
+ /* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+ palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+ /* start with a fresh palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ palette[i] = (i << 16) | (i << 8) | i;
+ }
+
+ /* get a pointer to gamma, contrast, and brightness attr */
+ i = 0;
+
+ while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+ switch (hal_attr_list[i].id) {
+ case PD_ATTR_ID_FB_GAMMA:
+ gamma_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_BRIGHTNESS:
+ brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_CONTRAST:
+ contrast_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ default:
+ break;
+ }
+
+ i++;
+ }
+
+ if(!gamma_attr || !brightness_attr || !contrast_attr) {
+ EMGD_ERROR_EXIT("Color Correction Atrributes not found!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get the max and min */
+ gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+ gamma_g_max_24i_8f = ((gamma_attr->max >> 8) & 0xFF) << 3;
+ gamma_b_max_24i_8f = (gamma_attr->max & 0xFF) << 3;
+
+ gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+ gamma_g_min_24i_8f = ((gamma_attr->min >> 8) & 0xFF) << 3;
+ gamma_b_min_24i_8f = (gamma_attr->min & 0xFF) << 3;
+
+ /* The new gamma values are in 3i.5f format, but we must convert it
+ * to 24i.8f format before passing it to OS_POW_FIX
+ */
+ new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+ new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+ new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+ /* make sure the new gamma is within range */
+ new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+ new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+ gamma_normal_r_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+ gamma_normal_g_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+ gamma_normal_b_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ unsigned int new_gamma;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* Note that we do not try to calculate the gamma if it
+ * is 1.0, e.g. 0x100. This is to avoid round-off errors
+ */
+
+ /* red: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_r_24i_8f) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+ palette[i] &= 0x00FFFF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_g_24i_8f) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+ palette[i] &= 0xFF00FF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_b_24i_8f) {
+ cur_color = cur_palette & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+ palette[i] &= 0xFFFF00;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+ }
+ }
+
+
+ /* Brightness correction */
+ brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+ brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+ brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+ /* The factors are offset by 0x80 because 0x80 is 0 correction */
+ brightness_factor_r -= 0x80;
+ brightness_factor_g -= 0x80;
+ brightness_factor_b -= 0x80;
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_r;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+ /* green: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_g;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+ /* blue: calculate and make sure the result is within range */
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_b;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00;
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+
+
+ /* contrast correction */
+ contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+ contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+ contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+ /* make sure values are within range */
+ contrast_factor_r -= 0x80;
+ contrast_factor_g -= 0x80;
+ contrast_factor_b -= 0x80;
+
+
+ /* We're doing integer division in this loop using 16i.16f
+ * integers. The result will then be converted back into a
+ * regular, 32-bit integer
+ */
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ if (0 != contrast_factor_r ) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF; /* clear out the R color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0 != contrast_factor_g ) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF; /* clear out the G color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0 != contrast_factor_b) {
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00; /* clear out the B color */
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+ }
+
+
+ /* write the new values in the palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ /* SDVO palette register is not accesible */
+ EMGD_WRITE32(palette[i],
+ MMIO_TNC(IGD_PORT_LVDS) +
+ pipe->palette_reg + i*4);
+ }
+
+ OS_FREE(palette);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ * kms_program_pipe_vga_tnc
+ *
+ * @param emgd_crtc Pointer to our private kms crtc structure
+ *
+ * @return void
+ */
+void kms_program_pipe_vga_tnc(
+ emgd_crtc_t *emgd_crtc)
+{
+ struct drm_device *dev = NULL;
+ igd_timing_info_t *timing = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ igd_display_port_t *port = NULL;
+ unsigned long vga_control;
+ unsigned long upscale = 0;
+ int centering = 1;
+ unsigned long pt;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ /*
+ * VGA Plane can attach to only one pipe at a time. LVDS can
+ * only attach to pipe B. We need to use the display passed to
+ * determine the pipe number to use. (Napa is same as Alm).
+ */
+
+ /*
+ * We can come here with following cases:
+ * 1. magic->vga CRT, DVI type displays
+ * 2. native->vga int-lvds, and up-scaling lvds displays
+ * 3. pipe->vga TV and other unscaled-lvds displays
+ */
+ vga_control = EMGD_READ32(context->device_context.virt_mmadr + 0x71400);
+ vga_control &= 0x18e3ff00;
+ vga_control |= 0x8e;
+
+ timing = pipe->timing;
+ if(!timing->extn_ptr) {
+ EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_tnc");
+ return;
+ }
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+
+ /* Find UPSCALING attr value*/
+ pi_pd_find_attr_and_value(port,
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ /* this PI func will not modify value
+ * of upscale if attr does not exist
+ */
+ break;
+ }
+ }
+
+ /* magic->vga || native->vga cases, centering isn't required */
+ if ((timing->width == 720 && timing->height == 400) || upscale) {
+ EMGD_DEBUG("Centering = 0");
+ centering = 0;
+ }
+
+ /* Enable border */
+ if((timing->width >= 800) && !upscale) {
+ EMGD_DEBUG("Enable VGA Border");
+ vga_control |= (1L<<26);
+ }
+
+ if(timing->width == 640) {
+ EMGD_DEBUG("Enable Nine Dot Disable");
+ vga_control |= (1L<<18);
+ }
+
+ if(centering) {
+ EMGD_DEBUG("Enable VGA Center Centering");
+ vga_control |= 1L<<24;
+
+ if(timing->height >= 960) {
+ if(timing->width >= 1280) {
+ EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+ vga_control |= (1L<<30) | (1L<<18);
+ }
+ }
+ } else {
+ pt = get_port_type(emgd_crtc->crtc_id);
+ if(pt == IGD_PORT_LVDS) {
+ EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+ vga_control |= (1L<<25 | (1L<<18));
+ } else if (upscale) {
+ EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+ vga_control |= 1L<<25;
+ }
+ }
+
+ if(pipe->pipe_num) {
+ vga_control |= 1L<<29;
+ }
+
+ kms_program_pipe_vga(emgd_crtc, (igd_timing_info_t *)timing->extn_ptr);
+ EMGD_WRITE32(vga_control, context->device_context.virt_mmadr + 0x71400);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+/**
+ * kms_set_pipe_pwr_tnc
+ *
+ * Turns the pipe ON or OFF depending on the input
+ *
+ * @param emgd_crtc (IN) specifies the pipe to change
+ * @param enable (IN) TRUE to enable pipe, FALSE to disable
+ *
+ * @return
+ */
+static void kms_set_pipe_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+ unsigned long pipe_conf;
+ unsigned long port_type;
+ unsigned long temp;
+ struct drm_device *dev;
+ igd_display_pipe_t *pipe;
+ igd_context_t *context;
+
+
+ EMGD_TRACE_ENTER;
+
+
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ pipe = emgd_crtc->igd_pipe;
+ port_type = get_port_type(emgd_crtc->crtc_id);
+ pipe_conf = READ_MMIO_REG_TNC(port_type, pipe->pipe_reg);
+
+
+ /* Do nothing if current power state is same as what we want to set */
+ /* The PIPE_ENABLE bit is at bit-position 31 */
+ if ( (enable << 31) == (pipe_conf & PIPE_ENABLE) ){
+
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+
+ if (!enable) {
+
+ /* For SDVO, disable both pipe Bs in 0:2:0 and 0:3:0 */
+ if (IGD_PORT_SDVO == port_type) {
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+ pipe_conf & ~PIPE_ENABLE);
+ }
+
+ /* Disable pipe */
+ WRITE_MMIO_REG_TNC(port_type, pipe->pipe_reg, pipe_conf & ~PIPE_ENABLE);
+
+ /* check when the pipe is disabled. */
+ wait_pipe(port_type, pipe->pipe_reg, 0);
+
+ /* Make sure the associated DPLL is turned off. */
+ temp = READ_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control);
+ if (temp & BIT31) {
+ /* Double buffered */
+ WRITE_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control,
+ temp & ~BIT31);
+ WRITE_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control,
+ temp & ~BIT31);
+ }
+
+
+ EMGD_DEBUG("Set Pipe Power: OFF");
+
+ } else {
+
+ if (IGD_PORT_SDVO == port_type) {
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+ pipe_conf | PIPE_ENABLE);
+ }
+
+ /* Enable pipe */
+ WRITE_MMIO_REG_TNC(port_type, pipe->pipe_reg, pipe_conf | PIPE_ENABLE);
+
+ EMGD_DEBUG("Set Pipe Power: ON");
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+/**
+ * kms_program_pipe_tnc
+ *
+ * Called before a mode set, takes the input "mode", matches it to the closest
+ * supported mode, then put the supported mode into "adjusted_mode" to let the
+ * caller know.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return true, false (details TBD)
+ */
+static void kms_program_pipe_tnc(emgd_crtc_t *emgd_crtc)
+{
+ unsigned long timing_reg;
+ unsigned long pipe_conf;
+ unsigned long hactive, vactive;
+ short hactive_tmp, vactive_tmp;
+ igd_timing_info_t *current_timings;
+ igd_timing_info_t pTimings_tmp;
+ struct drm_device *dev = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_display_port_t *port = NULL;
+ igd_context_t *context = NULL;
+ struct drm_encoder *encoder = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ pd_timing_t *vga_timing = NULL;
+
+ unsigned long flag_clip_fix;
+ unsigned long pipe_reg;
+ unsigned long temp;
+ unsigned long pt;
+ unsigned long dc;
+ unsigned long calc;
+ int i;
+ tnc_wa_timing_t *wa;
+ /* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */
+ platform_context_tnc_t *platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ pipe = emgd_crtc->igd_pipe;
+ current_timings = pipe->timing;
+ vga_timing = (pd_timing_t *) current_timings->extn_ptr;
+ pipe_reg = pipe->pipe_reg;
+
+ pt = get_port_type(emgd_crtc->crtc_id);
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ platform_context = (platform_context_tnc_t *) mode_context->context->platform_context;
+ flag_clip_fix = mode_context->clip_hw_fix;
+
+ EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+ pipe_conf = READ_MMIO_REG_TNC(pt, pipe->pipe_reg);
+
+ /* Preserving bits 0:17, bit 20, bit 24, bit 26, bit 29:30. The spec on
+ * which bits to preserve has been updated since we've originally written
+ * the code for the non-KMS path. However, to minimize risk of this fix,
+ * we are only updating them here. This is why we are not using
+ * device_data_tnc->pipe_preserve. */
+ pipe_conf &= 0x6513FFFF;
+
+ /* For TNC B1, enable hardware cliping fix*/
+ if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)&&
+ (flag_clip_fix & IGD_CLIP_FIX_GLOBAL_ENABLE)) {
+
+ /* Disable SDVO Pipe in Device 2 and Device 3 */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+ pipe_conf & (~0x80000000L));
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, pipe->pipe_reg,
+ pipe_conf & (~0x80000000L));
+
+ /* check when the pipe is disabled. */
+ wait_pipe(IGD_PORT_LVDS, pipe->pipe_reg, 0);
+
+ /* Enable clipping hardware fix */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+ if(flag_clip_fix & IGD_CLIP_FIX_REPLACE_STALL) {
+ temp |= BIT18;
+ } else {
+ temp &= ~BIT18;
+ }
+ if(flag_clip_fix & IGD_CLIP_FIX_DISABLE_THROTTLE) {
+ temp |= BIT15;
+ } else {
+ temp &= ~BIT15;
+ }
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp);
+ }
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ break;
+ }
+ }
+
+ if (NULL == emgd_encoder) {
+ EMGD_ERROR_EXIT("Invalid CRTC selected.");
+ return;
+ }
+
+ /* Debug messages */
+ EMGD_DEBUG("Current timings %ux%u mode_number = %u "
+ "mode_info_flags = 0x%lx, dclk = %lu",
+ current_timings->width,
+ current_timings->height,
+ current_timings->mode_number,
+ current_timings->mode_info_flags,
+ current_timings->dclk);
+
+ if (vga_timing) {
+ EMGD_DEBUG("ext_timing %ux%u mode_number = %u "
+ "mode_info_flags= 0x%lx, dclk = %lu",
+ vga_timing->width,
+ vga_timing->height,
+ vga_timing->mode_number,
+ vga_timing->mode_info_flags,
+ vga_timing->dclk);
+ }
+
+
+ /*
+ * If the mode is VGA and the PD says it handles all VGA modes without
+ * reprogramming then just set the mode and leave centering off.
+ */
+ if(current_timings->mode_info_flags & IGD_MODE_VESA) {
+ EMGD_DEBUG("IGD_MODE_VESA");
+
+ if (current_timings->mode_number <= VGA_MODE_NUM_MAX) {
+ EMGD_DEBUG("current_timings->mode_number <= VGA_MODE_NUM_MAX");
+ kms_program_pipe_vga_tnc(emgd_crtc);
+
+ EMGD_TRACE_EXIT;
+ return;
+ }
+ }
+
+ /* Program dot clock divisors. */
+ kms_program_clock_tnc(emgd_crtc, pipe->clock_reg, current_timings->dclk);
+
+ /* Program timing registers for the pipe */
+ timing_reg = pipe->timing_reg;
+ if (current_timings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ hactive = (unsigned long)current_timings->width*2 - 1;
+ } else {
+ hactive = (unsigned long)current_timings->width - 1;
+ }
+
+ if (current_timings->mode_info_flags & IGD_LINE_DOUBLE) {
+ vactive = (unsigned long)current_timings->height*2 - 1;
+ } else {
+ /* For Atom E6xx Hardware will automatically divide by 2 to
+ get the number of line in each field */
+ vactive = (unsigned long)current_timings->height - 1;
+ }
+
+
+ /* Reset the Palette */
+ for (i = 0; i < 256; i++) {
+ /* Program each of the 256 4-byte palette entries */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->palette_reg + (i << 2),
+ ((i<<16) | (i<<8) | i));
+ }
+
+ if (port) {
+ /* apply color correction */
+ for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+ if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) {
+
+ set_color_correct_tnc(emgd_crtc);
+ }
+ }
+ }
+
+
+ /*
+ * NOTE: For size reasons the timng table contains unsigned short
+ * values. Don't shift them past 16. Use a temp instead.
+ * All register offsets and bit shift are verified for Gen4
+ *
+ * For SDVO display:
+ * Write values into pipe B registers in both 0:2:0 and 0:3:0
+ */
+
+ dc = *(context->mod_dispatch.dsp_current_dc);
+
+ wa = WA_TUNE;
+
+ for (i=0; i<2; i++) {
+ /* Temp variable */
+ pTimings_tmp = *current_timings;
+ hactive_tmp = (short) hactive;
+ vactive_tmp = (short) vactive;
+
+ /* This work around is only for Atom E6xx B0 */
+ if((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
+ && pt == IGD_PORT_SDVO &&
+ (context->device_context.rid == TNC_B0_RID)
+ && FLAG(flag_basic_htotal_formula_wa)){
+
+ if(!(current_timings->reserved_dd & TNC_HTOTAL_TUNED)){
+ /* Modify blanks so it always begin after active pixel and ends
+ * at the end. Do not change it if we are already tuned to
+ * maintain original timing specification
+ */
+ pTimings_tmp.hblank_start =
+ (short) (current_timings->width - 1);
+ pTimings_tmp.vblank_start =
+ (short) (current_timings->height - 1);
+ pTimings_tmp.hblank_end = (short) (current_timings->htotal);
+ pTimings_tmp.vblank_end = (short) (current_timings->vtotal);
+ }
+
+ if(i==0){
+ if(current_timings->reserved_dd == 0 ||
+ (wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){
+ /* First time tuning */
+ if ((mode_context->ref_freq != 0) &&
+ (mode_context->ref_freq >= 190000) &&
+ (mode_context->ref_freq <= 210000)){
+ calc = (current_timings->htotal *
+ mode_context->ref_freq);
+ } else {
+ calc = (current_timings->htotal * LNC_CLOCK);
+ }
+
+ calc = (calc / (pipe->clock_reg->actual_dclk));
+ calc *= (current_timings->vtotal -1);
+ calc /= current_timings->vtotal;
+ pTimings_tmp.htotal = (short)calc;
+ current_timings->reserved_dd = wa->htotal =
+ pTimings_tmp.htotal;
+ EMGD_DEBUG("Delta = %d", wa->htotal);
+ }else if (current_timings->reserved_dd & TNC_HTOTAL_TUNED){
+ pTimings_tmp.htotal =
+ (short)(current_timings->reserved_dd &
+ (~TNC_HTOTAL_TUNED));
+ }else{
+ if(wa->htotal == 0)
+ wa->htotal = (short)current_timings->reserved_dd;
+ pTimings_tmp.htotal = wa->htotal;
+ }
+ /* Use vphase formula if available */
+ if(vphase){
+ pTimings_tmp.vtotal -= (short)vphase;
+ pTimings_tmp.vsync_start -= (short)vphase;
+ pTimings_tmp.vsync_end -= (short)vphase;
+ pTimings_tmp.vblank_end -= (short)vphase;
+ }else{
+ pTimings_tmp.hblank_end +=
+ (short) (pTimings_tmp.htotal - current_timings->htotal);
+ }
+ }
+ }
+
+
+ /* Program Timings */
+ temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp;
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp);
+
+ temp = ((unsigned long) pTimings_tmp.hblank_end << 16) |
+ (unsigned long)(pTimings_tmp.hblank_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp);
+
+ temp = ((unsigned long)(current_timings->hsync_end) << 16) |
+ (unsigned long)(current_timings->hsync_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp;
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) |
+ (unsigned long)(pTimings_tmp.vblank_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) |
+ (unsigned long)(pTimings_tmp.vsync_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp);
+
+ /*
+ * If there is a linked mode it is either the VGA or a scaled
+ * mode. If it is scaled then we need to use it as the source size.
+ */
+ if (current_timings->extn_ptr) {
+ igd_timing_info_t *scaled_timings =
+ (igd_timing_info_t *)current_timings->extn_ptr;
+
+ if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+ (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+ temp = (hactive << 16) | vactive;
+ } else {
+ EMGD_DEBUG("scaled_timings->width [%d], "
+ "scaled_timings->height [%d]\n",
+ scaled_timings->width, scaled_timings->height);
+ temp = (unsigned long)scaled_timings->width - 1;
+ temp = (temp << 16) |
+ (unsigned long)(scaled_timings->height - 1);
+ }
+ } else {
+ temp = (hactive_tmp << 16) | vactive_tmp;
+ }
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp);
+
+ /* Put pipe in interlaced mode if requested:
+ * should only happen for LVDS display if at all. */
+ if (current_timings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ pipe_conf |= (INTERLACE_EN);
+ } else {
+ pipe_conf &= ~(INTERLACE_EN);
+ }
+
+ pipe_conf |= PIPE_ENABLE;
+ WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg, pipe_conf);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg, pipe_conf);
+
+ /* For LVDS port, don't touch dev3 registers stop after 1st iteration */
+ if (pt == IGD_PORT_LVDS) {
+ break;
+ }
+ }
+
+
+ /* Gen4 can check when the pipe is enabled. */
+ wait_pipe(IGD_PORT_LVDS, pipe->pipe_reg, 0x40000000);
+
+ /*
+ * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+ * mode can be accessed through 0xa0000 in a 16bit world.
+ */
+ WRITE_AR(context->device_context.virt_mmadr, 0x10, 0xb);
+ WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x06, 0x5);
+ WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x10, 0x1);
+
+ if(current_timings->extn_ptr) {
+ /* This means either internal scaling (LVDS) or centered VGA */
+ current_timings = current_timings->extn_ptr;
+ if(current_timings->extn_ptr) {
+ /* This is both the scaled and centered VGA */
+ current_timings = current_timings->extn_ptr;
+ }
+ if (current_timings->mode_info_flags & IGD_MODE_VESA) {
+ if (current_timings->mode_number <= VGA_MODE_NUM_MAX) {
+ kms_program_pipe_vga_tnc(emgd_crtc);
+ }
+ }
+ }
+
+ if (pt == IGD_PORT_SDVO) {
+ /* Enable Chicken Bit */
+ /* Setting BIT6 enable Pipe B Palette Write
+ * to prevent hang during palette write */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp | BIT6);
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+static void kms_set_plane_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+ unsigned long plane_control;
+ unsigned long plane_reg;
+ struct drm_device *dev = NULL;
+ igd_display_plane_t *plane = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Plane: %s", enable?"ENABLE":"DISABLE");
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ plane = PLANE(pipe->owner);
+
+ if (!plane) {
+ EMGD_ERROR_EXIT("Trying to set power to a plane that is not tied "
+ " to a crtc.");
+ return;
+ }
+
+ /* In case a plane update is already in progress */
+ wait_for_vblank_tnc(pipe->pipe_reg);
+
+ /* Get the current value of the plane control register */
+ plane_reg = plane->plane_reg;
+ plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+
+ if((enable == FALSE) ||
+ (context->device_context.power_state != IGD_POWERSTATE_D0)) {
+ /*
+ * Note: The vga programming code does not have an "off". So
+ * when programming the plane to off we make sure VGA is off
+ * as well.
+ */
+ disable_vga_tnc(context->device_context.virt_mmadr);
+
+ /* The Sprite and Cursor planes need to turned off for the modeset
+ to succeed. */
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + DSPCCNTR);
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + DSPCCNTR + DSP_START_OFFSET);
+
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR);
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR + CUR_BASE_OFFSET);
+
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_A_CNTR);
+ EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR + CUR_BASE_OFFSET);
+
+ /*
+ * To turn off plane A or B, the program have to trigger the plane A
+ * or B start register. Or else, it will not work.
+ */
+ plane_control &= ~BIT31;
+
+ EMGD_WRITE32(plane_control,
+ context->device_context.virt_mmadr + plane_reg);
+
+ EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+ plane_reg + DSP_START_OFFSET),
+ context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+ } else {
+ /* Enable Plane */
+ plane_control |= BIT31;
+
+ EMGD_WRITE32(plane_control,
+ context->device_context.virt_mmadr + plane_reg);
+
+ EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+ plane_reg + DSP_START_OFFSET),
+ context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+ }
+
+
+ wait_for_vblank_tnc(pipe->pipe_reg);
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+
+static void kms_program_plane_tnc(emgd_crtc_t *emgd_crtc, unsigned long status)
+{
+ unsigned long stride;
+ unsigned long stereo;
+ unsigned long plane_control;
+ unsigned long other_plane_reg;
+ igd_timing_info_t *timing = NULL;
+ igd_framebuffer_info_t *fb_info = NULL;
+ unsigned long plane_reg;
+ struct drm_device *dev = NULL;
+ igd_display_plane_t *plane = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_context_t *context = NULL;
+ igd_timing_info_t *pipe_timing = NULL;
+ unsigned long ulreg = 0;
+ unsigned long b_reg = 0;
+ /* tnc_wa_timing_t *wa = WA_TUNE; */
+
+ EMGD_TRACE_ENTER;
+
+
+ pipe = emgd_crtc->igd_pipe;
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ plane = PLANE(pipe->owner);
+ if (!plane) {
+ EMGD_ERROR("Trying to program a plane that is not tied to a crtc.");
+ return;
+ }
+ fb_info = plane->fb_info;
+ plane_reg = plane->plane_reg;
+
+
+ EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+ wait_for_vblank_tnc(pipe->pipe_reg);
+
+ plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+ if(plane->plane_reg == DSPACNTR) {
+ plane_control &= device_data_tnc->plane_a_preserve;
+ } else { /* if it's plane b or plane c */
+ plane_control &= device_data_tnc->plane_b_c_preserve;
+ }
+
+
+ /*
+ * Note: The very first pass through this function will be with
+ * status false and timings == NULL. Don't use the timings before
+ * the check above.
+ */
+ timing = pipe->timing;
+ pipe_timing = timing;
+ /* There is a special case code for legacy VGA modes */
+ while (timing->extn_ptr) {
+ timing = (igd_timing_info_t *)timing->extn_ptr;
+ }
+ if(MODE_IS_VGA(timing) && CHECK_VGA(pipe_timing)) {
+ kms_program_plane_vga(context->device_context.virt_mmadr, timing);
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ disable_vga_tnc(context->device_context.virt_mmadr);
+
+ /* enable plane, select pipe, enable gamma correction logic */
+ plane_control |= (pipe->pipe_num<<24);
+ pipe->plane = plane;
+ plane_control |= (1<<30);
+
+
+ /* Here the settings:
+ * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+ * If line dbling only, set 21,20 to 11b
+ * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply
+ * If no doubling, set 21,20 to 00b (no Horz Multiply)
+ * For pixel doubling
+ * --> both progressive/interlaced modes
+ * For Line doubling
+ * --> progressive modes only
+ */
+
+ if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+ /* Line doubling in progressive mode requires special bits */
+ if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* BIT 20 for line & pixel doubling*/
+ plane_control |= BIT20;
+ /* check later, if no pixel doubling, set bit 21 too*/
+ }
+ }
+ if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ /* For line ONLY doubling, set bit 21 also '1' */
+ plane_control |= BIT21;
+ }
+
+ kms_mode_get_stride_stereo_tnc(pipe, plane, &stride, &stereo, 0);
+
+ /* set color depth */
+ switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+ case PF_DEPTH_8:
+ plane_control |= BIT27 | BIT30;
+ break;
+ case PF_DEPTH_16:
+ plane_control |= BIT28 | BIT26;
+ break;
+ default:
+ case PF_DEPTH_32:
+ plane_control |= BIT28 | BIT27;
+ break;
+ }
+
+ if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+ plane_control |= (BIT30);
+ }
+
+ if(fb_info->flags & IGD_SURFACE_TILED) {
+ plane_control |= (BIT10);
+ }
+
+ /* Set watermark for Atom E6xx */
+ if (!mode_context->en_reg_override) {
+ if (plane_reg == DSPACNTR) {
+ other_plane_reg = DSPBCNTR;
+ } else {
+ other_plane_reg = DSPACNTR;
+ }
+
+ if (EMGD_READ32(context->device_context.virt_mmadr + other_plane_reg) &
+ 0x80000000) {
+
+ EMGD_WRITE32(device_data_tnc->dsp_arb,
+ context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+ } else if (plane_reg == DSPACNTR) {
+ EMGD_WRITE32(0x00003fff,
+ context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+ } else {
+ EMGD_WRITE32(0x00003f80,
+ context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+ }
+
+ /*
+ * Setting WM priority level to 11
+ * to workaround display bouncing issues
+ * TODO: Mode set from Clone->Single(Primary)
+ * PIPEA_DISP_ARB_CTRL does not get updated
+ */
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + 0x00020f8);
+ EMGD_WRITE32(ulreg | 0x000003f0,
+ context->device_context.virt_mmadr + 0x00020f8);
+
+ EMGD_WRITE32(device_data_tnc->fifo_watermark1,
+ context->device_context.virt_mmadr + FW_1);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark2,
+ context->device_context.virt_mmadr + FW_2);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark3,
+ context->device_context.virt_mmadr + FW_3);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark4,
+ context->device_context.virt_mmadr + FW_4);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark5,
+ context->device_context.virt_mmadr + FW_5);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark6,
+ context->device_context.virt_mmadr + FW_6);
+ } else {
+ /* en_reg_override=1 */
+ /* Override display registers */
+ EMGD_WRITE32(mode_context->gvd_hp_control,
+ context->device_context.virt_mmadr + 0x00020f8);
+ EMGD_WRITE32(mode_context->disp_arb,
+ context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+ EMGD_WRITE32(mode_context->fifo_watermark1,
+ context->device_context.virt_mmadr + FW_1);
+ EMGD_WRITE32(mode_context->fifo_watermark2,
+ context->device_context.virt_mmadr + FW_2);
+ EMGD_WRITE32(mode_context->fifo_watermark3,
+ context->device_context.virt_mmadr + FW_3);
+ EMGD_WRITE32(mode_context->fifo_watermark4,
+ context->device_context.virt_mmadr + FW_4);
+ EMGD_WRITE32(mode_context->fifo_watermark5,
+ context->device_context.virt_mmadr + FW_5);
+ EMGD_WRITE32(mode_context->fifo_watermark6,
+ context->device_context.virt_mmadr + FW_6);
+ EMGD_WRITE32(mode_context->disp_chicken_bits,
+ context->device_context.virt_mmadr + 0x0070400);
+
+ /* Override Bunit Chickenbits and BWFLUSH register */
+ write_bunit_tnc(0x30, mode_context->bunit_chicken_bits);
+ write_bunit_tnc(0x02, mode_context->bunit_write_flush);
+ }
+
+ EMGD_DEBUG(" GVD HP_CONTROL: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr +
+ PIPEA_DISP_ARB_CTRL);
+ EMGD_DEBUG(" Display Arbitration register: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_1);
+ EMGD_DEBUG(" FIFO Watermark Control Register 1: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_2);
+ EMGD_DEBUG(" FIFO Watermark Control Register 2: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_3);
+ EMGD_DEBUG(" FIFO Watermark Control Register 3: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_4);
+ EMGD_DEBUG(" FIFO Watermark Control Register 4: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_5);
+ EMGD_DEBUG(" FIFO Watermark Control Register 5: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_6);
+ EMGD_DEBUG(" FIFO Watermark Control Register 6: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(context->device_context.virt_mmadr + DSP_CHICKENBITS);
+ EMGD_DEBUG(" Display Chicken bits: 0x%lx", ulreg);
+ read_bunit_tnc(0x30, &b_reg);
+ EMGD_DEBUG(" Bunit Chicken bits: 0x%lx", b_reg);
+ read_bunit_tnc(0x02, &b_reg);
+ EMGD_DEBUG(" Bunit Write Flush: 0x%lx", b_reg);
+
+
+ /* FIXME: Not required for TNC.
+ * The B-Spec states that rendering will be slower if the fences are not
+ * a power of 2. So for now, always use a power of 2. */
+ /* EMGD_WRITE32(0x04000400, context->device_context.virt_mmadr + 0x209c); */
+
+ EMGD_DEBUG(" Plane Control: 0x%lx", plane_control);
+ EMGD_DEBUG(" Plane Base: 0x%lx", fb_info->fb_base_offset);
+ EMGD_DEBUG(" Visible Offset: 0x%lx", fb_info->visible_offset);
+ EMGD_DEBUG(" Plane Pitch: 0x%lx", stride);
+
+ EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+ EMGD_WRITE32(stride,
+ context->device_context.virt_mmadr + plane_reg + DSP_STRIDE_OFFSET);
+
+ EMGD_WRITE32(fb_info->visible_offset,
+ context->device_context.virt_mmadr + plane_reg + DSP_LINEAR_OFFSET);
+ EMGD_WRITE32(0, context->device_context.virt_mmadr + plane_reg + 0x24);
+ EMGD_WRITE32(fb_info->fb_base_offset,
+ context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+
+ wait_for_vblank_tnc(pipe->pipe_reg);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return program_port_lvds_gen4()
+ * @return program_port_sdvo_gen4()
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int kms_program_port_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status)
+{
+ EMGD_TRACE_ENTER;
+
+ if (emgd_encoder->igd_port->port_type == IGD_PORT_LVDS) {
+ EMGD_TRACE_EXIT;
+ return kms_program_port_lvds_tnc(emgd_encoder, status);
+ } else {
+ EMGD_TRACE_EXIT;
+ return kms_program_port_sdvo_tnc(emgd_encoder, status);
+ }
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int kms_program_port_lvds_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status)
+{
+ int ret = 0;
+ unsigned long pd_powerstate = PD_POWER_MODE_D3;
+ pd_timing_t *timing = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder = NULL;
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ struct drm_crtc *crtc = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ encoder = &emgd_encoder->base;
+ port = emgd_encoder->igd_port;
+ dev = encoder->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ EMGD_DEBUG("Program LVDS: (%s)", status?"ENABLE":"DISABLE");
+
+ if (status == TRUE) {
+
+ if(!(port->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ pd_powerstate = (context->device_context.power_state > port->power_state) ?
+ context->device_context.power_state : port->power_state;
+
+ if (pd_powerstate == IGD_POWERSTATE_D0) {
+ EMGD_DEBUG("Power State: D0");
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == encoder->crtc) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+ break;
+ }
+ }
+
+ timing = (pd_timing_t *)pipe->timing;
+ /* Reach end timing to get user resolution and pass it to pd */
+ if(timing->extn_ptr) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+ /* set mode will take care of port control */
+ ret = port->pd_driver->set_mode(
+ port->pd_context,
+ timing,
+ 1<<pipe->pipe_num);
+ }
+ }
+
+ /* either status == FALSE, or status == TRUE, but powerstate is D1/D2/D3 */
+ if (pd_powerstate != IGD_POWERSTATE_D0) {
+ ret = port->pd_driver->set_power(
+ port->pd_context, PD_POWER_MODE_D3);
+ }
+
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+ (pd_powerstate == IGD_POWERSTATE_D0)?"mode":"power", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int kms_program_port_sdvo_tnc(emgd_encoder_t *emgd_encoder,
+ unsigned long status)
+{
+ unsigned long port_control;
+ unsigned long pd_powerstate = PD_POWER_MODE_D3;
+ unsigned long upscale = 0;
+ igd_timing_info_t local_timing;
+ igd_timing_info_t *timing = NULL;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder = NULL;
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ struct drm_crtc *crtc = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ unsigned long temp;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ encoder = &emgd_encoder->base;
+ port = emgd_encoder->igd_port;
+ dev = encoder->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ EMGD_DEBUG("Program Port: (%s)", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("pd_flags: 0x%lx", port->pd_flags);
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == encoder->crtc) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+ break;
+ }
+ }
+
+ timing = pipe->timing;
+
+ port_control = READ_MMIO_REG_TNC(IGD_PORT_SDVO, port->port_reg);
+
+ if (status == TRUE) {
+ if (!(port->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ /* Enable VGA syncs for native vga modes */
+ if (port->vga_sync == 1) {
+ EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
+ if((timing->width == 720) && (timing->height == 400)) {
+ EMGD_DEBUG("Modify port control and multi_port_control");
+ port_control |= (1L<<15);
+ }
+ }
+
+ /* Fact that both IGD_ powerstates and PD_ powermodes have
+ * same definitions */
+ pd_powerstate =
+ (context->device_context.power_state > port->power_state) ?
+ context->device_context.power_state : port->power_state;
+
+ if (pd_powerstate == IGD_POWERSTATE_D0) {
+ EMGD_DEBUG("Power State: D0");
+ /* Upscale */
+ pi_pd_find_attr_and_value(port,
+ PD_ATTR_ID_PANEL_FIT,
+ 0, /*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+
+ /* Reach the end timing if upscaling is enabled */
+ if (timing->extn_ptr && upscale) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+
+ local_timing = *timing;
+ if (upscale) {
+ /* For timings smaller than width 360 and height 200,
+ * double the size. This is because the active area of the mode
+ * is double the size of the resolution for these modes
+ * - Very tricky huh */
+ if (local_timing.width <= 360) {
+ local_timing.width <<= 1;
+ }
+ if (local_timing.height <= 200) {
+ local_timing.height <<= 1;
+ }
+ }
+
+ /* BIT31 - Enable
+ * BIT30 - PIPE B
+ * BIT29 - Stall
+ * BIT7 - Border
+ */
+ port_control |= BIT31|BIT30|BIT29|BIT7;
+
+ /* Program cDVO registers:
+ * Keep default values for
+ * 7000h - cDVO control register
+ * 7004h - cDVO slew rate register
+ * 7008h - cDVO strength register
+ * 700Ch - cDVO RCOMP update register
+ * 6102Ch - cDVO stall register = 0xA.
+ * Note: Though EAS says 6102Ch default value is 6, it is a typo
+ * in the spec, based on Si DE hw default value is 10 (0xA),
+ * so no need to program explicitly. This saves few bytes for
+ * micro.
+ */
+
+ /* Enable Current Source */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
+ temp |= 0x2000;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
+ }
+ }
+
+ if (pd_powerstate == PD_POWER_MODE_D0) {
+ ret = port->pd_driver->set_mode(port->pd_context, &local_timing, 0);
+ } else {
+ ret = port->pd_driver->set_power(port->pd_context, pd_powerstate);
+ }
+
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+ (pd_powerstate == PD_POWER_MODE_D0)?"mode":"power", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Port_control: 0x%lx", port_control);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, port->port_reg, port_control);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int kms_post_program_port_tnc(emgd_encoder_t * emgd_encoder,
+ unsigned long status)
+{
+ int ret;
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ struct drm_encoder *encoder = NULL;
+ struct drm_crtc *crtc = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_timing_info_t *timings = NULL;
+ /* unsigned long portreg; */
+
+ EMGD_TRACE_ENTER;
+
+ encoder = &emgd_encoder->base;
+ dev = encoder->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ port = emgd_encoder->igd_port;
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == encoder->crtc) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+ timings = pipe->timing;
+ break;
+ }
+ }
+
+ /*
+ * The programming found in the common code for all chipsets
+ * has the device programming sequence as follows:
+ * Port
+ * Pipe
+ * Post Port
+ * Plane
+ * On Gen4, if the port is enabled before the pipe, there is a 10%
+ * chance that the port will not turn on properly.
+ * Due to compatability requires with other chipsets, this workaround
+ * fixes this issue
+ *
+ * This is handled by set_power. This also only seems to apply to a
+ * chipset that is no longer supported. Not sure if this will get
+ * re-introduced with ValleyView and beyond, so I left it here.
+ *
+ * portreg = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
+ * WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg & ~BIT31);
+ * WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg);
+ */
+
+ if (port->port_type == IGD_PORT_SDVO) {
+ initialize_ST_bridge(context, port);
+ }
+
+ ret = 0;
+ /* call post_set_mode() if exists */
+ if (port->pd_driver->post_set_mode) {
+ if (port->port_type == IGD_PORT_SDVO){
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ status); /*Needed for LAPIS*/
+ } else {
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ 1<<pipe->pipe_num);
+ }
+ if (ret) {
+ EMGD_ERROR_EXIT("PD post_set_mode returned: 0x%x", ret);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+/*!
+ * kms_get_vblank_counter_tnc
+ *
+ * This function returns the vblank counter number back to the caller.
+ *
+ * @param emgd_crtc [IN] The pipe to get frame value from
+ *
+ * @return 0 frame number, which can also be used as a vblank counter number
+ */
+static u32 kms_get_vblank_counter_tnc(emgd_crtc_t *emgd_crtc)
+{
+ unsigned long high1, high2, low;
+ struct drm_device *dev;
+ unsigned long frame_high_reg, frame_low_reg;
+ igd_context_t *context;
+
+
+ dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+
+ switch (emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) {
+ case IGD_PORT_SHARE_DIGITAL:
+ frame_high_reg = PIPEB_FRAME_HIGH;
+ frame_low_reg = PIPEB_FRAME_PIXEL;
+ break;
+
+ case IGD_PORT_SHARE_LVDS:
+ default:
+ frame_high_reg = PIPEA_FRAME_HIGH;
+ frame_low_reg = PIPEA_FRAME_PIXEL;
+ break;
+ }
+
+
+ /*
+ * High and low register fields are not synchronized so it is possible
+ * that our low value is actually not from the same high value, e.g.
+ * going from "99" to "00" when transitioning 499 to 500. To get
+ * around this, we will read until the two reads of high values stay
+ * the same.
+ */
+ do {
+ high1 = EMGD_READ32(context->device_context.virt_mmadr +
+ frame_high_reg);
+ high1 &= PIPE_FRAME_HIGH_MASK;
+
+ low = EMGD_READ32(context->device_context.virt_mmadr +
+ frame_low_reg);
+ low &= PIPE_FRAME_LOW_MASK;
+
+ high2 = EMGD_READ32(context->device_context.virt_mmadr +
+ frame_high_reg);
+ high2 &= PIPE_FRAME_HIGH_MASK;
+ } while (high1 != high2);
+
+
+ /* Frame count low is located at bits 24-31 */
+ low >>= PIPE_FRAME_LOW_SHIFT;
+
+ /* Low value is 8 bits long, so shift high by 8 bits */
+ return (high1 << 8) | low;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
new file mode 100644
index 0000000..2a313ec
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
@@ -0,0 +1,2659 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_mode_tnc.c
+ * $Revision: 1.47 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * 1) Atom E6xx Core implementations for the mode dispatch functions.
+ * 2) 0:2:0 = Device2 = LNC VGA
+ * 0:3:0 = Device3 = Atom E6xx overlay
+ * 3) For MMIO access:
+ * Dev2 only: Use EMGD_READ32(), EMGD_WRITE32(): less code
+ * Dev2/3: Use READ_MMIO_REG_TNC(), WRITE_MMIO_REG_TNC(): more code
+ * For code optimization sake use the right macro.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd.h>
+#include <igd_pwr.h>
+
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+#include <dsp.h>
+#include <vga.h>
+#include <intelpci.h>
+#include <math_fix.h>
+#include <mode_access.h>
+#include <rb.h>
+#include <pi.h>
+#include <dispatch.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/mi.h>
+#include <tnc/instr.h>
+#include <tnc/igd_tnc_wa.h>
+#include "drm_emgd_private.h"
+
+#include "../cmn/match.h"
+#include "../cmn/mode_dispatch.h"
+#include "mode_tnc.h"
+
+/*
+ Turning on FIB part workaround for all IALs, for vBIOS this will limit
+ the port drivers to one at a time (SDVO or LVDS)due to code size
+ */
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*
+ * Exports from the other components of this module.
+ */
+
+#ifdef CONFIG_TNC
+
+extern int program_clock_tnc(igd_display_context_t *display,
+ igd_clock_t *clock, unsigned long dclk);
+
+int program_cdvo_tnc(void);
+
+extern unsigned long get_port_type(int crtc_id);
+
+extern mode_full_dispatch_t mode_full_dispatch_tnc;
+
+int wait_for_vblank_tnc(unsigned long pipe_reg);
+void wait_pipe(unsigned long pt, unsigned long pipe_reg, unsigned long check_on_off);
+
+void shutdown_ST_bridge(igd_context_t *context);
+void initialize_ST_bridge(igd_context_t *context, igd_display_port_t *port);
+
+#if 0
+static void cdvo_signal(void);
+#endif
+
+static unsigned long flag_clip_fix = IGD_CLIP_FIX_GLOBAL_ENABLE |
+ IGD_CLIP_FIX_DISABLE_THROTTLE;
+
+/* Extern defines for Device2, device3 and device31 iobases.
+ * For Atom E6xx all devices are always io_mapped. */
+extern unsigned char io_mapped;
+extern unsigned short io_base;
+extern unsigned char io_mapped_lvds;
+extern unsigned short io_base_lvds;
+extern unsigned char io_mapped_sdvo;
+extern unsigned short io_base_sdvo;
+extern unsigned char io_mapped_lpc;
+extern unsigned short io_base_lpc;
+extern unsigned char io_mapped_sdvo_st;
+extern unsigned short io_base_sdvo_st;
+extern unsigned char io_mapped_sdvo_st_gpio;
+extern unsigned short io_base_sdvo_st_gpio;
+
+#ifdef DEBUG_BUILD_TYPE
+/* Debug configuration flag for B0 workaround. Workaround is turned on by default. */
+int flag_basic_htotal_formula_wa = 1; /* Enable formula workaround flag */
+int flag_turn_off_port_wa = 1; /* Turn off port when sweeping */
+int flag_enable_tuning_wa = 1; /* Disable sweeping flag */
+#endif
+
+/* Do not change the order */
+const unsigned long ports_tnc[2] = {IGD_PORT_LVDS, IGD_PORT_SDVO};
+
+tnc_wa_timing_t tune = {0, 0, 0, 0, 0, 0, 0,};
+
+/* Temporary frame buffer */
+static igd_framebuffer_info_t fb_info_tmp = {0,0,0,0,0,0,0};
+
+/* VPhase variable */
+int vphase = 0; /* The current value to enable vphase is 5 */
+
+mode_data_tnc_t device_data_tnc[1] = {
+ {
+ 0x000b0000, /* plane a preservation */
+ 0x00000000, /* plane b c preservation */
+ 0x60000000, /* pipe preservation */
+ 0x00003232, /* DSP FIFO Size A=50 B=50 C=28 May require fine tuning*/
+ 0x3f8f0404, /* FIFO watermark control1 */
+ 0x04040f04, /* FIFO watermark control2 */
+ 0x00000000, /* FIFO watermark control3 */
+ 0x04040404, /* FIFO watermark1 control4 */
+ 0x04040404, /* FIFO watermark1 control5 */
+ 0x00000078, /* FIFO watermark1 control6 */
+ }
+};
+
+pixel_crc_t compute_pixel_crc( pixel_crc_t pixel, pixel_crc_t new_pixel)
+{
+ pixel_crc_t pixel_crc_new;
+
+ pixel_crc_new.pixel = 0x0;
+
+ pixel_crc_new.bit.bit22 = pixel.bit.bit14;
+ pixel_crc_new.bit.bit21 = pixel.bit.bit13;
+ pixel_crc_new.bit.bit20 = pixel.bit.bit12;
+ pixel_crc_new.bit.bit19 = pixel.bit.bit11;
+ pixel_crc_new.bit.bit18 = pixel.bit.bit10;
+ pixel_crc_new.bit.bit17 = pixel.bit.bit9;
+ pixel_crc_new.bit.bit16 = pixel.bit.bit22 ^ pixel.bit.bit8;
+ pixel_crc_new.bit.bit15 = pixel.bit.bit21 ^ pixel.bit.bit7;
+ pixel_crc_new.bit.bit14 = pixel.bit.bit20 ^ pixel.bit.bit6;
+ pixel_crc_new.bit.bit13 = pixel.bit.bit19 ^ pixel.bit.bit5;
+ pixel_crc_new.bit.bit12 = pixel.bit.bit18 ^ pixel.bit.bit4;
+ pixel_crc_new.bit.bit11 = pixel.bit.bit17 ^ pixel.bit.bit3;
+ pixel_crc_new.bit.bit10 = pixel.bit.bit16 ^ pixel.bit.bit2;
+ pixel_crc_new.bit.bit9 = pixel.bit.bit15 ^ pixel.bit.bit1;
+ pixel_crc_new.bit.bit8 = pixel.bit.bit0;
+ pixel_crc_new.bit.bit7 = pixel.bit.bit22 ^ new_pixel.bit.bit0;
+ pixel_crc_new.bit.bit6 = pixel.bit.bit21 ^ new_pixel.bit.bit1;
+ pixel_crc_new.bit.bit5 = pixel.bit.bit20 ^ new_pixel.bit.bit2;
+ pixel_crc_new.bit.bit4 = pixel.bit.bit19 ^ new_pixel.bit.bit3;
+ pixel_crc_new.bit.bit3 = pixel.bit.bit18 ^ new_pixel.bit.bit4;
+ pixel_crc_new.bit.bit2 = pixel.bit.bit17 ^ new_pixel.bit.bit5;
+ pixel_crc_new.bit.bit1 = pixel.bit.bit16 ^ new_pixel.bit.bit6;
+ pixel_crc_new.bit.bit0 = pixel.bit.bit15 ^ new_pixel.bit.bit7;
+
+ return (pixel_crc_new);
+}
+
+#ifndef CONFIG_MICRO
+int check_display_tnc(igd_display_context_t *display,
+ unsigned short port_number,unsigned long status)
+{
+ pixel_crc_t red_val, green_val, blue_val;
+ pixel_crc_t blue_crc, green_crc, red_crc;
+ int i, j, bps = 4, ret_val = 0;
+ unsigned long *curr_pixel, sync = 0, size = 0, dc;
+ unsigned long tnc_crc_red, tnc_crc_green, tnc_crc_blue, temp;
+ unsigned long temp_plane, temp_pitch, temp_control, plane_control;
+ unsigned long pt = PORT_TYPE(display);
+ igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
+ igd_timing_info_t pTimings_tmp, *pTimings_ext,*pTimings = PIPE(display)->timing;
+ /* igd_display_port_t *port = PORT_OWNER(display); */
+ platform_context_tnc_t *platform_context = display->context->platform_context;
+ igd_rect_t dst_rect;
+ igd_surface_t front_buffer;
+ tnc_wa_timing_t *wa = WA_TUNE;
+ os_alarm_t timeout;
+
+ EMGD_TRACE_ENTER;
+
+ dc = *(display->context->mod_dispatch.dsp_current_dc);
+ pTimings_tmp = *pTimings;
+ pTimings_ext = pTimings;
+
+ /* Check to see if VGA plane was requested */
+ while (pTimings_ext->extn_ptr) {
+ pTimings_ext = (igd_timing_info_t *)pTimings_ext->extn_ptr;
+ }
+ if((pt != IGD_PORT_SDVO) || (display->context->device_context.rid != TNC_B0_RID)
+ || (platform_context->stbridgedev)
+ || (pTimings->reserved_dd & TNC_HTOTAL_TUNED) || (!FLAG(flag_enable_tuning_wa))
+ || (mode_context->tuning_wa == 0) /*if 0 don't tune*/
+ || wa->counter > LIMIT_TOTAL_CHECK_DISPLAY
+ || (MODE_IS_VGA(pTimings_ext))
+ || (!IGD_DC_CLONE(dc) && !IGD_DC_EXTENDED(dc))
+ || (platform_context->tnc_dev3_rid != TNC_B0_DEV3_RID)){
+ /* Workaround is specific for SDVO display
+ * Dont tuned if it isnt B0 silicon
+ * Dont tuned if it is already tuned
+ * Dont tuned if bypass is turned on (debug)
+ * No tuning for VGA modes
+ * Stop Tuning if above limit LIMIT_TOTAL_CHECK_DISPLAY
+ * Dont tuned if B1 silicon (based on SDVO Device 3 RID)
+ */
+
+ if(pt != IGD_PORT_SDVO ||
+ (MODE_IS_VGA(pTimings_ext))){
+ EMGD_DEBUG("Unsupported tuning");
+ }else if((wa->counter > LIMIT_TOTAL_CHECK_DISPLAY) &&
+ !(pTimings->reserved_dd & TNC_HTOTAL_TUNED)){
+ pTimings->reserved_dd = 0;
+ EMGD_ERROR("Unable to get tuned value!");
+ }
+
+ if(FLAG(flag_turn_off_port_wa)){
+ /* Turn on SDVO source */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
+ temp |= BIT13;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
+ }
+
+ if(fb_info_tmp.width){
+ /* Free up the temporary frame buffer */
+ display->context->dispatch.gmm_free(fb_info_tmp.fb_base_offset);
+ OS_MEMSET(&fb_info_tmp,0,sizeof (igd_framebuffer_info_t));
+ }
+ OS_MEMSET(wa, 0, sizeof(tnc_wa_timing_t));
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+
+ /* Increment checking counter */
+ wa->counter++;
+
+ /* CRC starting value */
+ blue_crc.pixel = 0x007FFFFF;
+ green_crc.pixel = 0x007FFFFF;
+ red_crc.pixel = 0x007FFFFF;
+
+ if(FLAG(flag_turn_off_port_wa)){
+ /* Turn of port source.
+ * */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
+ temp &= ~BIT13;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
+ }
+
+ /* Allocate temporary 32 bpp frame buffer for CRC calculation.
+ * SV only provided codes for 32bpp CRC calculation so we would
+ * only calculate CRC for 32bpp. Once CRC is calculated EMGD
+ * would revert back to original plane. A temporary place is also
+ * neede so no corruption is seen on lvds for clone display
+ */
+ if(fb_info_tmp.width != (unsigned short)pTimings_tmp.width &&
+ fb_info_tmp.height != (unsigned short)pTimings_tmp.height){
+ if(fb_info_tmp.width){
+ EMGD_ERROR("Memory leak! Previous framebuffer is not freed!");
+ }
+ fb_info_tmp.width = pTimings_tmp.width;
+ fb_info_tmp.height = pTimings_tmp.height;
+ fb_info_tmp.screen_pitch = fb_info->screen_pitch;
+ fb_info_tmp.fb_base_offset = 0;
+ fb_info_tmp.pixel_format = IGD_PF_xRGB32;
+ fb_info_tmp.flags = IGD_SURFACE_DISPLAY | IGD_SURFACE_RENDER;
+
+ ret_val = display->context->dispatch.gmm_alloc_surface(
+ &fb_info_tmp.fb_base_offset,
+ fb_info_tmp.pixel_format,
+ &fb_info_tmp.width,
+ &fb_info_tmp.height,
+ &fb_info_tmp.screen_pitch,
+ &size,
+ IGD_GMM_ALLOC_TYPE_NORMAL,
+ &fb_info_tmp.flags);
+ }
+ /* Temp plane is always 32 bpp */
+ temp_control = EMGD_READ32(MMIO(display)
+ + PLANE(display)->plane_reg);
+ plane_control = temp_control;
+ plane_control &= ~(BIT30 | BIT29 | BIT28 | BIT27);
+ plane_control |= BIT28 | BIT27;
+ EMGD_WRITE32(plane_control, MMIO(display)
+ + PLANE(display)->plane_reg);
+ temp_pitch = EMGD_READ32(MMIO(display)
+ + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
+ EMGD_WRITE32(fb_info_tmp.screen_pitch, MMIO(display)
+ + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
+ temp_plane = EMGD_READ32(MMIO(display)
+ + PLANE(display)->plane_reg + DSP_START_OFFSET);
+ EMGD_WRITE32(fb_info_tmp.fb_base_offset,
+ MMIO(display) + PLANE(display)->plane_reg + DSP_START_OFFSET);
+ /* Setup front buffer */
+ OS_MEMSET(&front_buffer,0,sizeof (igd_surface_t));
+ front_buffer.width = fb_info_tmp.width;
+ front_buffer.height = fb_info_tmp.height;
+ front_buffer.pitch = fb_info_tmp.screen_pitch;
+ front_buffer.offset = fb_info_tmp.fb_base_offset;
+ front_buffer.pixel_format = fb_info_tmp.pixel_format;
+ front_buffer.flags = fb_info_tmp.flags;
+ /* Draw 2 color bars for CRC calculation. This is simple and sufficient
+ * to detect clipping. Will consider complicated color bar if an issue
+ * is found for now go for quickest methodColor bar. Red and Blue */
+ dst_rect.x1 = dst_rect.y1 = 0;
+ dst_rect.x2 = fb_info_tmp.width/2;
+ dst_rect.y2 = fb_info_tmp.height;
+
+ /*
+ // NOT supported in koheo, using software for now
+ display->context->dispatch.color_blt((igd_display_h)display,
+ IGD_PRIORITY_NORMAL,
+ &front_buffer,
+ &dst_rect,
+ IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL,
+ 0x00FF0000,
+ 0xF0,
+ (igd_appcontext_h)0, IGD_RENDER_BLOCK);
+ */
+
+ {
+ unsigned long row, col;
+ unsigned char *buf = NULL;
+ unsigned long height = fb_info_tmp.height;
+ unsigned long width = fb_info_tmp.width/2;
+ unsigned long pitch = fb_info_tmp.screen_pitch;
+
+ buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
+ for (row = 0; row < (height); row++) {
+ for (col = 0; col < (width); col++) {
+ EMGD_WRITE32(0x00FF0000, (buf + (col*4)));
+ }
+ buf = buf + pitch;
+ }
+ display->context->dispatch.gmm_unmap(buf);
+ }
+
+ dst_rect.x1 = fb_info_tmp.width/2;
+ dst_rect.y1 = 0;
+ dst_rect.x2 = fb_info_tmp.width;
+ dst_rect.y2 = fb_info_tmp.height;
+
+ /*
+ // NOT supported in koheo, using software for now
+ display->context->dispatch.color_blt((igd_display_h)display,
+ IGD_PRIORITY_NORMAL,
+ &front_buffer,
+ &dst_rect,
+ IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL,
+ 0x000000FF,
+ 0xF0,
+ (igd_appcontext_h)0, IGD_RENDER_BLOCK);
+ wa->flag |= TNC_HTOTAL_TUNED;
+ pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED);
+ return FALSE;
+
+ display->context->dispatch.sync((igd_display_h)display, IGD_PRIORITY_NORMAL,
+ &sync,
+ IGD_SYNC_NONBLOCK);
+ */
+
+ {
+ unsigned long row, col;
+ unsigned char *buf = NULL;
+ unsigned long height = fb_info_tmp.height;
+ unsigned long width = fb_info_tmp.width;
+ unsigned long pitch = fb_info_tmp.screen_pitch;
+
+ buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
+ for (row = 0; row < (height); row++) {
+ for (col = fb_info_tmp.width/2; col < (width); col++) {
+ EMGD_WRITE32(0x000000FF, (buf + (col*4)));
+ }
+ buf = buf + pitch;
+ }
+ display->context->dispatch.gmm_unmap(buf);
+ }
+
+
+ ret_val = -IGD_ERROR_BUSY;
+ timeout = OS_SET_ALARM(500);
+ while (-IGD_ERROR_BUSY == ret_val && (!OS_TEST_ALARM(timeout))){
+ ret_val = display->context->dispatch.sync(
+ (igd_display_h)display,
+ IGD_PRIORITY_NORMAL,
+ &sync,
+ IGD_SYNC_BLOCK);
+ OS_SCHEDULE();
+ if (0 == ret_val) {
+ break;
+ }
+ }
+
+ /* Turn on HW CRC */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x80000000);
+ /* Reset Status Bit */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024);
+ temp |= 0x00001000;
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024, temp);
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024);
+ temp |= 0x00001000;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024, temp);
+
+ /* Calculate CRC pixel by reading every single pixel.
+ * Pixel that is more than the timing range is ignore which happens
+ * during panning. To save time CRC is only calculated once per timing
+ * change and kept inside a scratch global variable wa.
+ */
+ if(wa->crc_red == 0 || wa->crc_green == 0 ||
+ wa->crc_blue == 0 ){
+ unsigned char *fb_adr;
+
+ fb_adr = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
+
+ /* Calculate CRC for this timing */
+ for(i=0; i<(int)pTimings_tmp.height; i++){
+ for(j=0; j<(int)pTimings_tmp.width; j++){
+ if(i < (int)fb_info_tmp.height && j < (int)fb_info_tmp.width){
+ /* virt_fb_adr not available anymore */
+ /*
+ curr_pixel = (unsigned long*)(
+ mode_context->context->device_context.virt_fb_adr +
+ fb_info_tmp.fb_base_offset + j*bps + (i*fb_info_tmp.screen_pitch));
+ */
+
+ curr_pixel = (unsigned long*)(fb_adr + (j*bps) + (i*fb_info_tmp.screen_pitch));
+
+ if(curr_pixel == NULL){
+ EMGD_DEBUG("FB not valid return true for now util FB is allocated");
+ return TRUE;
+ }
+
+
+
+ /*
+ blue_val.pixel = (0x0000ff & *curr_pixel) >> 0;
+ green_val.pixel = (0x00ff00 & *curr_pixel) >> 8;
+ red_val.pixel = (0xff0000 & *curr_pixel) >> 16;
+ */
+
+ blue_val.pixel = (0x0000ff & EMGD_READ32(curr_pixel)) >> 0;
+ green_val.pixel = (0x00ff00 & EMGD_READ32(curr_pixel)) >> 8;
+ red_val.pixel = (0xff0000 & EMGD_READ32(curr_pixel)) >> 16;
+
+ }else{
+ red_val.pixel = green_val.pixel = blue_val.pixel = 0;
+ }
+
+ blue_crc = compute_pixel_crc(blue_crc, blue_val);
+ green_crc = compute_pixel_crc(green_crc, green_val);
+ red_crc = compute_pixel_crc(red_crc, red_val);
+ }
+ }
+ display->context->dispatch.gmm_unmap(fb_adr);
+
+ /* Save calculated value */
+ wa->crc_red = red_crc.pixel;
+ wa->crc_green = green_crc.pixel;
+ wa->crc_blue = blue_crc.pixel;
+ }else{
+ /* Reuse CRC value calculated before */
+ red_crc.pixel = wa->crc_red;
+ green_crc.pixel = wa->crc_green;
+ blue_crc.pixel = wa->crc_blue;
+ }
+
+ timeout = OS_SET_ALARM(70);
+ do {
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024);
+ if(temp & 0x00002000){
+ break;
+ }
+ OS_SCHEDULE();
+ } while ((!OS_TEST_ALARM(timeout)));
+ /* Give some time for CRC to be stable */
+ OS_SLEEP(500);
+ /* Read CRC on LNC and OVL */
+ tnc_crc_red = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61060);
+ tnc_crc_green = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61064);
+ tnc_crc_blue = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61068);
+
+ /* Revert back to original plane */
+ EMGD_WRITE32(temp_control, MMIO(display)
+ + PLANE(display)->plane_reg);
+ EMGD_WRITE32(temp_pitch, MMIO(display)
+ + PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
+ EMGD_WRITE32(temp_plane, MMIO(display)
+ + PLANE(display)->plane_reg + DSP_START_OFFSET);
+
+ /* Turn off CRC */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x00000000);
+ /* Compare CRC calculation with Atom E6xx CRC, return false if a mismatch and
+ * tuning continues. If it matches indicate the flag as tuned and return
+ * false anyway so pipe programming would program based on the correct
+ * timing spec.
+ */
+ if((red_crc.pixel != (unsigned int)tnc_crc_red) ||
+ (green_crc.pixel != (unsigned int)tnc_crc_green) ||
+ (blue_crc.pixel != (unsigned int)tnc_crc_blue)){
+
+ /* Step by step tuning */
+ wa->delta = 1;
+
+ /* Calculate the delta value */
+ wa->htotal = (wa->htotal + wa->delta);
+
+ EMGD_DEBUG("Counter %d",wa->counter);
+ EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red);
+ EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green);
+ EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue);
+ EMGD_DEBUG("CRC does not match, tuning....");
+ EMGD_TRACE_EXIT;
+ return FALSE;
+ }
+ EMGD_ERROR("Tuned value found.");
+ EMGD_ERROR("Total tuning required %d",wa->counter);
+ EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red);
+ EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green);
+ EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue);
+ wa->flag |= TNC_HTOTAL_TUNED;
+ pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED);
+
+ EMGD_TRACE_EXIT;
+ /* We are tuned but lets do another sequence since we may have changed
+ * the blanks to get a valid CRC. This happens on certain modes that has
+ * weird blanks value like VESA's 640x480 at 60
+ */
+ return FALSE;
+}
+#endif
+
+/*!
+ *
+ * @param mmio dev2 mmio
+ *
+ * @return void
+ */
+void disable_vga_tnc (unsigned char *mmio)
+{
+ unsigned long temp;
+ unsigned char sr01;
+
+ EMGD_TRACE_ENTER;
+
+ /* Disable VGA plane if it is enabled. */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL);
+ if ((temp & BIT31) == 0) {
+ /* Read SR01 */
+ READ_VGA(mmio, SR_PORT, SR01, sr01);
+
+ /* Turn on SR01 bit 5 */
+ WRITE_VGA(mmio, SR_PORT, SR01, sr01|BIT(5));
+
+ /* Wait for 30us */
+ OS_SLEEP(30);
+
+ temp |= BIT31; /* set bit 31 to disable */
+ temp &= ~BIT30; /* clear bit 30 to get VGA display in normal size */
+ EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL);
+
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_set_palette_entry_tnc(
+ igd_display_h display_handle,
+ unsigned long palette_entry,
+ unsigned long palette_color)
+{
+ /* Return if Pipe is not on */
+ if(!((1L<<31) & READ_MMIO_REG_TNC(PORT_TYPE_DH(display_handle),
+ PIPE(display_handle)->pipe_reg))) {
+ return -IGD_INVAL;
+ }
+ /* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS,
+ PIPE(display_handle)->palette_reg + palette_entry * 4,
+ palette_color);
+
+ return 0;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_get_palette_entry_tnc(
+ igd_display_h display_handle,
+ unsigned long palette_entry,
+ unsigned long *palette_color)
+{
+ /* Return if Pipe is not on */
+ if(!((1L<<31) & READ_MMIO_REG_TNC(
+ PORT_TYPE_DH(display_handle),
+ PIPE(display_handle)->pipe_reg))) {
+ return -IGD_INVAL;
+ }
+ /* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
+ *palette_color = 0xffffff & READ_MMIO_REG_TNC(
+ IGD_PORT_LVDS,
+ PIPE(display_handle)->palette_reg + palette_entry * 4);
+ return 0;
+}
+
+/*!
+ *
+ * @param mmio
+ * @param pipe_reg
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int wait_for_vblank_tnc(unsigned long pipe_reg)
+{
+ unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET;
+ unsigned long tmp;
+ unsigned long port_type = IGD_PORT_LVDS;
+ os_alarm_t timeout;
+ int ret;
+ unsigned long request_for;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Parameter: pipe_reg = %lx", pipe_reg);
+
+ /* If pipe is off then just return */
+ if(!((1L<<31) & READ_MMIO_REG_TNC(port_type, pipe_reg))) {
+ EMGD_DEBUG("Pipe disabled/Off");
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ /*
+ * When VGA plane is on the normal wait for vblank won't work
+ * so just skip it. VGA plane is on 0:2:0 so no need to use _TNC macros.
+ */
+ if(!(EMGD_READ32(MMIO_TNC(port_type) + 0x71400) & 0x80000000)) {
+ EMGD_DEBUG("VGA Plane On");
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ /* 1. Request the interrupt handler to record the next VBlank: */
+ request_for = VBINT_REQUEST(VBINT_WAIT,
+ (pipe_status_reg == PIPEA_STAT) ? VBINT_PORT4 : VBINT_PORT2);
+ mode_context->dispatch->full->request_vblanks(request_for,
+ MMIO_TNC(port_type));
+
+ /* 2. Wait (about 50 msec, 20Hz) & poll for the next VBlank: */
+ timeout = OS_SET_ALARM(50);
+ do {
+ OS_SCHEDULE();
+ tmp = mode_context->dispatch->full->vblank_occured(request_for);
+ } while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout)));
+
+
+ if (tmp == 0) {
+ EMGD_ERROR_EXIT("Timeout waiting for VBLANK");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+ /* 3. End our request for the next VBlank: */
+ mode_context->dispatch->full->end_request(request_for,
+ MMIO_TNC(port_type));
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* wait_for_vblank_tnc */
+
+
+
+/*!
+ * This procedure waits for the next vertical blanking (vertical retrace)
+ * period. If the display is already in a vertical blanking period, this
+ * procedure exits.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param display_handle
+ *
+ * @return FALSE if timed out
+ */
+int igd_wait_vblank_tnc(igd_display_h display_handle)
+{
+
+ return wait_for_vblank_tnc(PIPE(display_handle)->pipe_reg);
+
+}
+
+
+/*!
+ * Get the stride and stereo values based on the display. This is also used
+ * by the MI instructions.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int mode_get_stride_stereo_tnc(igd_display_context_t *display,
+ unsigned long *stride,
+ unsigned long *stereo,
+ unsigned long flags)
+{
+ unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
+ igd_timing_info_t *timing = PIPE(display)->timing;
+ unsigned long base_offset;
+
+ EMGD_TRACE_ENTER;
+
+ base_offset = PLANE(display)->fb_info->visible_offset;
+ *stride = pitch;
+ *stereo = 0;
+
+ /* For field replication, valid for interlaced modes only
+ * set stereo = fb_base
+ * stride = pitch
+ */
+ if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+ if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* Interlaced + Line double flags means field replication.
+ * same lines are sent for both fields. Program the
+ * second eye to be same as the first
+ */
+ *stereo = base_offset;
+ } else {
+ /* Regular interlaced. Second eye starts on line 2.
+ * Skip every other line.
+ */
+ *stereo = base_offset + pitch;
+ *stride = pitch * 2;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*
+ * Atom E6xx LVDS display: Mode switch sequence
+ *
+ * 1. Enable sequence
+ *
+ * Program power on delay, power off delay, power cycle delay registers
+ * Program backlight control register to set appropriate backlight value
+ * Pipe A must be completely off at this point
+ * Write PIPEACONF bits[19:18] = 00
+ * Write DSPACNTR bit[31] = 1
+ * Write DSPASURF = 0x00000000
+ * Write DSPACNTR bit[31] =Â 0
+ * Write DSPASURF = 0x00000000
+ * Restore PIPEACONF bits[19:18]Â to original value
+ * Program DPLL
+ * Enable DPLL
+ * Wait for DPLL warm up 10us and check for DPLL lock bit in Pipe A config reg
+ * (Wait ensures clock is running smoothly before enabling pipe)
+ * Program pipe timings (Can be done before DPLL programming)
+ * Enable panel fitter as needed (Can be done before DPLL and/or
+ * pipe timing programming)
+ * Enable pipe
+ * Enable planes (VGA or HiRes)
+ * Enable ports
+ * Enable panel power (Can be done before DPLL programming)
+ *
+ * 2. Disable sequence
+ *
+ * Disable panel backlight
+ * Disable panel power (for AOAC standby)
+ * Disable ports
+ * Disable planes (VGA or hires)
+ * Disable pipe
+ * Disable VGA display in 0x71400 bit 31
+ * (Disable VGA display done after disable pipe to allow pipe to turn off
+ * when no vblank is available in native VGA mode)
+ * Wait for pipe off status
+ * (Wait ensures planes and pipe have completely turned off prior to
+ * disabling panelfitter then DPLL)
+ * Disable panelfitter
+ * Disable DPLL
+ * Pipe timings change or change between VGA native or VGA center/upperleft
+ * or HiRes
+ * Use complete disable sequence followed by complete enable sequence with
+ * new mode programmings.
+ *
+ *
+ * Atom E6xx SDVO display: Display Pipe B Enable/Disable sequence:
+ *
+ * 1. Enable sequence
+ *
+ * Program LNC and LNW DPLL
+ * Write all planes, port, power control registers on both LNC and LNW
+ * 1st Enable LNC pipe
+ * 2nd Enable LNW pipe
+ *
+ * 2. Disable Sequence
+ *
+ * Disable panel power
+ * Disable ports
+ * Disable planes
+ * 1st Disable LNC pipe
+ * 2nd Disable TNC_SDVO pipe
+ * Disable panel fitter
+ * Disable DPLL
+ */
+
+
+/*!
+ *
+ * @param display Pointer to hardware device instance data
+ *
+ * @return void
+ */
+void program_pipe_vga_tnc(
+ igd_display_context_t *display)
+{
+ igd_timing_info_t *timing;
+ unsigned long vga_control;
+ unsigned long upscale = 0;
+ int centering = 1;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * VGA Plane can attach to only one pipe at a time. LVDS can
+ * only attach to pipe B. We need to use the display passed to
+ * determine the pipe number to use. (Napa is same as Alm).
+ */
+
+ /*
+ * We can come here with following cases:
+ * 1. magic->vga CRT, DVI type displays
+ * 2. native->vga int-lvds, and up-scaling lvds displays
+ * 3. pipe->vga TV and other unscaled-lvds displays
+ */
+ vga_control = EMGD_READ32(MMIO(display) + 0x71400);
+ vga_control &= 0x18e3ff00;
+ vga_control |= 0x8e;
+
+ timing = PIPE(display)->timing;
+ if(!timing->extn_ptr) {
+ EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_tnc");
+ return;
+ }
+
+ /* Find UPSCALING attr value*/
+ pi_pd_find_attr_and_value(PORT_OWNER(display),
+ PD_ATTR_ID_PANEL_FIT,
+ 0,/*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+ /* this PI func will not modify value of upscale if attr does not exist */
+
+ /* magic->vga || native->vga cases, centering isn't required */
+ if ((timing->width == 720 && timing->height == 400) || upscale) {
+ EMGD_DEBUG("Centering = 0");
+ centering = 0;
+ }
+
+ /* Enable border */
+ if((timing->width >= 800) && !upscale) {
+ EMGD_DEBUG("Enable VGA Border");
+ vga_control |= (1L<<26);
+ }
+
+ if(timing->width == 640) {
+ EMGD_DEBUG("Enable Nine Dot Disable");
+ vga_control |= (1L<<18);
+ }
+
+ if(centering) {
+ EMGD_DEBUG("Enable VGA Center Centering");
+ vga_control |= 1L<<24;
+
+ if(timing->height >= 960) {
+ if(timing->width >= 1280) {
+ EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+ vga_control |= (1L<<30) | (1L<<18);
+ }
+ }
+ } else {
+ if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
+ EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+ vga_control |= (1L<<25 | (1L<<18));
+ } else if (upscale) {
+ EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+ vga_control |= 1L<<25;
+ }
+ }
+
+ if(PIPE(display)->pipe_num) {
+ vga_control |= 1L<<29;
+ }
+
+ program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
+ EMGD_WRITE32(vga_control, MMIO(display) + 0x71400);
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+
+#ifndef CONFIG_MICRO
+extern os_pci_dev_t bridge_dev;
+int read_bunit_tnc(unsigned long reg, unsigned long *val)
+{
+ reg <<= 8;
+ reg &= 0x0000ff00;
+ reg |= 0xD00300F0;
+
+ EMGD_TRACE_ENTER;
+
+ if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD0, reg)) {
+ EMGD_ERROR_EXIT("Writing into the MCR Failed\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(OS_PCI_READ_CONFIG_32(bridge_dev, 0xD4, val)) {
+ EMGD_ERROR_EXIT("Reading from MDR Failed\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+int write_bunit_tnc(unsigned long reg, unsigned long val)
+{
+ reg <<= 8;
+ reg &= 0x0000ff00;
+ reg |= 0xE00300F0;
+
+ EMGD_TRACE_ENTER;
+
+ if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD4, val)) {
+ EMGD_ERROR_EXIT("Writing into the MDR Failed\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD0, reg)) {
+ EMGD_ERROR_EXIT("Writing into the MCR Failed\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+#endif
+
+/*!
+ * Program Display Plane Values.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param status
+ *
+ * @return void
+ */
+void program_plane_tnc(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long stride;
+ unsigned long stereo;
+ unsigned long plane_control;
+ unsigned long other_plane_reg;
+ igd_timing_info_t *timing;
+ igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
+ unsigned long plane_reg = PLANE(display)->plane_reg;
+ igd_timing_info_t *pipe_timing;
+#ifndef CONFIG_MICRO
+ unsigned long ulreg = 0;
+#endif
+ unsigned long b_reg;
+ /* tnc_wa_timing_t *wa = WA_TUNE; */
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ igd_wait_vblank_tnc((igd_display_h)display);
+
+ plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+ if(PLANE(display)->plane_reg == DSPACNTR) {
+ plane_control &= device_data_tnc->plane_a_preserve;
+ } else { /* if it's plane b or plane c */
+ plane_control &= device_data_tnc->plane_b_c_preserve;
+ }
+
+ /* TODO: Bspec: For EagleLake this Trickle Feed must always disable */
+
+ if((status == FALSE) ||
+ (GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {
+
+ /*
+ * Note: The vga programming code does not have an "off". So
+ * when programming the plane to off we make sure VGA is off
+ * as well.
+ */
+ disable_vga_tnc(MMIO(display));
+
+ /*
+ * To turn off plane A or B, the program have to triger the plane A or B
+ * start register. Or else, it will not work.
+ */
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(EMGD_READ32(MMIO(display) + plane_reg + DSP_START_OFFSET),
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+ igd_wait_vblank_tnc((igd_display_h)display);
+ EMGD_TRACE_EXIT;
+ return;
+ }
+ /*
+ * Note: The very first pass through this function will be with
+ * status false and timings == NULL. Don't use the timings before
+ * the check above.
+ */
+ timing = PIPE(display)->timing;
+ pipe_timing = timing;
+ /* There is a special case code for legacy VGA modes */
+ while (timing->extn_ptr) {
+ timing = (igd_timing_info_t *)timing->extn_ptr;
+ }
+ if(MODE_IS_VGA(timing) && CHECK_VGA(pipe_timing)) {
+ program_plane_vga(display, timing);
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ disable_vga_tnc(MMIO(display));
+
+ /* enable plane, select pipe, enable gamma correction logic */
+ plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
+ PIPE(display)->plane = PLANE(display);
+#ifndef CONFIG_MICRO
+ plane_control |= (1<<30);
+#endif
+
+ /* Here the settings:
+ * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+ * If line dbling only, set 21,20 to 11b
+ * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply
+ * If no doubling, set 21,20 to 00b (no Horz Multiply)
+ * For pixel doubling
+ * --> both progressive/interlaced modes
+ * For Line doubling
+ * --> progressive modes only
+ */
+
+ if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+ /* Line doubling in progressive mode requires special bits */
+ if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+ /* BIT 20 for line & pixel doubling*/
+ plane_control |= BIT20;
+ /* check later, if no pixel doubling, set bit 21 too*/
+ }
+ }
+ if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ /* For line ONLY doubling, set bit 21 also '1' */
+ plane_control |= BIT21;
+ }
+
+ mode_get_stride_stereo_tnc(display, &stride, &stereo, 0);
+
+ /* set color depth */
+ switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+ case PF_DEPTH_8:
+ plane_control |= BIT27 | BIT30;
+ break;
+ case PF_DEPTH_16:
+ plane_control |= BIT28 | BIT26;
+ break;
+ default:
+ case PF_DEPTH_32:
+ plane_control |= BIT28 | BIT27;
+ break;
+ }
+
+ if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+ plane_control |= (BIT30);
+ }
+
+ if(fb_info->flags & IGD_SURFACE_TILED) {
+ plane_control |= (BIT10);
+ }
+
+ /* Set watermark for Atom E6xx */
+#ifndef CONFIG_MICRO
+ if (!mode_context->en_reg_override) {
+ if (plane_reg == DSPACNTR) {
+ other_plane_reg = DSPBCNTR;
+ } else {
+ other_plane_reg = DSPACNTR;
+ }
+
+ if (EMGD_READ32(MMIO(display) + other_plane_reg) & 0x80000000) {
+ EMGD_WRITE32(device_data_tnc->dsp_arb, MMIO(display) +
+ PIPEA_DISP_ARB_CTRL);
+ } else if (plane_reg == DSPACNTR) {
+ EMGD_WRITE32(0x00003fff, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+ } else {
+ EMGD_WRITE32(0x00003f80, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+ }
+
+ /*
+ * Setting WM priority level to 11
+ * to workaround display bouncing issues
+ * TODO: Mode set from Clone->Single(Primary)
+ * PIPEA_DISP_ARB_CTRL does not get updated
+ */
+ ulreg = EMGD_READ32(MMIO(display) + 0x00020f8);
+ EMGD_WRITE32(ulreg | 0x000003f0, MMIO(display) + 0x00020f8);
+
+ EMGD_WRITE32(device_data_tnc->fifo_watermark1, MMIO(display) + FW_1);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark2, MMIO(display) + FW_2);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark3, MMIO(display) + FW_3);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark4, MMIO(display) + FW_4);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark5, MMIO(display) + FW_5);
+ EMGD_WRITE32(device_data_tnc->fifo_watermark6, MMIO(display) + FW_6);
+ } else {
+ /* en_reg_override=1 */
+ /* Override display registers */
+ EMGD_WRITE32(mode_context->gvd_hp_control, MMIO(display) + 0x00020f8);
+ EMGD_WRITE32(mode_context->disp_arb, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+ EMGD_WRITE32(mode_context->fifo_watermark1, MMIO(display) + FW_1);
+ EMGD_WRITE32(mode_context->fifo_watermark2, MMIO(display) + FW_2);
+ EMGD_WRITE32(mode_context->fifo_watermark3, MMIO(display) + FW_3);
+ EMGD_WRITE32(mode_context->fifo_watermark4, MMIO(display) + FW_4);
+ EMGD_WRITE32(mode_context->fifo_watermark5, MMIO(display) + FW_5);
+ EMGD_WRITE32(mode_context->fifo_watermark6, MMIO(display) + FW_6);
+ EMGD_WRITE32(mode_context->disp_chicken_bits, MMIO(display) + 0x0070400);
+
+ /* Override Bunit Chickenbits and BWFLUSH register */
+ write_bunit_tnc(0x30, mode_context->bunit_chicken_bits);
+ write_bunit_tnc(0x02, mode_context->bunit_write_flush);
+ }
+
+ EMGD_DEBUG(" GVD HP_CONTROL: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + PIPEA_DISP_ARB_CTRL);
+ EMGD_DEBUG(" Display Arbitration register: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_1);
+ EMGD_DEBUG(" FIFO Watermark Control Register 1: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_2);
+ EMGD_DEBUG(" FIFO Watermark Control Register 2: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_3);
+ EMGD_DEBUG(" FIFO Watermark Control Register 3: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_4);
+ EMGD_DEBUG(" FIFO Watermark Control Register 4: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_5);
+ EMGD_DEBUG(" FIFO Watermark Control Register 5: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + FW_6);
+ EMGD_DEBUG(" FIFO Watermark Control Register 6: 0x%lx", ulreg);
+ ulreg = EMGD_READ32(MMIO(display) + DSP_CHICKENBITS);
+ EMGD_DEBUG(" Display Chicken bits: 0x%lx", ulreg);
+ read_bunit_tnc(0x30, &b_reg);
+ EMGD_DEBUG(" Bunit Chicken bits: 0x%lx", b_reg);
+ read_bunit_tnc(0x02, &b_reg);
+ EMGD_DEBUG(" Bunit Write Flush: 0x%lx", b_reg);
+#else
+ /* ITP Script is doing this and so go ahead */
+ /* The PIPEA_DISP_ARB_CTRL set fixed the issue with 32bit vesa modes */
+ EMGD_WRITE32(0x00001FBF, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+ EMGD_WRITE32(0x3F8F0F18, MMIO(display) + FW_1);
+#endif
+ /* FIXME: Not required for TNC.
+ * The B-Spec states that rendering will be slower if the fences are not
+ * a power of 2. So for now, always use a power of 2. */
+ /* EMGD_WRITE32(0x04000400, MMIO(display) + 0x209c); */
+
+ EMGD_DEBUG(" Plane Control: 0x%lx", plane_control);
+ EMGD_DEBUG(" Plane Base: 0x%lx", fb_info->visible_offset);
+ EMGD_DEBUG(" Plane Pitch: 0x%lx", stride);
+
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
+ /* Both of these registers are Reserved on Gen4 */
+ /*EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);*/
+ /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);*/
+ EMGD_WRITE32(0, MMIO(display) + plane_reg + DSP_LINEAR_OFFSET);
+ EMGD_WRITE32(0, MMIO(display) + plane_reg + 0x24);
+ EMGD_WRITE32(fb_info->visible_offset,
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+ igd_wait_vblank_tnc((igd_display_h)display);
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * PGen4 can check when the pipe is enabled or disabled.
+ * This function waits for the pipe to be enabled or disabled.
+ * check_on_off = 0 to wait for the pipe to disable.
+ * check_on_off = 0x40000000 to wait for the pipe to enable.
+ *
+ * @param mmio
+ * @param pipe_reg
+ * @param check_on_off
+ *
+ * @return void
+ */
+void wait_pipe(unsigned long pt, unsigned long pipe_reg, unsigned long check_on_off)
+{
+ unsigned long temp;
+ os_alarm_t timeout;
+
+ EMGD_TRACE_ENTER;
+
+ /* 0:3:0 doesn't wait pipe, only LNC device does. */
+ if (pt == IGD_PORT_SDVO) {
+ return;
+ }
+
+ /* Wait for Pipe enable/disable, about 50 msec (20Hz). */
+ timeout = OS_SET_ALARM(50);
+ do {
+ OS_SCHEDULE();
+ temp = EMGD_READ32(MMIO_TNC(IGD_PORT_LVDS) + pipe_reg) & 0x40000000;
+ /* Check for timeout */
+ } while ((temp != check_on_off) && (!OS_TEST_ALARM(timeout)));
+
+ if (temp != check_on_off) {
+ EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable");
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+unsigned long get_port_type(int crtc_id) {
+ if (crtc_id == IGD_KMS_PIPEA) {
+ return IGD_PORT_LVDS;
+ }
+ if (crtc_id == IGD_KMS_PIPEB) {
+ return IGD_PORT_SDVO;
+ }
+ EMGD_ERROR("Unrecognized port type based on crtc_id of %d", crtc_id);
+ return 0;
+}
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param display
+ * @param status
+ *
+ * @return void
+ */
+void program_pipe_tnc(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long timing_reg;
+ unsigned long pipe_conf;
+ unsigned long hactive, vactive;
+ igd_timing_info_t *pTimings;
+ igd_timing_info_t pTimings_tmp;
+ igd_display_port_t *port;
+ unsigned long temp;
+ unsigned long pt = PORT_TYPE(display);
+ unsigned long dc;
+ unsigned long calc;
+ short hactive_tmp, vactive_tmp;
+ int i;
+ tnc_wa_timing_t *wa;
+ /* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */
+ platform_context_tnc_t *platform_context;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ platform_context = (platform_context_tnc_t *)display->context->platform_context;
+
+ /* For Windows OS, flag_clip_fix will be overridden by configurable parameter in registry.
+ * This section of code is excluded in VBIOS, VBIOS will always use the pre-assigned value.
+ */
+ flag_clip_fix = mode_context->clip_hw_fix;
+
+ pipe_conf = device_data_tnc->pipe_preserve &
+ READ_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg);
+
+ if((status == FALSE) ||
+ (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
+ /* For SDVO disable both pipe Bs in 0:2:0 and 0:3:0 */
+ if (pt == IGD_PORT_SDVO) {
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg,
+ pipe_conf & (~0x80000000L));
+ /* After disable pipe B in 0:2:0, wait_pipe must be
+ * called to ensure the pipe B to be turned off */
+ wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0);
+ }
+ /* Disable pipe */
+ WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
+ pipe_conf & (~0x80000000L));
+
+ /* check when the pipe is disabled. */
+ wait_pipe(pt, PIPE(display)->pipe_reg, 0);
+
+ /* Disable DPLL */
+ //WRITE_MMIO_REG_TNC(pt, PIPE(display)->clock_reg->dpll_control,
+ // READ_MMIO_REG_TNC(pt,
+ // PIPE(display)->clock_reg->dpll_control) & ~0x80000000L);
+
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ /* For TNC B1, enable hardware cliping fix*/
+ if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)&&
+ (flag_clip_fix & IGD_CLIP_FIX_GLOBAL_ENABLE)) {
+ /* Disable SDVO Pipe in Device 2 and Device 3 */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg,
+ pipe_conf & (~0x80000000L));
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg,
+ pipe_conf & (~0x80000000L));
+
+ /* check when the pipe is disabled. */
+ wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0);
+
+ /* Enable clipping hardware fix */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+ if(flag_clip_fix & IGD_CLIP_FIX_REPLACE_STALL) {
+ temp |= BIT18;
+ } else {
+ temp &= ~BIT18;
+ }
+ if(flag_clip_fix & IGD_CLIP_FIX_DISABLE_THROTTLE) {
+ temp |= BIT15;
+ } else {
+ temp &= ~BIT15;
+ }
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp);
+ }
+
+
+ port = PORT_OWNER(display);
+ pTimings = PIPE(display)->timing;
+
+ {
+ /* Debug messages */
+ pd_timing_t *vga_timing = (pd_timing_t *)pTimings->extn_ptr;
+ EMGD_DEBUG("pTimings %ux%u mode_number = %u mode_info_flags = 0x%lx, dclk = %lu",
+ pTimings->width,
+ pTimings->height,
+ pTimings->mode_number,
+ pTimings->mode_info_flags,
+ pTimings->dclk);
+ if (vga_timing) {
+ EMGD_DEBUG("ext_timing %ux%u mode_number = %u mode_info_flags= 0x%lx, dclk = %lu",
+ vga_timing->width,
+ vga_timing->height,
+ vga_timing->mode_number,
+ vga_timing->mode_info_flags,
+ vga_timing->dclk);
+ }
+ }
+
+ /*
+ * If the mode is VGA and the PD says it handles all VGA modes without
+ * reprogramming then just set the mode and leave centering off.
+ */
+ if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+ EMGD_DEBUG("IGD_MODE_VESA");
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ /* Pipe timings and clocks no longer need to be set since
+ * the VGA timings will be used.
+ WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
+ pipe_conf | 0x80000000); */
+
+ /* Gen4 can check when the pipe is enabled. No longer needed
+ * since pipe not enabled and VGA timings are used.
+ wait_pipe(PIPE(display)->pipe_reg, 0x40000000);*/
+
+ EMGD_DEBUG("pTimings->mode_number <= VGA_MODE_NUM_MAX");
+ program_pipe_vga_tnc(display);
+ EMGD_TRACE_EXIT;
+ return;
+ } else {
+#ifdef CONFIG_MICRO
+ set_256_palette(
+ MMIO_TNC(PORT(display, display->port_number)->port_type));
+#endif
+ }
+ }
+
+ /* Program dot clock divisors. */
+ program_clock_tnc(display, PIPE(display)->clock_reg, pTimings->dclk);
+
+ /* Program timing registers for the pipe */
+ timing_reg = PIPE(display)->timing_reg;
+ if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+ hactive = (unsigned long)pTimings->width*2 - 1;
+ } else {
+ hactive = (unsigned long)pTimings->width - 1;
+ }
+
+ if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
+ vactive = (unsigned long)pTimings->height*2 - 1;
+ } else {
+ /* For Atom E6xx Hardware will automatically divide by 2 to
+ get the number of line in each field */
+ vactive = (unsigned long)pTimings->height - 1;
+ }
+
+#ifndef CONFIG_MICRO
+ /* reset the palette */
+ for (i = 0; i < 256; i++) {
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->palette_reg,
+ ((i<<16) | (i<<8) | i));
+ }
+
+
+ /* apply color correction */
+ for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+ if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+ (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) {
+
+ mode_context->dispatch->full->set_color_correct(display);
+ }
+ }
+#endif
+
+ /*
+ * NOTE: For size reasons the timng table contains unsigned short
+ * values. Don't shift them past 16. Use a temp instead.
+ * All register offsets and bit shift are verified for Gen4
+ *
+ * For SDVO display:
+ * Write values into pipe B registers in both 0:2:0 and 0:3:0
+ */
+
+ dc = *(display->context->mod_dispatch.dsp_current_dc);
+
+ wa = WA_TUNE;
+
+ for (i=0; i<2; i++) {
+ /* Temp variable */
+ pTimings_tmp = *pTimings;
+ hactive_tmp = (short) hactive;
+ vactive_tmp = (short) vactive;
+#ifndef CONFIG_MICRO
+
+ /* Htotal and tuning wa is not supported in VBIOS for TNC
+ * TNC B0: Enable Htotal formula and CRC Tuning to fix clipping issue and
+ * async flip flikering on single display
+ * TNC B1: Enable Htotal formula without CRC Tuning to fix async flip flikering
+ * For B0, TVOUT is excluded for htotal workaround to avoid image shifting
+ * issue happen. Image shifting will be fixed on B1 while ref_freq is lower down
+ * to 198Mhz
+ */
+
+
+ if( (pt == IGD_PORT_SDVO) && FLAG(flag_basic_htotal_formula_wa) &&
+ ( ((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID) &&
+ (mode_context->async_flip_wa) )||
+ ( (platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) &&
+ (!IGD_DC_SINGLE(dc) || (port->pd_driver->type != PD_DISPLAY_TVOUT))
+ )
+ )){
+
+
+ if((!(pTimings->reserved_dd & TNC_HTOTAL_TUNED)) &&
+ (wa->counter < LIMIT_TOTAL_CHECK_DISPLAY) &&
+ (platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) &&
+ (FLAG(flag_enable_tuning_wa))) {
+
+ /* Modify blanks so it always begin after active pixel and ends at the
+ * end. Do not change it if we are already tuned to maintain
+ * original timing specification
+ */
+ pTimings_tmp.hblank_start = (short) (pTimings->width - 1);
+ pTimings_tmp.vblank_start = (short) (pTimings->height - 1);
+ pTimings_tmp.hblank_end = (short) (pTimings->htotal);
+ pTimings_tmp.vblank_end = (short) (pTimings->vtotal);
+ }
+
+#ifndef CONFIG_MICRO
+ /* Delay Frame start while Tuning*/
+ /* Frame start delay is added as plane corruption occurs without delay.
+ * Pipe would begin fetching data from random memory location causing the delay.
+ * Silicon could not determine why this is happening but agree that adding a delay
+ * would not cause any issue unless for a DTD with single vsync line which is
+ * super unlikely used.
+ */
+
+ /* B1 stepping does not need to set this bit because it does not need tuning*/
+ if((platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) &&
+ (IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))){
+ pipe_conf |= BIT27;
+ }
+#endif
+
+
+ if(i==0){
+ if(pTimings->reserved_dd == 0 || (wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){
+ /* First time tuning */
+ if ((mode_context->ref_freq != 0) &&
+ (mode_context->ref_freq >= 190000) &&
+ (mode_context->ref_freq <= 210000))
+ {
+ if ((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)){
+ /* The optimum reference frequency used for 3DMark flickering workaround formula
+ is the LNC clock minus the optimum margin found from experiment */
+ calc = (pTimings->htotal * (mode_context->ref_freq - LNC_B1_OPTIMUM_MARGIN));
+ } else {
+ calc = (pTimings->htotal * mode_context->ref_freq);
+ }
+ } else {
+ if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)){
+ calc = (pTimings->htotal * (LNC_CLOCK - LNC_B1_OPTIMUM_MARGIN));
+ } else {
+ calc = (pTimings->htotal * LNC_CLOCK);
+ }
+
+ }
+
+ calc = (calc / (PIPE(display)->clock_reg->actual_dclk));
+ calc *= (pTimings->vtotal -1);
+ calc /= pTimings->vtotal;
+ pTimings_tmp.htotal = (short)calc;
+ pTimings->reserved_dd = wa->htotal = pTimings_tmp.htotal;
+ EMGD_DEBUG("Delta = %d", wa->htotal);
+ }else if (pTimings->reserved_dd & TNC_HTOTAL_TUNED){
+ pTimings_tmp.htotal = (short)(pTimings->reserved_dd & (~TNC_HTOTAL_TUNED));
+ }else{
+ if(wa->htotal == 0)
+ wa->htotal = (short)pTimings->reserved_dd;
+ pTimings_tmp.htotal = wa->htotal;
+ }
+ /* Use vphase formula if available */
+ if(vphase){
+ pTimings_tmp.vtotal -= (short)vphase;
+ pTimings_tmp.vsync_start -= (short)vphase;
+ pTimings_tmp.vsync_end -= (short)vphase;
+ pTimings_tmp.vblank_end -= (short)vphase;
+ }else{
+ //pTimings_tmp.hblank_start += (short) (pTimings_tmp.htotal - pTimings->htotal);
+ pTimings_tmp.hblank_end += (short) (pTimings_tmp.htotal - pTimings->htotal);
+ }
+ }
+ }
+#endif
+
+ temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp;
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp);
+
+ temp = ((unsigned long) pTimings_tmp.hblank_end << 16) |
+ (unsigned long)(pTimings_tmp.hblank_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp);
+
+ temp = ((unsigned long)(pTimings->hsync_end) << 16) |
+ (unsigned long)(pTimings->hsync_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp;
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) |
+ (unsigned long)(pTimings_tmp.vblank_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp);
+
+ temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) |
+ (unsigned long)(pTimings_tmp.vsync_start);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp);
+
+ /*
+ * If there is a linked mode it is either the VGA or a scaled
+ * mode. If it is scaled then we need to use it as the source size.
+ */
+ if(pTimings->extn_ptr) {
+ igd_timing_info_t *scaled_timings =
+ (igd_timing_info_t *)pTimings->extn_ptr;
+ if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+ (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+ temp = (hactive << 16) | vactive;
+ } else {
+ EMGD_DEBUG("scaled_timings->width [%d], scaled_timings->height [%d]\n", scaled_timings->width, scaled_timings->height);
+ temp = (unsigned long)scaled_timings->width - 1;
+ temp = (temp << 16) |
+ (unsigned long)(scaled_timings->height - 1);
+ }
+ } else {
+ temp = (hactive_tmp << 16) | vactive_tmp;
+ }
+ WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp);
+
+ /* Enable pipe */
+ pipe_conf |= PIPE_ENABLE;
+
+ /* Put pipe in interlaced mode if requested:
+ * should only happen for LVDS display if at all. */
+ if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+ pipe_conf |= (INTERLACE_EN);
+ } else {
+ pipe_conf &= ~(INTERLACE_EN);
+ }
+
+#ifdef CONFIG_MICRO
+ if (pt == IGD_PORT_SDVO) {
+ /*
+ Enable the panel fitter as VGA controller in Lincroft
+ is a Panel Fitted VGA controller.
+ LNC only supports panel fitted VGA mode
+ (upper left VGA mode). You need to enable the panel fitter.
+ The timing control will be from the pipe timing generator
+ but not from the VGA timing generator CRTC registers
+ as in the centering mode.
+ */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PFIT_CONTROL, 0xA2000000);
+ }
+#endif
+
+ WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
+ WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
+ /* For LVDS port, don't touch dev3 registers stop after 1st iteration */
+ if (pt == IGD_PORT_LVDS) {
+ break;
+ }
+ }
+
+
+ /* Gen4 can check when the pipe is enabled. */
+ wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0x40000000);
+
+ /*
+ * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+ * mode can be accessed through 0xa0000 in a 16bit world.
+ */
+ WRITE_AR(MMIO(display), 0x10, 0xb);
+ WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
+ WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);
+
+ if(pTimings->extn_ptr) {
+ /* This means either internal scaling (LVDS) or centered VGA */
+ pTimings = pTimings->extn_ptr;
+ if(pTimings->extn_ptr) {
+ /* This is both the scaled and centered VGA */
+ pTimings = pTimings->extn_ptr;
+ }
+ if (pTimings->mode_info_flags & IGD_MODE_VESA) {
+ if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+ program_pipe_vga_tnc(display);
+ } else {
+#ifdef CONFIG_MICRO
+ /*
+ * FIXME: This is not appropriate. This assumes that
+ * CONFIG_MICRO means "This is vBIOS" and programs
+ * the palette. vBIOS IAL should probably just set the
+ * palette itself??
+ */
+ set_256_palette(
+ MMIO_TNC(PORT(display, display->port_number)->port_type));
+#endif
+ }
+ }
+ }
+
+ if (pt == IGD_PORT_SDVO) {
+ /* Enable Chicken Bit */
+ /* Setting BIT6 enable Pipe B Palette Write
+ * to prevent hang during palette write */
+ /* Enable Chicken Bit */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp | BIT6);
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void reset_plane_pipe_ports_tnc(igd_context_t *context)
+{
+ igd_plane_t *plane;
+ igd_display_pipe_t *pipe;
+ igd_display_port_t *port,*tv_port=NULL;
+ unsigned long temp;
+ unsigned long i, j;
+ unsigned char *mmio;
+ inter_module_dispatch_t *md;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Disable all plane, pipe and port registers because the
+ * bios may have been using a different set. Only unset the
+ * enable bit.
+ */
+ mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ md = &context->mod_dispatch;
+ /* Turn off LVDS and SDVO ports */
+ port = NULL;
+ while((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
+ /* if the port is TV, then don't set the power to S3 as this causes
+ * blank screen on analog port after killx or cosole mode,
+ * probably because the external clock needs to be on till the pipes and
+ * DPLLs are off
+ */
+ if (port->pd_driver) {
+ if(port->pd_type == PD_DISPLAY_TVOUT) {
+ tv_port = port;
+ }else {
+
+ /* for CH7036: Code fix Meego hang after killall X
+ * Basicall, when X enters ACPI D1 state, we want to pass that info to port device (Ch7036)
+ * from reset_plane_pipe_ports_xxx().
+ */
+ if(context->device_context.power_state == IGD_POWERSTATE_D1) {
+ /* D1 power state for graphics is requested
+ * Then the power_state status will pass to pd
+ */
+ port->pd_driver->set_power(port->pd_context,context->device_context.power_state);
+ }
+ else {
+ port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3);
+ }
+ }
+ }
+
+ if (port->port_type == IGD_PORT_SDVO) {
+ shutdown_ST_bridge(context);
+ }
+
+ if (port->pd_driver) {
+ temp = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
+ WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, (temp & ~BIT31));
+ }
+ }
+
+ /* disable plane C */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + DSPCCNTR);
+ if(temp & BIT31) {
+ EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR);
+ EMGD_WRITE32(0x0, EMGD_MMIO(mmio) + DSPCCNTR + DSP_START_OFFSET);
+ }
+
+ /*
+ * Gen4 appears to require that plane B be shut off prior to
+ * shutting off plane A. The normal get_next_plane returns them
+ * in order. We need to read the list backwards.
+ */
+ plane = NULL;
+ while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) {
+ /* This section only deals with display planes.
+ * Leave cursor, VGA, overlay, sprite planes alone since they will
+ * need a different disable bit/sequence.
+ */
+ temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg);
+ if ((plane->plane_features & IGD_PLANE_DISPLAY)) {
+ i = 0x71008; /* PIPE B */
+ if (temp & BIT31) {
+ if(plane->plane_reg == DSPACNTR) {
+ temp = temp & device_data_tnc->plane_a_preserve;
+ i = 0x70008; /* use i as pipe_reg */
+ }
+ EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + plane->plane_reg);
+
+ /* The B-Spec is ambiguous on which register is the trigger.
+ * Testing has shown the the surface start address is the
+ * correct trigger to disable the plane.
+ */
+ EMGD_WRITE32(0, EMGD_MMIO(mmio)+plane->plane_reg+DSP_START_OFFSET);
+
+ /* Wait for VBLANK to ensure that the plane is really off */
+ wait_for_vblank_tnc(i);
+
+ EMGD_DEBUG("Plane disabled 0x%lx", plane->plane_reg);
+ }
+ } else if ((plane->plane_features & IGD_PLANE_CURSOR)) {
+ EMGD_WRITE32((temp & 0xffffffe8),
+ EMGD_MMIO(mmio) + plane->plane_reg);
+ EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
+ }
+
+ }
+
+ /* Turn off pipes */
+ pipe = NULL;
+ while ((pipe = md->dsp_get_next_pipe(context, pipe, 0)) != NULL) {
+ j = 0;
+
+ /* Is this really required? Just waited for vblank above 2 times */
+ wait_for_vblank_tnc(pipe->pipe_reg);
+
+ for (i = 0; i < 2; i++) {
+ temp = READ_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg);
+
+ if (temp & BIT31) {
+ /* Do not turn off Pipe B when shutting down */
+ if((context->device_context.power_state
+ == IGD_POWERSTATE_UNDEFINED) &&
+ (pipe->pipe_reg == PIPEB_CONF)){
+ continue;
+ }
+ WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg,
+ (temp & device_data_tnc->pipe_preserve));
+
+ /* Gen4 can check when the pipe is disabled. */
+ wait_pipe(ports_tnc[i], pipe->pipe_reg, 0);
+
+ /* Disable VGA display */
+ disable_vga_tnc(EMGD_MMIO(mmio));
+
+ }
+
+ /* If current pipe is for sDVO, then iterate for PIPE B in
+ * both 0:2:0 LNC and 0:3:0 Atom E6xx devices */
+ if (pipe->pipe_reg == 0x70008L) {
+ break;
+ }
+ }
+ /* Disable DPLL:
+ * LVDS: LNC 0xF014
+ * SDVO: Atom E6xx 0x6018 */
+ temp = READ_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control);
+
+ if (temp & BIT31) {
+ WRITE_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control,
+ temp & ~BIT31);
+ }
+ j++;
+ }
+ /* pipes and DPLLs are off, now set the power for TV */
+ if(tv_port && tv_port->pd_driver) {
+ tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3);
+ }
+
+ EMGD_TRACE_EXIT;
+} /* end reset_plane_pipe_ports */
+
+
+void shutdown_ST_bridge(igd_context_t *context) {
+ platform_context_tnc_t *platform_context = context->platform_context;
+
+ if (!platform_context->stbridgedev) {
+ return;
+ }
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, 0x0106007E);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2000, 0x80);
+
+ pd_usleep(20);
+}
+
+void initialize_ST_bridge(igd_context_t *context, igd_display_port_t *port) {
+ platform_context_tnc_t *platform_context = context->platform_context;
+ pd_port_status_t port_status;
+ unsigned long tempreg;
+ unsigned char cmdreg;
+ unsigned long val;
+ unsigned long port_output = 0x04000000;
+ int ret;
+
+ if (!platform_context->stbridgedev) {
+ return;
+ }
+
+ /* call pd_get_port_status() if exists */
+ if (port && port->pd_driver && port->pd_driver->pd_get_port_status) {
+ ret = port->pd_driver->pd_get_port_status(port->pd_context, &port_status);
+ if (ret == PD_SUCCESS) {
+ if (port_status.display_type == PD_DISPLAY_LVDS_EXT) {
+ port_output = 0x02000000;
+ }
+ }
+ }
+
+ tempreg = READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x20);
+ tempreg |= 0xFFFFFF00;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x20, tempreg);
+
+ tempreg = READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x1020);
+ tempreg |= 0x7;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x1020, tempreg);
+
+ tempreg = READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x10);
+ tempreg |= 0x6;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x10, tempreg);
+
+ tempreg = READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x4);
+ tempreg |= 0x6;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST_GPIO,0x4, tempreg);
+
+ OS_PCI_READ_CONFIG_8((os_pci_dev_t)platform_context->stbridgedev, 0x4, &cmdreg);
+ cmdreg |= 0x7;
+ OS_PCI_WRITE_CONFIG_8((os_pci_dev_t)platform_context->stbridgedev, 0x4, cmdreg);
+
+ OS_PCI_READ_CONFIG_8((os_pci_dev_t)platform_context->stgpiodev, 0x4, &cmdreg);
+ cmdreg |= 0x7;
+ OS_PCI_WRITE_CONFIG_8((os_pci_dev_t)platform_context->stgpiodev, 0x4, cmdreg);
+
+ OS_PCI_READ_CONFIG_8((os_pci_dev_t)platform_context->pcidev1, 0x4, &cmdreg);
+ cmdreg |= 0x7;
+ OS_PCI_WRITE_CONFIG_8((os_pci_dev_t)platform_context->pcidev1, 0x4, cmdreg);
+
+ /* Write DB control values */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, 0x0106007E);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2000, 0x00000000);
+ pd_usleep(20);
+
+ /* Put Display Bridge in Reset */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, 0x00F8003E | port_output);
+ pd_usleep(20);
+
+ /* SDVO PHY startup sequence */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2800, READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2800) | 0x00000080);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2900, READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2900) | 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2400, READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2400) | 0x00000080);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2500, READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2500) | 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2054, 0x00000063);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2454, 0x00000063);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2854, 0x00000063);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2044, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2444, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2844, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2040, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2440, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2840, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2080, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2480, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2880, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2148, 0x00000050);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2144, 0x00000002);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2000, 0x00000086);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2104, 0x00000020);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2108, 0x0000002B);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2100, 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x20C0, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x24C0, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x28C0, 0x00000000);
+ pd_usleep(20);
+
+ do {
+ pd_usleep(20);
+ val = READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2100);
+ } while ((val & 0xC) != 0xC);
+
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2000, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2140, 0x0000008D);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2400, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2800, 0x00000000);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x200C, 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2010, 0x0000007F);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x240C, 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2410, 0x0000007F);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x280C, 0x00000013);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2810, 0x0000007F);
+ pd_usleep(20);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2080, 0x00000001);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2480, 0x00000001);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2880, 0x00000001);
+ pd_usleep(20);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2084, 0x0000000F);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2484, 0x0000000F);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2884, 0x0000000F);
+ pd_usleep(20);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2040, 0x00000004);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2440, 0x00000004);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2840, 0x00000004);
+ pd_usleep(20);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2044, 0x00000014);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2444, 0x00000014);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2844, 0x00000014);
+ pd_usleep(20);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2054, 0x0000002B);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2454, 0x0000002B);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x2854, 0x0000002B);
+ pd_usleep(20);
+
+ /*
+ * Enable interrupts. It is optional per STM. Include this line only
+ * when interrupt handler with functionality is implemented for Display
+ * Bridge.
+ */
+ //WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x10, 0x00FC0000);
+ //pd_usleep(20);
+
+ /* Release Reset from Control register */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, 0x00F80030 | port_output);
+ pd_usleep(20);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, 0x00F80000 | port_output);
+ pd_usleep(20);
+
+ /* Increase driver strength in case OLDI output is enabled */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18, READ_MMIO_REG_TNC(IGD_PORT_SDVO_ST, 0x18) | 0x00001800);
+ pd_usleep(20);
+}
+
+/*!
+ * Status is currently not used
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int post_program_port_tnc(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ int ret;
+ igd_display_port_t *port;
+ igd_timing_info_t *timings;
+ unsigned long portreg; /* temp; */
+#ifndef CONFIG_MICRO
+ unsigned long pt = PORT_TYPE(display);
+#endif
+
+ EMGD_TRACE_ENTER;
+
+ port = PORT(display, port_number);
+ timings = PIPE(display)->timing;
+
+ /*
+ * The programming found in the common code for all chipsets
+ * has the device programming sequence as follows:
+ * Port
+ * Pipe
+ * Post Port
+ * Plane
+ * On Gen4, if the port is enabled before the pipe, there is a 10%
+ * chance that the port will not turn on properly.
+ * Due to compatability requires with other chipsets, this workaround
+ * fixes this issue
+ */
+ portreg = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
+ WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg & ~BIT31);
+ WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg);
+
+ if (port->port_type == IGD_PORT_SDVO) {
+ initialize_ST_bridge(display->context, port);
+ }
+
+ ret = 0;
+ /* call post_set_mode() if exists */
+ if (port->pd_driver->post_set_mode) {
+ #ifndef CONFIG_MICRO
+ if (pt == IGD_PORT_SDVO){
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ status); /*Needed for LAPIS*/
+ } else {
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ 1<<PIPE(display)->pipe_num);
+ }
+ #else
+ ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+ 1<<PIPE(display)->pipe_num);
+ #endif
+ if (ret) {
+ EMGD_ERROR_EXIT("PD post_set_mode returned: 0x%x", ret);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int program_port_sdvo_tnc(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ unsigned long port_control;
+ unsigned long pd_powerstate = PD_POWER_MODE_D3;
+ unsigned long preserve = 0;
+ unsigned long upscale = 0;
+ igd_timing_info_t local_timing;
+ igd_timing_info_t *timing;
+ unsigned long temp;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program Port: (%s)", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("pd_flags: 0x%lx", PORT(display, port_number)->pd_flags);
+
+ timing = PIPE(display)->timing;
+
+ port_control = preserve & READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PORT(display, port_number)->port_reg);
+
+ if (status == TRUE) {
+ if (!(PORT(display, port_number)->pt_info->flags &
+ IGD_DISPLAY_ENABLE)) {
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ /* Enable VGA syncs for native vga modes */
+ if (PORT(display, port_number)->vga_sync == 1) {
+ EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
+ if((timing->width == 720) && (timing->height == 400)) {
+ EMGD_DEBUG("Modify port control and multi_port_control");
+ port_control |= (1L<<15);
+ }
+ }
+
+ /* Fact that both IGD_ powerstates and PD_ powermodes have
+ * same definitions */
+ pd_powerstate = GET_DISPLAY_POWER_STATE(display, port_number);
+
+ if (pd_powerstate == IGD_POWERSTATE_D0) {
+ EMGD_DEBUG("Power State: D0");
+ /* Upscale */
+ pi_pd_find_attr_and_value(PORT(display, port_number),
+ PD_ATTR_ID_PANEL_FIT,
+ 0, /*no PD_FLAG for UPSCALING */
+ NULL, /* dont need the attr ptr*/
+ &upscale);
+
+ /* Reach the end timing if upscaling is enabled */
+ if (timing->extn_ptr && upscale) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+
+ local_timing = *timing;
+ if (upscale) {
+ /* For timings smaller than width 360 and height 200,
+ * double the size. This is because the active area of the mode
+ * is double the size of the resolution for these modes
+ * - Very tricky huh */
+ if (local_timing.width <= 360) {
+ local_timing.width <<= 1;
+ }
+ if (local_timing.height <= 200) {
+ local_timing.height <<= 1;
+ }
+ }
+
+ /* BIT31 - Enable
+ * BIT30 - PIPE B
+ * BIT29 - Stall
+ * BIT7 - Border
+ */
+ port_control |= BIT31|BIT30|BIT29|BIT7;
+
+ /* Program cDVO registers:
+ * Keep default values for
+ * 7000h - cDVO control register
+ * 7004h - cDVO slew rate register
+ * 7008h - cDVO strength register
+ * 700Ch - cDVO RCOMP update register
+ * 6102Ch - cDVO stall register = 0xA.
+ * Note: Though EAS says 6102Ch default value is 6, it is a typo
+ * in the spec, based on Si DE hw default value is 10 (0xA),
+ * so no need to program explicitly. This saves few bytes for
+ * micro.
+ */
+
+ /* Enable Current Source */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
+ temp |= 0x2000;
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
+ }
+ }
+
+ if (pd_powerstate == PD_POWER_MODE_D0) {
+ ret = PORT(display, port_number)->pd_driver->set_mode(
+ PORT(display, port_number)->pd_context, &local_timing, 0);
+ } else {
+ ret = PORT(display, port_number)->pd_driver->set_power(
+ PORT(display, port_number)->pd_context, pd_powerstate);
+ }
+
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+ (pd_powerstate == PD_POWER_MODE_D0)?"mode":"power", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Port_control: 0x%lx", port_control);
+
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+ PORT(display, port_number)->port_reg, port_control);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int program_port_lvds_tnc(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ int ret = 0;
+ unsigned long powerstate = PD_POWER_MODE_D3;
+ pd_timing_t *timing;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Program LVDS: (%s)", status?"ENABLE":"DISABLE");
+
+ if (status == TRUE) {
+ if(!(PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+ powerstate = GET_DISPLAY_POWER_STATE(display,port_number);
+ if (powerstate == IGD_POWERSTATE_D0) {
+ EMGD_DEBUG("Power State: D0");
+ timing = (pd_timing_t *)PIPE(display)->timing;
+ /* Reach end timing to get user resolution and pass it to pd */
+ if(timing->extn_ptr) {
+ timing = (pd_timing_t *)timing->extn_ptr;
+ }
+ /* set mode will take care of port control */
+ ret = PORT(display, port_number)->pd_driver->set_mode(
+ PORT(display, port_number)->pd_context,
+ timing,
+ 1<<PIPE(display)->pipe_num);
+ }
+ }
+
+ /* either status == FALSE, or status == TRUE, but powerstate is D1/D2/D3 */
+ if (powerstate != IGD_POWERSTATE_D0) {
+ ret = PORT(display, port_number)->pd_driver->set_power(
+ PORT(display, port_number)->pd_context,
+ PD_POWER_MODE_D3);
+ }
+
+ if (ret) {
+ EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+ (powerstate == IGD_POWERSTATE_D0)?"mode":"power", ret);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+/*!
+ *
+ * @param display
+ * @param port_number
+ * @param status
+ *
+ * @return program_port_lvds_gen4()
+ * @return program_port_sdvo_gen4()
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int program_port_tnc(igd_display_context_t *display,
+ unsigned short port_number,
+ unsigned long status)
+{
+ EMGD_TRACE_ENTER;
+
+ if (PORT(display, port_number)->port_type == IGD_PORT_LVDS) {
+ EMGD_TRACE_EXIT;
+ return program_port_lvds_tnc(display, port_number, status);
+ } else {
+ EMGD_TRACE_EXIT;
+ return program_port_sdvo_tnc(display, port_number, status);
+ }
+}
+
+/*!
+ *
+ * @param gpio
+ *
+ * @return size
+ */
+unsigned long get_gpio_sets_tnc(unsigned long **gpio)
+{
+ /* To small to trace */
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param in_list
+ *
+ * @return void - To small to trace
+ */
+void filter_modes_tnc(igd_context_t *context, igd_display_port_t *port,
+ pd_timing_t *in_list)
+{
+ while (in_list->width != IGD_TIMING_TABLE_END) {
+ /* TC LVDS:
+ * supports from 19.75MHz to 79.MHz
+ * TC SDVO:
+ * supports from 25 MHz to 160 MHz and progressive only.
+ */
+ if (port->port_type == IGD_PORT_SDVO) {
+ if (in_list->mode_info_flags & IGD_SCAN_INTERLACE ||
+ in_list->dclk < 25000 || in_list->dclk > 160000) {
+ in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED;
+ }
+ }
+ /* No clock check is required for LVDS port as LVDS port driver
+ * already taken care of this.
+ if (port->port_type == IGD_PORT_LVDS) {
+ if (in_list->dclk < 19750 || in_list->dclk > 79500) {
+ in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED;
+ }
+ }*/
+ in_list++;
+ if (in_list->width == IGD_TIMING_TABLE_END && in_list->extn_ptr) {
+ in_list = in_list->extn_ptr;
+ }
+ }
+ return;
+}
+#ifndef CONFIG_MICRO
+int get_timing_tnc(igd_display_context_t *display, pd_timing_t *in_list)
+{
+ //int ret = TRUE;
+ igd_timing_info_t *pTimings_ori;
+ pd_timing_t *timing = NULL;
+ timing = in_list;
+
+ EMGD_TRACE_ENTER;
+ pTimings_ori = PIPE(display)->timing;
+
+ if(display->port_number != 2){
+ EMGD_DEBUG("Port does not need tuning");
+ EMGD_TRACE_EXIT;
+ return FALSE;
+ }
+
+ while(timing->width != PD_TIMING_LIST_END) {
+
+ if((timing->width == pTimings_ori->width) &&
+ (timing->height == pTimings_ori->height) &&
+ (timing->refresh == pTimings_ori->refresh)){
+ EMGD_DEBUG("Timing found");
+ timing->reserved_dd = pTimings_ori->reserved_dd;
+ timing->mode_info_flags = pTimings_ori->mode_info_flags;
+
+ /* also return the hblank_end so that ioctl can calculate
+ * the xblank_length.
+ */
+ timing->hblank_end = pTimings_ori->hblank_end;
+ timing->vblank_end = pTimings_ori->vblank_end;
+
+
+ }
+ /* Go through the table list */
+ timing++;
+ if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+int check_port_supported(void *port_tmp)
+{
+ //igd_display_port_t *port = (igd_display_port_t *)port_tmp;
+ /* Determine which port driver is supported by Atom E6xx */
+#if 0 //Pendng confirmation from LNC architect
+ if(pd_driver->type & PD_DISPLAY_TVOUT){
+ return 1;
+ }
+#endif
+ return 0;
+}
+#endif
+
+/* Function checks if the incoming user DTD is one of the timings
+ * in the crt_timing_table that has border. Meaning that the
+ * h_blank_end is not the same as htotal.
+ * We only see this issue when reading a user DTD generated for
+ * harmonic which is derived from crt_timing_table. pi module
+ * only handles user DTD which does not have borders.
+ */
+int get_refresh_in_border(pd_timing_t *in_list)
+{
+ /* return 1 if refresh is obtained */
+
+ if(in_list->width == 640 &&
+ in_list->height == 480 &&
+ in_list->dclk == 25175 &&
+ in_list->hsync_start == 655 &&
+ in_list->hsync_end == 751 &&
+ in_list->vsync_start == 489 &&
+ in_list->vsync_end == 491){
+ in_list->refresh = 60;
+ in_list->htotal = 799;
+ in_list->vtotal = 524;
+ in_list->hblank_start = 646;
+ in_list->vblank_start = 486;
+ return 1;
+ }
+
+ if(in_list->width == 640 &&
+ in_list->height == 480 &&
+ in_list->dclk == 31500 &&
+ in_list->hsync_start == 663 &&
+ in_list->hsync_end == 703 &&
+ in_list->vsync_start == 488 &&
+ in_list->vsync_end == 491){
+
+ in_list->refresh = 72;
+ in_list->htotal = 831;
+ in_list->vtotal = 519;
+ in_list->hblank_start = 646;
+ in_list->vblank_start = 486;
+ return 1;
+ }
+
+
+ return 0;
+}
+
+/*
+ * Function to check if dc is switching from
+ * SDVO single to clone/extended mode
+ * Tunnel Creek B0 needs tuning when there are 2 planes,
+ * if true, it will force alter to run tuning
+ */
+bool dsp_is_force_alter_required_tnc(igd_display_context_t *display,
+ unsigned long current_dc, unsigned long dc_to_set){
+
+ if ((IGD_DC_SINGLE(current_dc) &&
+ (IGD_DC_PRIMARY(current_dc) == IGD_PORT_TYPE_SDVOB )) &&
+ (IGD_DC_CLONE(dc_to_set) || IGD_DC_EXTENDED(dc_to_set)) &&
+ (display->context->device_context.rid == TNC_B0_RID)){
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+mode_dispatch_t mode_dispatch_tnc = {
+ igd_set_palette_entry_tnc,
+ igd_get_palette_entry_tnc,
+ igd_wait_vblank_tnc,
+ program_plane_tnc,
+ program_pipe_tnc,
+ program_port_tnc,
+ post_program_port_tnc,
+ program_clock_tnc,
+ program_cdvo_tnc,
+ reset_plane_pipe_ports_tnc,
+ get_gpio_sets_tnc,
+ filter_modes_tnc,
+ OPT_MICRO_VALUE(check_display_tnc, NULL),
+ OPT_MICRO_VALUE(get_timing_tnc, NULL),
+ OPT_MICRO_VALUE(check_port_supported, NULL),
+ OPT_MICRO_VALUE(get_refresh_in_border, NULL),
+ OPT_MICRO_VALUE(dsp_is_force_alter_required_tnc, NULL),
+ OPT_MICRO_VALUE(&mode_full_dispatch_tnc, NULL),
+};
+
+/* VBIOS does not use the virtual mapped address
+ * This function will return 0 for VBIOS anyway */
+#ifndef CONFIG_MICRO
+unsigned char *get_mmio_tnc(unsigned long port_type)
+{
+ unsigned char *virt_mmio;
+ if (port_type == IGD_PORT_LVDS) {
+ virt_mmio = mode_context->context->device_context.virt_mmadr;
+ } else if (port_type == IGD_PORT_SDVO) {
+ virt_mmio = mode_context->context->device_context.virt_mmadr_sdvo;
+ } else if (port_type == IGD_PORT_SDVO_ST) {
+ virt_mmio = mode_context->context->device_context.virt_mmadr_sdvo_st;
+ } else if (port_type == IGD_PORT_SDVO_ST_GPIO) {
+ virt_mmio = mode_context->context->device_context.virt_mmadr_sdvo_st_gpio;
+ } else {
+ /* i2c_bitbash will use the else condition by passing in port_type
+ * as '0' */
+ virt_mmio = mode_context->context->device_context.virt_gpio_bar;
+ }
+ return virt_mmio;
+}
+#endif
+
+/* Function to read Atom E6xx 0:2:0, 0:3:0 and 0:31:0 mmio registers */
+unsigned long read_mmio_reg_tnc(unsigned long port_type, unsigned long reg)
+{
+ unsigned long value;
+#ifndef CONFIG_MICRO
+ unsigned char *mmio;
+#endif
+
+ /* to avoid updating or having another set of read/write macros for
+ * vbios, overwrite io_base to properly read from 0:2:0/0:3:0/0:31:0
+ * io_base and set it back after reading */
+ if (port_type == IGD_PORT_LVDS) {
+ io_base = io_base_lvds;
+ } else if (port_type == IGD_PORT_SDVO) {
+ io_base = io_base_sdvo;
+ } else if (port_type == IGD_PORT_LPC) {
+ io_base = io_base_lpc;
+ } else if (port_type == IGD_PORT_SDVO_ST) {
+ io_base = io_base_sdvo_st;
+ }
+ OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type));
+ if (port_type == IGD_PORT_LPC) {
+ value = EMGD_READ_PORT32(io_base_lpc + reg);
+ } else {
+ value = EMGD_READ32(EMGD_MMIO(mmio) + reg);
+ }
+
+ io_base = io_base_lvds;
+ return value;
+}
+
+/* Function to write Atom E6xx 0:2:0 and 0:3:0 mmio registers */
+void write_mmio_reg_tnc(unsigned long port_type, unsigned long reg,
+ unsigned long value)
+{
+#ifndef CONFIG_MICRO
+ unsigned char *mmio;
+#endif
+
+ /* to avoid updating or having another set of read/write macros for
+ * vbios, overwrite io_base to properly read from 0:2:0/0:3:0 io_base
+ * and set it back after writing */
+ if (port_type == IGD_PORT_LVDS) {
+ io_base = io_base_lvds;
+ } else if (port_type == IGD_PORT_SDVO) {
+ io_base = io_base_sdvo;
+ } else if (port_type == IGD_PORT_LPC) {
+ io_base = io_base_lpc;
+ } else if (port_type == IGD_PORT_SDVO_ST) {
+ io_base = io_base_sdvo_st;
+ }
+
+ OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type));
+ if (port_type == IGD_PORT_LPC) {
+ EMGD_WRITE_PORT32(io_base_lpc + reg, value);
+ } else {
+ EMGD_WRITE32(value, EMGD_MMIO(mmio) + reg);
+ }
+ io_base = io_base_lvds;
+ return;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
new file mode 100644
index 0000000..13f8613
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
@@ -0,0 +1,2219 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_tnc.c
+ * $Revision: 1.36 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Atom E6xx implementations for the mode dispatch functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd.h>
+#include <igd_pwr.h>
+
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+#include <dsp.h>
+#include <intelpci.h>
+#include <mode_access.h>
+#include <rb.h>
+#include <pi.h>
+#include <math_fix.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/mi.h>
+#include <tnc/instr.h>
+#include <tnc/cmd.h>
+
+#include "drm_emgd_private.h"
+#include "../cmn/match.h"
+#include "../cmn/mode_dispatch.h"
+
+#include "emgd_shared.h"
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <drm/drmP.h>
+
+#include <emgd_drm.h>
+
+/* Get this table from clocks_tnc.c, use this in get_pipe_info */
+extern unsigned long lvds_m_converts[];
+extern unsigned long LVDS_M_CONVERTS_LEN;
+
+/* This is a duplicate define of the same constant in clocks_tnc.c.
+ * Redefined it here because there's no good TNC-specific common header
+ * file to put this in */
+#define LVDS_M_MIN 10
+
+
+/* Registered VBlank interrupt callbacks (one-per-pipe): */
+static emgd_vblank_callback_t interrupt_callbacks_tnc[IGD_MAX_PORTS] =
+ {{NULL,NULL,0},{NULL,NULL,1},{NULL,NULL,2},{NULL,NULL,3},{NULL,NULL,4}};
+
+/* This variable contains a number of bits, which tell whether the interrupt
+ * code has enabled interrupts, and if so, for what software and for what
+ * port(s); and whether certain events have happened.
+ */
+static unsigned long vblank_interrupt_state = 0;
+
+/* This variables keeps track of the number of clients currently using
+ * the vblank interrupt
+ */
+static int vblank_interrupt_ref_cnt_port2 = 0;
+static int vblank_interrupt_ref_cnt_port4 = 0;
+
+/* Spin lock for synchronization of the vblank_interrupt_state variable,
+ * between the VBlank interrupt handler and the non-interrupt handler code:
+ */
+DEFINE_SPINLOCK(vblank_lock_tnc);
+
+
+
+int set_flip_pending_tnc(unsigned char *mmio, unsigned long pipe_status_reg);
+int check_flip_pending_tnc(unsigned char *mmio, unsigned long pipe_status_reg);
+unsigned long get_port_control_tnc(unsigned long port_num, unsigned long port_reg);
+
+/* KMS callback from emgd_crtc.c */
+int crtc_pageflip_handler(struct drm_device *dev, int port);
+void notify_userspace_vblank(struct drm_device *dev, int port);
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+int mode_get_stride_stereo_tnc(igd_display_context_t *display,
+ unsigned long *stride, unsigned long *stereo, unsigned long flags);
+
+
+
+/*!
+ *
+ * @param display
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_tnc(igd_display_context_t *display)
+{
+ const int MID_PIXEL_VAL = 125;
+ const int MAX_PIXEL_VAL = 255;
+ const int NUM_PALETTE_ENTRIES = 256;
+
+ unsigned int gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+ unsigned int gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+ unsigned int gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+ unsigned int new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+ unsigned int new_gamma_b_24i_8f;
+ unsigned int gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ int brightness_factor_r, brightness_factor_g;
+ int brightness_factor_b;
+ int contrast_factor_r, contrast_factor_g;
+ int contrast_factor_b;
+
+ unsigned int *palette;
+ unsigned int i;
+
+ igd_range_attr_t *gamma_attr = NULL, *contrast_attr = NULL;
+ igd_range_attr_t *brightness_attr = NULL;
+ igd_attr_t *hal_attr_list = PORT_OWNER(display)->attributes;
+
+ EMGD_TRACE_ENTER;
+
+ /* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+ palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+ /* start with a fresh palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ palette[i] = (i << 16) | (i << 8) | i;
+ }
+
+ /* get a pointer to gamma, contrast, and brightness attr */
+ i = 0;
+
+ while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+ switch (hal_attr_list[i].id) {
+ case PD_ATTR_ID_FB_GAMMA:
+ gamma_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_BRIGHTNESS:
+ brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ case PD_ATTR_ID_FB_CONTRAST:
+ contrast_attr = (igd_range_attr_t *) &hal_attr_list[i];
+ break;
+
+ default:
+ break;
+ }
+
+ i++;
+ }
+
+ if(!gamma_attr || !brightness_attr || !contrast_attr) {
+ EMGD_ERROR_EXIT("Color Correction Atrributes not found!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get the max and min */
+ gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+ gamma_g_max_24i_8f = ((gamma_attr->max >> 8) & 0xFF) << 3;
+ gamma_b_max_24i_8f = (gamma_attr->max & 0xFF) << 3;
+
+ gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+ gamma_g_min_24i_8f = ((gamma_attr->min >> 8) & 0xFF) << 3;
+ gamma_b_min_24i_8f = (gamma_attr->min & 0xFF) << 3;
+
+ /* The new gamma values are in 3i.5f format, but we must convert it
+ * to 24i.8f format before passing it to OS_POW_FIX
+ */
+ new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+ new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+ new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+ /* make sure the new gamma is within range */
+ new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+ new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+ new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+ new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+ gamma_normal_r_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+ gamma_normal_g_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+ gamma_normal_b_24i_8f =
+ OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ unsigned int new_gamma;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* Note that we do not try to calculate the gamma if it
+ * is 1.0, e.g. 0x100. This is to avoid round-off errors
+ */
+
+ /* red: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_r_24i_8f) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+ palette[i] &= 0x00FFFF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_g_24i_8f) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+ palette[i] &= 0xFF00FF;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0x100 != new_gamma_b_24i_8f) {
+ cur_color = cur_palette & 0xFF;
+ new_gamma = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+ new_gamma = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+ palette[i] &= 0xFFFF00;
+ palette[i] |=
+ (OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+ }
+ }
+
+
+ /* Brightness correction */
+ brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+ brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+ brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+ /* The factors are offset by 0x80 because 0x80 is 0 correction */
+ brightness_factor_r -= 0x80;
+ brightness_factor_g -= 0x80;
+ brightness_factor_b -= 0x80;
+
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_r;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+ /* green: calculate and make sure the result is within range */
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_g;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF;
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+ /* blue: calculate and make sure the result is within range */
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val = cur_color + brightness_factor_b;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00;
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+
+
+ /* contrast correction */
+ contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+ contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+ contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+ /* make sure values are within range */
+ contrast_factor_r -= 0x80;
+ contrast_factor_g -= 0x80;
+ contrast_factor_b -= 0x80;
+
+
+ /* We're doing integer division in this loop using 16i.16f
+ * integers. The result will then be converted back into a
+ * regular, 32-bit integer
+ */
+ for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+ int new_pixel_val;
+ unsigned int cur_color;
+ unsigned int cur_palette = palette[i];
+
+ /* red: calculate and make sure the result is within range */
+ if (0 != contrast_factor_r ) {
+ cur_color = (cur_palette >> 16) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0x00FFFF; /* clear out the R color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+ }
+
+ /* green: calculate and make sure the result is within range */
+ if (0 != contrast_factor_g ) {
+ cur_color = (cur_palette >> 8) & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFF00FF; /* clear out the G color */
+ palette[i] |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+ }
+
+ /* blue: calculate and make sure the result is within range */
+ if (0 != contrast_factor_b) {
+ cur_color = cur_palette & 0xFF;
+ new_pixel_val =
+ (MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+ new_pixel_val = new_pixel_val * (cur_color - MID_PIXEL_VAL);
+ new_pixel_val >>= 16; /* convert back to 32i format */
+ new_pixel_val += MID_PIXEL_VAL;
+ new_pixel_val = OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+ palette[i] &= 0xFFFF00; /* clear out the B color */
+ palette[i] |= OS_MAX(new_pixel_val, 0) & 0xFF;
+ }
+ }
+
+
+ /* write the new values in the palette */
+ for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+ /* SDVO palette register is not accesible */
+ EMGD_WRITE32(palette[i],
+ MMIO_TNC(IGD_PORT_LVDS) +
+ PIPE(display)->palette_reg + i*4);
+ }
+
+ OS_FREE(palette);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param display
+ * @param fb
+ * @param x
+ * @param y
+ *
+ * @return 0
+ */
+static int set_display_base_tnc(igd_display_context_t *display,
+ igd_framebuffer_info_t *fb, unsigned long *x, unsigned long *y)
+{
+ unsigned long reg;
+ unsigned long temp;
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG ("Pan linear to (%lu,%lu)", *x, *y);
+
+ /* Update framebuffer's visible offset */
+ PLANE(display)->fb_info->visible_offset =
+ ((*y * fb->screen_pitch) + (*x * IGD_PF_BYPP(fb->pixel_format)));
+
+ temp = PLANE(display)->fb_info->visible_offset;
+ EMGD_DEBUG ("visible offset = %lx",temp );
+ if(PLANE(display)->fb_info->lock) {
+
+ EMGD_DEBUG ("Plane is locked");
+ reg = (unsigned long)READ_MMIO_REG(display, PLANE(display)->plane_reg- 4);
+ EMGD_DEBUG("Plane B start addr = %lx", reg);
+ reg = (unsigned long)READ_MMIO_REG(display,PLANE(display)->plane_reg + 4);
+ EMGD_DEBUG("Plane B start offset = %lx", reg);
+
+ } else {
+ /* Plane registers are always on 0:2:0 */
+ WRITE_MMIO_REG(display, PLANE(display)->plane_reg + DSP_LINEAR_OFFSET,
+ PLANE(display)->fb_info->visible_offset);
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This function alters the position parameters associated with a cursor.
+ *
+ * @param display_handle
+ * @param cursor_info
+ *
+ * @return 0
+ */
+static int igd_alter_cursor_pos_tnc(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info)
+{
+ unsigned long cursor_reg;
+ unsigned long new_pos;
+ unsigned long cursor_base;
+
+ igd_display_context_t *display = (igd_display_context_t *) display_handle;
+ cursor_reg = PIPE(display)->cursor->cursor_reg;
+
+ /* To Fast For Tracing */
+
+ /* Plane registers are always on 0:2:0 device */
+ if (0x27 & READ_MMIO_REG(display, cursor_reg)) {
+ /* unlike almador, for Gen4, u must program the base offset
+ to trigger the position update. However, this also means we
+ accidentally enable an invalid cursor surface if the cursor
+ was not enabled already. So do this check first */
+
+ /*
+ * Encode the cursor position in the format required for the
+ * cursor position register.
+ */
+ if(cursor_info->y_offset >= 0) {
+ new_pos = (cursor_info->y_offset << 16);
+ } else {
+ new_pos = ((-(cursor_info->y_offset)) << 16) | 0x80000000;
+ }
+ if(cursor_info->x_offset >= 0) {
+ new_pos |= (cursor_info->x_offset);
+ } else {
+ new_pos |= (-(cursor_info->x_offset)) | 0x00008000;
+ }
+
+ cursor_base = READ_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET);
+
+ WRITE_MMIO_REG(display, cursor_reg + CUR_POS_OFFSET, new_pos);
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+ }
+
+ return 0;
+}
+
+/*!
+ * The assumption here is that palette_colors points to index 0 and
+ * this function indexes into the palette_colors array by start_index
+ *
+ * @param display_handle
+ * @param palette_colors
+ * @param start_index
+ * @param count
+ *
+ * @return 0
+ */
+static int igd_set_palette_entries_tnc(
+ igd_display_h display_handle,
+ unsigned long *palette_colors,
+ unsigned int start_index,
+ unsigned int count)
+{
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ for(i=start_index; i<start_index+count; i++) {
+ /* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
+ WRITE_MMIO_REG_TNC(IGD_PORT_LVDS,
+ PIPE(display_handle)->palette_reg + i*4, palette_colors[i]);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * This procedure waits for the next vertical sync
+ * period. If the display is already in a vertical sync period, this
+ * procedure exits.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param display_handle
+ * @param palette_colors
+ * @param start_index
+ * @param count
+ *
+ * @return FALSE - if timed out
+ */
+static int igd_wait_vsync_tnc(igd_display_h display_handle)
+{
+ unsigned long tmp;
+ unsigned long status_reg;
+ os_alarm_t timeout;
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ status_reg = PIPE(display)->pipe_reg + PIPE_STATUS_OFFSET;
+
+ /* If pipe is off then just return */
+ if(!((1<<31) & READ_MMIO_REG_TNC(PORT_TYPE(display),
+ PIPE(display)->pipe_reg))) {
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ /* 1. Disable VSync interrupt */
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(PORT_TYPE(display), status_reg, tmp & ~(1<<25));
+
+ /* 2. Clear interrupt status (by writing a 1) */
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(PORT_TYPE(display), status_reg, tmp | (1<<9));
+
+ /* 3. Enable VSync interrupt */
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(PORT_TYPE(display), status_reg, tmp | (1<<25));
+ READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+
+ /* 4. Wait for VSync about 50 msec (20Hz) */
+ timeout = OS_SET_ALARM(50);
+ do {
+ OS_SCHEDULE();
+ /* Check for timeout */
+ } while (((READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg) & (1<<9)) ==
+ 0x00) &&
+ (!OS_TEST_ALARM(timeout)));
+
+ if (((READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg) & (1<<9)) ==
+ 0x00)) {
+ EMGD_ERROR_EXIT("Timeout waiting for VSYNC");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+ /* 5. Disable VSync interrupt */
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(PORT_TYPE(display), status_reg, tmp & ~(1<<25));
+
+ /* 6. Clear interrupt status (by writing a 1) */
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(PORT_TYPE(display), status_reg, tmp | (1<<9));
+ READ_MMIO_REG_TNC(PORT_TYPE(display), status_reg);
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* igd_wait_vsync*/
+
+/*!
+ *
+ * @param display_handle
+ * @param scanline
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_get_scanline_tnc(igd_display_h display_handle, int *scanline)
+{
+ unsigned int tmp;
+ unsigned long reg;
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned long fb_height = PLANE(display)->fb_info->height;
+ unsigned long dp_height = PIPE(display)->timing->height;
+
+ EMGD_TRACE_ENTER;
+
+ /* Scanline reg is -8 from control reg */
+ reg = PIPE(display)->pipe_reg - 0x8;
+
+ tmp = READ_MMIO_REG_TNC(PORT_TYPE_DH(display_handle), reg);
+
+ if(!(PORT_OWNER(display)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+ EMGD_DEBUG("Port off, can not get scanline");
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ tmp = (tmp * fb_height) / dp_height;
+
+ if(tmp >= fb_height) {
+ *scanline = IGD_IN_VBLANK;
+ } else {
+ *scanline = (int)tmp;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end igd_get_scanline() */
+
+/*!
+ *
+ * @param display_handle
+ *
+ * @return 1 if TRUE
+ * @return 0 if FALSE
+ */
+static int igd_query_in_vblank_tnc(igd_display_h display_handle)
+{
+ int sl;
+
+ /* To small for Tracing */
+
+ igd_get_scanline_tnc(display_handle, &sl);
+ if (sl == IGD_IN_VBLANK) {
+ return 1; /*TRUE*/
+ } else {
+ return 0; /*FALSE*/
+ }
+}
+
+/*!
+ * This function programs the cursor registers for Grantsdale
+ *
+ * @param display
+ * @param status
+ *
+ * @return void
+ */
+static void program_cursor_tnc(igd_display_context_t *display,
+ unsigned long status)
+{
+ unsigned long cursor_reg;
+ unsigned long cursor_control = 0x00000000;
+ unsigned long cursor_pos;
+ unsigned long cursor_base;
+ igd_cursor_info_t *cursor_info;
+ int i;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Program Cursor: %s", status?"ENABLE":"DISABLE");
+ EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+ cursor_reg = PIPE(display)->cursor->cursor_reg;
+ cursor_info = PIPE(display)->cursor->cursor_info;
+
+ /* Turn off cursor before changing anything */
+ /* planes are always on 0:2:0 device, so no need to use _TNC macros */
+ cursor_base = READ_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET);
+
+ WRITE_MMIO_REG(display, cursor_reg, cursor_control);
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+
+ if(cursor_info->flags & IGD_CURSOR_GAMMA) {
+ cursor_control |= BIT26;
+ }
+
+ cursor_info->argb_pitch = 64*4;
+ cursor_info->xor_pitch = 16;
+
+ /* Setting the cursor format/pitch */
+ switch(cursor_info->pixel_format) {
+ case IGD_PF_ARGB32:
+ cursor_control |= BIT5 | 0x7;
+ break;
+ case IGD_PF_RGB_XOR_2:
+ cursor_control |= 0x5;
+ break;
+ case IGD_PF_RGB_T_2:
+ cursor_control |= 0x4;
+ break;
+ case IGD_PF_RGB_2:
+ cursor_control |= 0x6;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid Pixel Format");
+ return;
+ }
+
+ switch(cursor_info->pixel_format) {
+ case IGD_PF_ARGB32:
+ cursor_base = cursor_info->argb_offset;
+ break;
+ default:
+ cursor_base = cursor_info->xor_offset;
+ break;
+ }
+
+ /* If status is FALSE return with the cursor off */
+ if((!status) || (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ if(cursor_info->y_offset >= 0) {
+ cursor_pos = cursor_info->y_offset << 16;
+ } else {
+ cursor_pos = ((-(cursor_info->y_offset)) << 16) | 0x80000000;
+ }
+ if(cursor_info->x_offset >= 0) {
+ cursor_pos |= cursor_info->x_offset;
+ } else {
+ cursor_pos |= (-(cursor_info->x_offset)) | 0x00008000;
+ }
+
+ WRITE_MMIO_REG(display, cursor_reg + CUR_POS_OFFSET,
+ cursor_pos);
+
+ for(i=0; i<4; i++) {
+ WRITE_MMIO_REG(display, cursor_reg + CUR_PAL0_OFFSET + i*4,
+ cursor_info->palette[i]);
+ }
+
+ cursor_control = cursor_control | (PIPE(display)->pipe_num<<28);
+
+ WRITE_MMIO_REG(display, cursor_reg, cursor_control);
+ WRITE_MMIO_REG(display, cursor_reg + CUR_BASE_OFFSET, cursor_base);
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param type
+ * @param surface
+ * @param appcontext
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_get_surface_tnc(igd_display_h display_handle,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext)
+{
+#if 0
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ state3d_tnc_t *state = STATE3D_TNC(appcontext);
+
+ EMGD_TRACE_ENTER;
+
+ if(!surface) {
+ EMGD_ERROR_EXIT("Surface is NULL");
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch(type) {
+ case IGD_BUFFER_DISPLAY:
+ surface->offset = PLANE(display)->fb_info->visible_offset;
+ surface->pitch = PLANE(display)->fb_info->screen_pitch;
+ surface->width = PLANE(display)->fb_info->width;
+ surface->height = PLANE(display)->fb_info->height;
+ surface->u_offset = 0;
+ surface->u_pitch = 0;
+ surface->v_offset = 0;
+ surface->v_pitch = 0;
+ surface->pixel_format = PLANE(display)->fb_info->pixel_format;
+ surface->palette_info = 0;
+ surface->flags = PLANE(display)->fb_info->flags;
+ surface->logic_ops = 0;
+ surface->render_ops = 0;
+ surface->alpha = 0;
+ surface->diffuse = 0;
+ surface->chroma_high = 0;
+ surface->chroma_low = 0;
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_COLOR:
+ OS_MEMCPY(surface, &state->color_buffer,
+ sizeof(igd_surface_t));
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_DEPTH:
+ OS_MEMCPY(surface, &state->depth_buffer,
+ sizeof(igd_surface_t));
+ EMGD_TRACE_EXIT;
+ return 0;
+ default:
+ EMGD_ERROR("Invalid type in get_surface");
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+#else
+ return 0;
+#endif
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param type
+ * @param surface
+ * @param appcontext
+ * @param flags
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_set_surface_tnc(igd_display_h display_handle,
+ int priority,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext,
+ unsigned long flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned int dsp_current;
+ unsigned long plane_reg;
+ unsigned long plane_control;
+ unsigned long visible_offset;
+
+ EMGD_TRACE_ENTER;
+ if(!surface) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch(type) {
+ case IGD_BUFFER_DISPLAY:
+ if(! (surface->flags & IGD_SURFACE_DISPLAY)) {
+ EMGD_ERROR_EXIT("Surface is not a display surface");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (PLANE(display)->plane_reg == DSPACNTR) {
+ EMGD_DEBUG("About to flip a buffer for display/pipe A");
+ dsp_current = 0;
+ } else {
+ EMGD_DEBUG("About to flip a buffer for display/pipe B");
+ dsp_current = 1;
+ }
+
+ if(flags & IGD_BUFFER_WAIT) {
+ /* If this is just a wait for flip, so return */
+ return 0;
+ }
+
+ /*
+ * Async flips only work when the offset is on a 256kb boundary.
+ */
+ if(surface->offset & 0x3ffff) {
+ EMGD_ERROR("Display surface offset %lu is not 256kb aligned", surface->offset);
+ }
+
+ if (flags & IGD_BUFFER_NO_PAN) {
+ /* Do not pan. Set visible_offset to zero */
+ visible_offset = 0;
+ } else {
+ /* calculate the visible offset, taking panning into account */
+ visible_offset =
+ (PORT_OWNER(display)->pt_info->y_offset * surface->pitch) +
+ (PORT_OWNER(display)->pt_info->x_offset *
+ IGD_PF_BYPP(surface->pixel_format));
+ }
+ EMGD_DEBUG("visible surface_offset = 0x%08lx", visible_offset);
+
+ /* Save new fb_info */
+ PLANE(display)->fb_info->fb_base_offset = surface->offset;
+ PLANE(display)->fb_info->visible_offset = visible_offset;
+ PLANE(display)->fb_info->screen_pitch = surface->pitch;
+ PLANE(display)->fb_info->width = surface->width;
+ PLANE(display)->fb_info->height = surface->height;
+ PLANE(display)->fb_info->pixel_format = surface->pixel_format;
+ PLANE(display)->fb_info->flags = surface->flags;
+
+ /* Get the correct stride and stereo */
+ /* TODO - Does Atom E6xx flip need to handle stereo mode? */
+ /*mode_get_stride_stereo_tnc(display, &stride, &stereo, 0);*/
+
+ /* plane registers are always on 0:2:0, so no need to use _TNC macros */
+ plane_reg = PLANE(display)->plane_reg;
+ plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+
+ /* Perform the flip by doing the following:
+ *
+ * Write the current plane_control value to the plane_reg
+ * Write the surface stride to DSP_STRIDE_OFFSET
+ * Write the visible from start of plane to DSP_LINEAR_OFFSET
+ * Write the base surface offset to either:
+ * 1) the plane_reg - 4 if async
+ * 2) plane_reg + DSP_START_OFFSET (+0x1C) if not async
+ */
+ if(!PLANE(display)->fb_info->lock){
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(surface->pitch,
+ MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
+ EMGD_WRITE32(visible_offset,
+ MMIO(display) + plane_reg + DSP_LINEAR_OFFSET);
+ EMGD_WRITE32(surface->offset,
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_COLOR:
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_DEPTH:
+ EMGD_TRACE_EXIT;
+ return 0;
+ case IGD_BUFFER_SAVE:
+ PLANE(display)->fb_info->saved_offset = surface->offset;
+ EMGD_DEBUG("saving surface_offset = 0x%08lx", surface->offset);
+ EMGD_TRACE_EXIT;
+ return 0;
+ default:
+ EMGD_ERROR("Invalid type in set_surface");
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/* Atom E6xx does not support a flip pending, since there is no
+ * Display Buffer Info instruction. So this must be done with vBlank.
+ * However, a wait_for_vblank can be given while a flip is also in
+ * progress, so a semaphore is required when changing flip_pending or
+ * when modifying the vBlank interrupt bits.
+ *
+ * This function should only be called with a flip_mutex around it */
+int set_flip_pending_tnc(unsigned char *mmio, unsigned long pipe_status_reg)
+{
+ platform_context_tnc_t *tnc_context =
+ (platform_context_tnc_t *)mode_context->context->platform_context;
+ unsigned long request_for;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT((pipe_status_reg == PIPEB_STAT) ||
+ (pipe_status_reg == PIPEA_STAT), "Invalid pipe_status_reg", 0);
+
+ if (pipe_status_reg == PIPEB_STAT) {
+ tnc_context->flip_pending |= PLB_FLIP_PIPE_B_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2);
+ } else {
+ tnc_context->flip_pending |= PLB_FLIP_PIPE_A_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4);
+ }
+ mode_context->dispatch->full->request_vblanks(request_for, mmio);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/* This function should only be called with a flip_mutex around it */
+int check_flip_pending_tnc(unsigned char *mmio,
+ unsigned long pipe_status_reg)
+{
+ platform_context_tnc_t *tnc_context =
+ (platform_context_tnc_t *)mode_context->context->platform_context;
+ unsigned long request_for;
+ unsigned int flip_pending;
+
+ EMGD_TRACE_ENTER;
+ EMGD_ASSERT((pipe_status_reg == PIPEB_STAT) ||
+ (pipe_status_reg == PIPEA_STAT), "Invalid pipe_status_reg", 0);
+
+ if (pipe_status_reg == PIPEB_STAT) {
+ flip_pending = tnc_context->flip_pending & PLB_FLIP_PIPE_B_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT2);
+ } else {
+ flip_pending = tnc_context->flip_pending & PLB_FLIP_PIPE_A_PENDING;
+ request_for = VBINT_REQUEST(VBINT_FLIP, VBINT_PORT4);
+ }
+
+ if (flip_pending) {
+ if (mode_context->dispatch->full->vblank_occured(request_for)) {
+ /* VBlank occured, flip complete */
+ tnc_context->flip_pending &= ~flip_pending;
+ mode_context->dispatch->full->end_request(request_for, mmio);
+ EMGD_DEBUG("VBlank occured--returning 0");
+ return 0;
+ } else {
+ /* VBlank not done, flip still in progress */
+ EMGD_DEBUG("VBlank hasn't yet occured--returning 1");
+ return 1;
+ }
+ } else {
+ /* No flip pending, so it must have completed */
+ EMGD_DEBUG("returning 0");
+ return 0;
+ }
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param event
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int igd_query_event_tnc(igd_display_h display_handle,
+ igd_event_t event, unsigned long *status)
+{
+ platform_context_tnc_t *tnc_context =
+ (platform_context_tnc_t *)mode_context->context->platform_context;
+ unsigned char *mmio = MMIO(display_handle);
+ unsigned long pipe_status_reg =
+ (PLANE(display_handle)->plane_reg == DSPACNTR) ? 0x70024 : 0x71024;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("mmio=0x%p, pipe_status_reg=0x%08lx", mmio, pipe_status_reg);
+
+ switch (event) {
+ case IGD_EVENT_FLIP_PENDING:
+ ret = OS_PTHREAD_MUTEX_LOCK(&tnc_context->flip_mutex);
+ *status = check_flip_pending_tnc(mmio, pipe_status_reg);
+ OS_PTHREAD_MUTEX_UNLOCK(&tnc_context->flip_mutex);
+ break;
+ default:
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Returning status=%lu", *status);
+ return IGD_SUCCESS;
+}
+
+/*!
+ *
+ * @param void
+ *
+ * @return 0
+ */
+static int get_plane_info_tnc(void)
+{
+ igd_framebuffer_info_t *buffer_info;
+ unsigned char* mmio = NULL;
+ unsigned long plane_control = 0;
+ unsigned long reg = 0;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ /* Check that plane A is active and process it */
+ plane_control = EMGD_READ32(mmio + DSPACNTR);
+ if(plane_control & PLANE_ENABLE){
+ buffer_info = &mode_context->fw_info->fb_info[0];
+
+ /* get the DSPASIZE register value */
+ reg = (unsigned long)EMGD_READ32(mmio + DSPACNTR + DSP_SIZE_OFFSET);
+ buffer_info[0].height = (reg >> 16) & 0xFFF;
+ buffer_info[0].width = reg & 0xFFF;
+
+ /* get the DSPASTRIDE register value */
+ buffer_info[0].screen_pitch =
+ (unsigned int)EMGD_READ32(mmio + DSPACNTR + DSP_STRIDE_OFFSET);
+
+ /* Following are NOT offset by 1 in fb info */
+ buffer_info[0].width++;
+ buffer_info[0].height++;
+ if((plane_control & (BIT27 | BIT30)) == (BIT27 | BIT30)){
+ buffer_info[0].pixel_format = PF_DEPTH_8;
+ }
+ if((plane_control & (BIT28 | BIT26)) == (BIT28 | BIT26)){
+ buffer_info[0].pixel_format = PF_DEPTH_16;
+ }
+ if((plane_control & (BIT28 | BIT27)) == (BIT28 | BIT27)){
+ buffer_info[0].pixel_format = PF_DEPTH_32;
+ }
+
+ EMGD_DEBUG("Plane A info height==%d, width=%d, pitch=%d", buffer_info[0].height, buffer_info[0].width, buffer_info[0].screen_pitch);
+ reg = (unsigned long)EMGD_READ32(mmio + DSPACNTR - 4);
+ EMGD_DEBUG("Plane A start addr = %lx", reg);
+ reg = (unsigned long)EMGD_READ32(mmio + DSPACNTR + 4);
+ EMGD_DEBUG("Plane A start offset = %lx", reg);
+ }
+
+ /* Check that plane B is active and process it */
+ plane_control = EMGD_READ32(mmio + DSPBCNTR);
+ if(plane_control & PLANE_ENABLE){
+ buffer_info = &mode_context->fw_info->fb_info[0];
+
+ /* get the DSPBSIZE register value */
+ reg = (unsigned long)EMGD_READ32(mmio + DSPBCNTR + DSP_SIZE_OFFSET);
+ buffer_info[1].height = (reg >> 16) & 0xFFF;
+ buffer_info[1].width = reg & 0xFFF;
+
+ /* get the DSPBSTRIDE register value */
+ buffer_info[1].screen_pitch =
+ (unsigned int)EMGD_READ32(mmio + DSPBCNTR + DSP_STRIDE_OFFSET);
+
+ /* Following are NOT offset by 1 in fb info */
+ buffer_info[1].width++;
+ buffer_info[1].height++;
+ if((plane_control & (BIT27 | BIT30)) == (BIT27 | BIT30)){
+ buffer_info[1].pixel_format = PF_DEPTH_8;
+ }
+ if((plane_control & (BIT28 | BIT26)) == (BIT28 | BIT26)){
+ buffer_info[1].pixel_format = PF_DEPTH_16;
+ }
+ if((plane_control & (BIT28 | BIT27)) == (BIT28 | BIT27)){
+ buffer_info[1].pixel_format = PF_DEPTH_32;
+ }
+
+ EMGD_DEBUG("Plane B info height==%d, width=%d, pitch=%d", buffer_info[1].height, buffer_info[1].width, buffer_info[1].screen_pitch);
+ reg = (unsigned long)EMGD_READ32(mmio + DSPBCNTR - 4);
+ EMGD_DEBUG("Plane B start addr = %lx", reg);
+ reg = (unsigned long)EMGD_READ32(mmio + DSPBCNTR + 4);
+ EMGD_DEBUG("Plane B start offset = %lx", reg);
+}
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param void
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int get_pipe_info_tnc(igd_display_h *display)
+{
+ unsigned char *mmio = NULL;
+ unsigned char *mmio_sdvo = NULL;
+ unsigned long pipe_conf = 0;
+ igd_display_info_t *timing;
+ unsigned long reg = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ mmio_sdvo =
+ EMGD_MMIO(mode_context->context->device_context.virt_mmadr_sdvo);
+
+ /*
+ * On Atom E6xx only
+ * PIPE A + LVDS and
+ * PIPE B + SDVO are valid.
+ *
+ * Read both VGA_TNC(0:2:0) and SDVO_TNC(0:3:0) mmio reg values in
+ * determining the current timing
+ *
+ * [FIXME]
+ * 1) Reading both device mmio regs in determining FW timings
+ * 2) Update dclk equation as it changed for TNC.
+ */
+ pipe_conf = EMGD_READ32(mmio + PIPEA_CONF);
+ if(pipe_conf & BIT(31)) { /* pipe A is active */
+ timing = &mode_context->fw_info->timing_arr[0];
+
+ reg = EMGD_READ32(mmio + HTOTAL_A);
+ timing[0].htotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[0].width = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + HBLANK_A);
+ timing[0].hblank_start = (unsigned short)reg & 0x1FFF;
+ timing[0].hblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + HSYNC_A);
+ timing[0].hsync_start = (unsigned short)reg & 0x1FFF;
+ timing[0].hsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + VTOTAL_A);
+ timing[0].vtotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[0].height = (unsigned short)reg & 0xFFF;
+
+ reg = EMGD_READ32(mmio + VBLANK_A);
+ timing[0].vblank_start = (unsigned short)reg & 0x1FFF;
+ timing[0].vblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = EMGD_READ32(mmio + VSYNC_A);
+ timing[0].vsync_start = (unsigned short)reg & 0x1FFF;
+ timing[0].vsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ /* Following are not offset by 1 in ptinfo */
+ timing[0].width++;
+ timing[0].height++;
+
+ EMGD_DEBUG("Pipe A timing width = %d", timing[0].width);
+ EMGD_DEBUG("Pipe A timing width = %d", timing[0].height);
+
+ {
+ /* Calculate the firmware programmed dot clock */
+ unsigned long dplla, fpa0, fpa1;
+ unsigned long m_select, m, p1_select, p1, p2;
+ unsigned long ref_freq, dclk;
+ int j;
+ unsigned long lvds_port;
+
+ dplla = EMGD_READ32(mmio + DPLLACNTR);
+ fpa0 = EMGD_READ32(mmio + FPA0);
+ fpa1 = EMGD_READ32(mmio + FPA1);
+ /* Note: Only Pipe A supports LVDS */
+ lvds_port = EMGD_READ32(mmio + LVDSCNTR);
+
+
+ if(dplla & BIT(31)) {
+
+ /*************************************************************
+ * Find M: read m_select from the register, then do a reverse
+ * lookup in the lvds_m_converts table
+ ************************************************************/
+
+ /* Bits 0:8 determines where the divisor is coming from */
+ if (dplla & 0xFF) {
+ EMGD_DEBUG("Using fpa1");
+ m_select = (fpa1 >> 8) & 0x3F; /* M is at bits 13:8 */
+ } else {
+ EMGD_DEBUG("Using fpa0");
+ m_select = (fpa0 >> 8) & 0x3F; /* M is at bits 13:8 */
+ }
+
+ EMGD_DEBUG("m_select %ld", m_select);
+
+ for( j=0; j < LVDS_M_CONVERTS_LEN; j++) {
+ if (m_select == lvds_m_converts[j]) {
+ break;
+ }
+ }
+
+ if (j == LVDS_M_CONVERTS_LEN) {
+ EMGD_ERROR_EXIT("Invalid M select value");
+ return -IGD_ERROR_INVAL;
+ } else {
+ m = j + LVDS_M_MIN;
+ EMGD_DEBUG("m value %ld", m);
+ }
+
+
+ /*************************************************************
+ * Find P1 and P2: read p1_select from the register, figure
+ * out its bit position, then add 2.
+ * P2 is always 14 for TNC.
+ ************************************************************/
+ p2 = 14; /* P2 is always 14 for TNC */
+
+ /* P1 select is bits 23:17 */
+ if (0 != (p1_select = (dplla >> 17) & 0x7F)) {
+ EMGD_DEBUG("p1_select %ld", p1_select);
+
+ /* p1 = 1 << (p1_select -2), so do the reverse to get p1 */
+ for (j = 0; p1_select > 1; j++) {
+ p1_select >>= 1;
+ }
+
+ /* According to the spec, only 7 bit positions are defined
+ * and so we should not have shifted more than 6 times */
+ if (j <= 6) {
+ p1 = j + 2;
+ EMGD_DEBUG("p1 %ld", p1);
+ } else {
+ EMGD_ERROR_EXIT("Invalid P1 select value");
+ return -IGD_ERROR_INVAL;
+ }
+ } else {
+ EMGD_ERROR_EXIT("Invalid P1 select value (zero)");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ /* Equation that calculates the dot clk:
+ * -------------------------------------
+ * dot clock = ref_freq * M / (P1 * P2)
+ */
+ ref_freq = 200000000; /* 200 MHz */
+
+ dclk = ref_freq * m / (p1*p2);
+
+ /* FIXME: This is a workaround to get dclk. We are supposed
+ * to be calculating this based on the formula, but DPLL
+ * is somehow locked and does not return the programmed
+ * p1 value. Once this is fixed, we no longer need to have
+ * igd_display_handle in the parameter of get_pipe_info
+ *
+ * Update:
+ * Now that we initialize the driver before X starts,
+ * we want to do a seamless mode-set from firmware to
+ * our kernel mode driver. At this point we do not have
+ * the igd_display_context_t setup.
+ *
+ * if (NULL != display) {
+ * igd_display_context_t *display_context =
+ * (igd_display_context_t *) display;
+ *
+ * dclk = ref_freq * m / (p1 * p2);
+ *
+ * PIPE(display)->dclk is in KHhz
+ * dclk = PIPE(display)->dclk * 1000;
+ * } else {
+ * dclk = 0;
+ * }
+ *
+ * if( dclk == 0 ) {
+ * EMGD_ERROR_EXIT(" Dot Clock/Ref Frequency is Zero!!!");
+ * return -IGD_ERROR_INVAL;
+ * }
+ */
+
+ EMGD_DEBUG("Ref frequency = %lu", ref_freq);
+ EMGD_DEBUG("Pipe A constructed Dot clock is = %lu", dclk);
+ timing[0].dclk = dclk/1000; /* Make it to KHz */
+ EMGD_DEBUG("Pipe A Dot clock in KHz = %lu", timing[0].dclk);
+
+ timing[0].refresh = (unsigned short)(dclk/
+ ((timing[0].htotal)*(timing[0].vtotal)));
+
+ EMGD_DEBUG("Pipe A refresh = %u", timing[0].refresh);
+ } /* if DPLL A active */
+ } /* dot clock code block */
+ } /* if Pipe A active */
+
+ /* For 2nd display pipe, pipe b registers in both 0:2:0 and 0:3:0
+ * supposed to be programmed to same values. So these values can be
+ * read from either devices */
+ pipe_conf = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF);
+
+ if(pipe_conf & BIT(31)) { /* pipe B is active */
+ timing = &mode_context->fw_info->timing_arr[0];
+
+ reg = READ_MMIO_REG_TNC(IGD_PORT_SDVO, HTOTAL_B);
+ timing[1].htotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[1].width = (unsigned short)reg & 0xFFF;
+
+ reg = READ_MMIO_REG_TNC(IGD_PORT_SDVO, HBLANK_B);
+ timing[1].hblank_start = (unsigned short)reg & 0x1FFF;
+ timing[1].hblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = READ_MMIO_REG_TNC(IGD_PORT_SDVO, HSYNC_B);
+ timing[1].hsync_start = (unsigned short)reg & 0x1FFF;
+ timing[1].hsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ reg = READ_MMIO_REG_TNC(IGD_PORT_SDVO, VTOTAL_B);
+ timing[1].vtotal = (unsigned short)(reg >> 16) & 0x1FFF;
+ timing[1].height = (unsigned short)reg & 0xFFF;
+
+ reg = READ_MMIO_REG_TNC(IGD_PORT_SDVO, VBLANK_B);
+ timing[1].vblank_start = (unsigned short)reg & 0x1FFF;
+ timing[1].vblank_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, VSYNC_B);
+ timing[1].vsync_start = (unsigned short)reg & 0x1FFF;
+ timing[1].vsync_end = (unsigned short)(reg >> 16) & 0x1FFF;
+
+ /* Following are not offset by 1 in ptinfo */
+ timing[1].width++;
+ timing[1].height++;
+
+ {
+ /* Calculate the firmware programmed dot clock */
+ unsigned long dpllb, fpb0, fpb1;
+ unsigned long mb1, mb2, nb, pb1, pb2, pllb_select;
+ unsigned long ref_freq = 0, dclk;
+ unsigned long port_mult = 1;
+ unsigned long temp; /* To store intermediate values b4 dclk */
+ int j;
+
+ dpllb = READ_MMIO_REG_TNC(IGD_PORT_SDVO, DPLLBCNTR);
+ fpb0 = READ_MMIO_REG_TNC(IGD_PORT_SDVO, FPB0);
+ fpb1 = READ_MMIO_REG_TNC(IGD_PORT_SDVO, FPB1);
+
+ if(dpllb & BIT(31)) {
+
+ mb1 = (fpb0 >> 8) & 0x3F; /* M1 is bits 13:8 */
+ mb2 = (fpb0) & 0xFF; /* M1 is bits 7:0 */
+ nb = (fpb0 >> 16) & 0xFF; /* N is bits 23:16 */
+ pb1 = (dpllb >> 16) & 0xFF; /* P1 is bits 23:16 */
+
+ port_mult = (((dpllb >> 4) & 0x0F) + 1);
+ /* Check for illegal values of P1
+ * The bit representation MUST be power of 2
+ * All other values are illegal including zero.
+ */
+ if( (pb1 == 0) ||
+ ( (pb1 & (pb1-1)) != 0 ) ) {
+ EMGD_ERROR_EXIT("Invalid P1 bits set");
+ return -IGD_ERROR_INVAL;
+ }
+
+ for(j = 0; j < 8; j++) {
+ if(pb1 & BIT(j)) { /* P1 is divide by 1 to 8 */
+ pb1 = j+1;
+ break; }
+ }
+
+ for(j = 0; j < 8; j++) {
+ if(nb & BIT(j)) {
+ nb = j+1;
+ break;
+ }
+ }
+
+ pb2 = (dpllb >> 24) & 0x3; /* P2 is bits 25:24 */
+
+ /* Since Pipe B does not support internal LVDS, we just
+ * follow the normal divisor values
+ */
+ if(pb2 == 0) {
+ pb2 = 10;
+ } else if(pb2 == 1) {
+ pb2 = 5;
+ } else {
+ EMGD_ERROR("Invalid P2 bits set = 0x%lx", pb2);
+ }
+
+ pllb_select = (dpllb >> 13) & 0x3; /* PLL Ref I/P Select */
+
+ /* Equation that calculates the dot clk
+ * -------------------------------------
+ *
+ * pll_freq_factor = ((float)(5 * (mb1+2)+(mb2+2))/(nb+2))/
+ * ((pb1*pb2));
+ *
+ * fdclk = pll_freq_factor * ref_freq * 1000000;
+ *
+ * Support for FPU in Kernel Code is not straightforward
+ * we will just stick to int operations. We will just re-
+ * arrange the factors.
+ */
+ if(pllb_select == 0) {
+ ref_freq = 96; /* 96MHz */
+
+ } else if( (pllb_select == 1) || (pllb_select == 3) ) {
+
+ EMGD_ERROR_EXIT("PLL Reference Input Select Reserved");
+ return -IGD_ERROR_INVAL;
+
+ } else if(pllb_select == 2) {
+ EMGD_ERROR_EXIT("PLL ref is SDVO TV CLK");
+ /* TODO: How to handle this value? */
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* First let's multiply by 1000 * 1000
+ * so that we don't end up in zero during
+ * integer division
+ */
+ temp = 1000 * 1000;
+ temp = temp * (mb2+2);
+ temp = temp / nb;
+ temp = temp/(pb1*pb2);
+ dclk = temp * ref_freq;
+ dclk = dclk / port_mult;
+
+ if( (dclk == 0) || (ref_freq == 0) ) {
+ EMGD_ERROR_EXIT("Dot Clock/Ref Frequency is Zero!!!");
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_DEBUG("Ref frequency = %lu", ref_freq);
+ EMGD_DEBUG("Pipe B constructed Dot clock is = %lu", dclk);
+ timing[1].dclk = dclk/1000; /* Make it to KHz */
+ EMGD_DEBUG("Pipe B Dot clock in KHz = %lu", timing[1].dclk);
+
+ timing[1].refresh = (unsigned short) (dclk/
+ ((timing[1].htotal+1)*(timing[1].vtotal+1)));
+
+ EMGD_DEBUG("Pipe B refresh = %u", timing[1].refresh);
+ } /* if DPLL B active */
+ } /* dot clock code block */
+ } /* if Pipe B is active */
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ *
+ * @param void
+ *
+ * @return 0
+ */
+static int get_port_info_tnc(void)
+{
+ /* TODO: Any port related info that needs to be populated ? */
+ EMGD_TRACE_ENTER;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+
+}
+
+
+/*******************************************************************************
+ *
+ * The following code provides VBlank interrupt support both within and without
+ * the EMGD HAL.
+ *
+ ******************************************************************************/
+
+/*!
+ * Interrupt handler for VBlanks.
+ *
+ * @param irq (IN). Unused.
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return A value to tell the kernel whether or not we handled the interrupt.
+ */
+static irqreturn_t interrupt_handler_tnc(int irq, void* mmio)
+{
+ unsigned long iir, iir_dev3;
+ unsigned long lock_flags;
+ unsigned long tmp;
+ unsigned long port2_interrupt = 0;
+ unsigned long port4_interrupt = 0;
+ emgd_vblank_callback_t *cb;
+
+ EMGD_TRACE_ENTER;
+
+ iir = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ iir_dev3 = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IIR);
+
+
+ /* Detect whether a vblank interrupt occured, and if so, what type of
+ * processing is needed (do the simple processing now):
+ */
+ spin_lock_irqsave(&vblank_lock_tnc, lock_flags);
+ if ((port2_interrupt = iir_dev3 & BIT5 /* Port 2/Pipe A/SDVO-B */) != 0) {
+ if ((tmp = vblank_interrupt_state & VBLANK_INT4_PORT2) != 0) {
+ /* Record "answers" for all requestors: */
+ vblank_interrupt_state |= VBINT_ANSWER4_REQUEST(tmp);
+ }
+ }
+ if ((port4_interrupt = iir & BIT7 /* Port 4/Pipe B/Int-LVDS */) != 0) {
+ if ((tmp = vblank_interrupt_state & VBLANK_INT4_PORT4) != 0) {
+ /* Record "answers" for all requestors: */
+ vblank_interrupt_state |= VBINT_ANSWER4_REQUEST(tmp);
+ }
+ }
+ spin_unlock_irqrestore(&vblank_lock_tnc, lock_flags);
+
+ /*
+ * Call the KMS 'flip complete' handler if we're waiting for a flip to
+ * complete on this port. Note that we should do this before the
+ * drm_handle_vblank() calls below since we need to clear the
+ * 'flip pending' bit in the CRTC before the vblank waitqueue gets
+ * woken up.
+ */
+ if (port4_interrupt) {
+ crtc_pageflip_handler(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_LVDS);
+
+ if (mode_context->batch_blits[IGD_PORT_TYPE_LVDS - 1]) {
+ notify_userspace_vblank(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_LVDS);
+ }
+ } else if (port2_interrupt) {
+ crtc_pageflip_handler(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_SDVOB);
+
+ if (mode_context->batch_blits[IGD_PORT_TYPE_SDVOB - 1]) {
+ notify_userspace_vblank(mode_context->context->drm_dev,
+ IGD_PORT_TYPE_SDVOB);
+ }
+ }
+
+
+ /* Notify KMS Hander: The assignment of CRTC=0 for PIPE A and
+ * CRTC=1 for PIPE B is not correct if somehow PIPE A is disabled.
+ */
+ if (port2_interrupt) {
+ drm_handle_vblank(mode_context->context->drm_dev, 1);
+ }
+
+ if (port4_interrupt) {
+ drm_handle_vblank(mode_context->context->drm_dev ,0);
+ }
+
+ /* Call any registered/enabled callbacks for this interrupt: */
+ cb = &interrupt_callbacks_tnc[2];
+ if (port2_interrupt && cb->callback &&
+ (vblank_interrupt_state & VBINT_ANSWER(VBINT_CB, VBINT_PORT2))) {
+ /* Clear the state to indicate the vblank has occured prior to
+ * invoking the callback.
+ */
+ vblank_interrupt_state &= ~VBINT_ANSWER(VBINT_CB, VBINT_PORT2);
+ cb->callback(cb->priv);
+ }
+ cb = &interrupt_callbacks_tnc[4];
+ if (port4_interrupt && cb->callback &&
+ (vblank_interrupt_state & VBINT_ANSWER(VBINT_CB, VBINT_PORT4))) {
+ /* Clear the state to indicate the vblank has occured prior to
+ * invoking the callback.
+ */
+ vblank_interrupt_state &= ~VBINT_ANSWER(VBINT_CB, VBINT_PORT4);
+ cb->callback(cb->priv);
+ }
+
+ /* Clear interrupt status registers: */
+ if (port2_interrupt || port4_interrupt) {
+ /* Clear the corresponding bits in the PIPE{A|B}_STAT register(s): */
+ if (port2_interrupt) {
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS), EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT,
+ (tmp | VBLANK_STS));
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, PIPEB_STAT);
+ }
+ if (port4_interrupt) {
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS), EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ }
+
+ /* Clear the corresponding bits in the IIR register: */
+ EMGD_WRITE32((port2_interrupt | port4_interrupt), EMGD_MMIO(mmio)+IIR);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IIR, port2_interrupt);
+
+
+ EMGD_DEBUG("EXIT--IRQ_HANDLED");
+ return IRQ_HANDLED;
+ } else {
+ EMGD_DEBUG("EXIT--IRQ_NONE");
+ return IRQ_NONE;
+ }
+}
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to request VBlank interrupts for a particular purpose & port.
+ * Based upon the outstanding requests, this function decides whether to
+ * touch registers, register the interrupt handler, etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+int request_vblanks_tnc(unsigned long request_for, unsigned char *mmio)
+{
+ unsigned long lock_flags;
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: request_for=0x%lx, mmio=0x%p", request_for, mmio);
+
+ /* Perform error checking--ensure a valid bit was set: */
+ if (!(request_for & (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4))) {
+ EMGD_ERROR_EXIT("Invalid parameter, request_for=0x%lx",
+ request_for);
+ return -1;
+ }
+
+ /* If we're just enabling interrupts, register the interrupt handler: */
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ struct drm_device *drm_device = mode_context->context->drm_dev;
+
+ EMGD_DEBUG("Registering interrupt_handler_tnc()");
+ if (request_irq(drm_device->pdev->irq, interrupt_handler_tnc,
+ IRQF_SHARED, EMGD_DRIVER_NAME, mmio)) {
+ EMGD_ERROR_EXIT("Failed to register interrupt_handler_tnc()");
+ return -1;
+ } else {
+ EMGD_DEBUG("Successfully registered interrupt_handler_tnc()");
+ }
+ }
+
+ /* Lock here to stop the interrupt handler until after changing bits: */
+ spin_lock_irqsave(&vblank_lock_tnc, lock_flags);
+
+ /* Enable interrupts for the requested purpose/port, actually touching the
+ * hardware registers if newly enabling interrupts for the given port/pipe:
+ */
+ if (request_for & VBLANK_INT4_PORT2) {
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT2) {
+ /* 1. Change Pipe Display Status Register for this pipe: set the
+ * Vertical Blank Interrupt Enable bit & clear (by setting) the
+ * Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS_EN | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+
+ /* 2. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IIR);
+
+ /* 3. Clear the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp & (~BIT5)), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Set the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IER);
+
+ /* NOW LET'S PROGRAM DEVICE 3 */
+
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT,
+ (tmp | VBLANK_STS_EN | VBLANK_STS));
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+
+ /* 2. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IIR);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IIR, (tmp | BIT5));
+
+ /* 3. Clear the Interrupt Mask Register bit for this pipe: */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IMR);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IMR, (tmp & (~BIT5)));
+
+ /* 4. Set the Interrupt Enable Register bit for this pipe: */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IER);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IER, (tmp | BIT5));
+
+ }
+ vblank_interrupt_state |= request_for;
+ /* Since there is only one vblank interrupt per request for now,
+ add counter have been remove for now and disable it when end request.
+ The counter may required after there is more than one request in future.
+ */
+ vblank_interrupt_ref_cnt_port2 = 1;
+ } else /* if (request_for & VBLANK_INT4_PORT4) */ {
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT4) {
+ /* 1. Change Pipe Display Status Register for this pipe: set the
+ * Vertical Blank Interrupt Enable bit & clear (by setting) the
+ * Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32((tmp | VBLANK_STS_EN | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+
+ /* 2. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IIR);
+
+ /* 3. Clear the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp & (~BIT7)), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Set the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IER);
+ }
+ vblank_interrupt_state |= request_for;
+ vblank_interrupt_ref_cnt_port4 = 1;
+ }
+
+
+ /* Unlock to allow the interrupt handler to proceed: */
+ spin_unlock_irqrestore(&vblank_lock_tnc, lock_flags);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to end a previous request VBlank interrupts for a particular
+ * purpose & port. Based upon the outstanding requests, this function
+ * decides whether to touch registers, unregister the interrupt handler,
+ * etc.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @param mmio (IN). A pointer to the start of memory-mapped IO, to access
+ * registers.
+ *
+ * @return Zero for success, non-zero for failure.
+ */
+int end_request_tnc(unsigned long request_for, unsigned char *mmio)
+{
+ unsigned long lock_flags;
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: request_for=0x%lx, mmio=0x%p", request_for, mmio);
+
+ /* Perform error checking--ensure a valid bit was set: */
+ if (!(request_for & (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4)) ||
+ !(vblank_interrupt_state & request_for)) {
+ EMGD_ERROR_EXIT("Invalid parameter, request_for=0x%lx", request_for);
+ return -1;
+ }
+
+ /* Lock here to stop the interrupt handler until after changing bits: */
+ spin_lock_irqsave(&vblank_lock_tnc, lock_flags);
+
+ /* Disable interrupts for the requested purpose/port, actually touching the
+ * hardware registers no software wants interrupts for the given port/pipe:
+ */
+ if (request_for & VBLANK_INT4_PORT2) {
+ /* Decrement reference count */
+ vblank_interrupt_ref_cnt_port2 = 0;
+ if (0 > vblank_interrupt_ref_cnt_port2) {
+ EMGD_DEBUG("WARNING: Disabled vblank INT too many times.");
+ vblank_interrupt_ref_cnt_port2 = 0;
+ }
+
+ if (0 == vblank_interrupt_ref_cnt_port2) {
+ /* Turn off both the request and the answer bits: */
+ tmp = request_for & VBLANK_INT4_PORT2;
+ vblank_interrupt_state &= ~(tmp | VBINT_ANSWER4_REQUEST(tmp));
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT2) {
+ /* 1. Change Pipe Display Status Register for this pipe: clear
+ * the Vertical Blank Interrupt Enable bit & clear (by
+ * setting) the Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+ /* Clear bits that are written by a 1, so don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32(((tmp & (~VBLANK_STS_EN)) | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEB_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEB_STAT);
+
+ /* 2. Clear the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp & (~BIT5)), EMGD_MMIO(mmio) + IER);
+
+ /* 3. Set the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT5), EMGD_MMIO(mmio) + IIR);
+
+ /* NOW LET'S PROGRAM DEVICE 3 */
+
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+ /* Clear bits that are written by a 1, so we don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT,
+ ((tmp & (~VBLANK_STS_EN)) | VBLANK_STS));
+ READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_STAT);
+
+ /* 2. Clear the Interrupt Enable Register bit for this pipe: */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IER);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IER, (tmp & (~BIT5)));
+
+ /* 3. Set the Interrupt Mask Register bit for this pipe: */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IMR);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IMR, (tmp | BIT5));
+
+ /* 4. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, IIR);
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, IIR, (tmp | BIT5));
+
+ }
+ }
+ }
+
+ if (request_for & VBLANK_INT4_PORT4) {
+ /* Decrement reference count */
+ vblank_interrupt_ref_cnt_port4 = 0;
+ if (0 > vblank_interrupt_ref_cnt_port4) {
+ EMGD_DEBUG("WARNING: Disabled vblank INT too many times.");
+ vblank_interrupt_ref_cnt_port4 = 0;
+ }
+
+ if (0 == vblank_interrupt_ref_cnt_port4) {
+ /* Turn off both the request and the answer bits: */
+ tmp = request_for & VBLANK_INT4_PORT4;
+ vblank_interrupt_state &= ~(tmp | VBINT_ANSWER4_REQUEST(tmp));
+ if (!VBLANK_INTERRUPTS_ENABLED4_PORT4) {
+ /* 1. Change Pipe Display Status Register for this pipe: clear
+ * the Vertical Blank Interrupt Enable bit & clear (by
+ * setting the Vertical Blank Interrupt Status bit:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+ /* Clear bits that are written by a 1, so don't clear them: */
+ tmp = tmp & (~PIPESTAT_STS_BITS);
+ EMGD_WRITE32(((tmp & (~VBLANK_STS_EN)) | VBLANK_STS),
+ EMGD_MMIO(mmio) + PIPEA_STAT);
+ EMGD_READ32(EMGD_MMIO(mmio) + PIPEA_STAT);
+
+ /* 2. Clear the Interrupt Enable Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IER);
+ EMGD_WRITE32((tmp & (~BIT7)), EMGD_MMIO(mmio) + IER);
+
+ /* 3. Set the Interrupt Mask Register bit for this pipe: */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IMR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IMR);
+
+ /* 4. Just in case, clear (by setting) the Interrupt Identity
+ * Register bit for this pipe:
+ */
+ tmp = EMGD_READ32(EMGD_MMIO(mmio) + IIR);
+ EMGD_WRITE32((tmp | BIT7), EMGD_MMIO(mmio) + IIR);
+ }
+ }
+ }
+
+ /* Unlock to allow the interrupt handler to proceed: */
+ spin_unlock_irqrestore(&vblank_lock_tnc, lock_flags);
+
+ /* If we've completely disabled all causes for interrupts, unregister the
+ * interrupt handler:
+ */
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ struct drm_device *drm_device = mode_context->context->drm_dev;
+
+ EMGD_DEBUG("Unregistering interrupt_handler_tnc()");
+ free_irq(drm_device->pdev->irq, mmio);
+ EMGD_DEBUG("Successfully unregistered interrupt_handler_tnc()");
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Implementation of "protected" function (i.e. for use within the mode
+ * module) to check whether a requested VBlank interrupt occured.
+ *
+ * @param request_for (IN). A bit that identifies a who and what (e.g.
+ * VBINT_REQUEST(VBINT_WAIT, VBINT_PORT4)).
+ *
+ * @return Non-zero if the requested VBlank occured, zero if not.
+ */
+int vblank_occured_tnc(unsigned long request_for)
+{
+ return (vblank_interrupt_state & VBINT_ANSWER4_REQUEST(request_for));
+}
+
+/*!
+ * Registers a VBlank interrupt callback function (and its parameter) to
+ * call when a VBlank interrupt occurs for a given port.
+ *
+ * @param callback (IN). A callback (function pointer) to a non-HAL
+ * function that processes a VBlank interrupt.
+ *
+ * @param priv (IN). An opaque pointer to a non-HAL data structure.
+ * This pointer is passed as a parameter of the callback function.
+ *
+ * @param port_number (IN). The EMGD port number to register a VBlank
+ * interrupt callback for.
+ *
+ * @return A handle that uniquely identifies this callback/port
+ * combination, or NULL if a failure.
+ */
+emgd_vblank_callback_h register_vblank_callback_tnc(
+ emgd_process_vblank_interrupt_t callback,
+ void *priv,
+ unsigned long port_number)
+{
+ EMGD_TRACE_ENTER;
+
+ if (!callback || !priv ||
+ !((port_number == 2) || (port_number == 4))) {
+ EMGD_ERROR_EXIT("Invalid parameter amongst the following:\n"
+ " process_interrupt=0x%p, priv=0x%p, port_number=%lu",
+ callback, priv, port_number);
+ return NULL;
+ }
+
+ interrupt_callbacks_tnc[port_number].callback = callback;
+ interrupt_callbacks_tnc[port_number].priv = priv;
+
+ EMGD_TRACE_EXIT;
+ return &interrupt_callbacks_tnc[port_number];
+}
+
+/*!
+ * Unregisters a previously-registered VBlank interrupt callback function
+ * for a given port.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies the VBlank
+ * interrupt callback to unregister.
+ */
+void unregister_vblank_callback_tnc(emgd_vblank_callback_h callback_h)
+{
+ emgd_vblank_callback_t *cb = (emgd_vblank_callback_t *) callback_h;
+
+ EMGD_TRACE_ENTER;
+
+ cb->callback = NULL;
+ cb->priv = NULL;
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * Enable delivering VBlank interrupts to the callback function for the
+ * registered callback/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to enable.
+ *
+ * @return Zero if successful, non-zero if a failure.
+ */
+int enable_vblank_callback_tnc(emgd_vblank_callback_h callback_h)
+{
+ emgd_vblank_callback_t *cb = (emgd_vblank_callback_t *) callback_h;
+ unsigned long enable_for = VBINT_REQUEST(VBINT_CB,
+ (cb->port_number == 2) ? VBINT_PORT2 : VBINT_PORT4);
+ unsigned char* mmio =
+ EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: callback_h=0x%p", callback_h);
+
+ ret = request_vblanks_tnc(enable_for, mmio);
+
+ EMGD_DEBUG("Return %d", ret);
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/*!
+ * Disable delivering VBlank interrupts to the callback function for the
+ * registered function/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to disable.
+ */
+void disable_vblank_callback_tnc(emgd_vblank_callback_h callback_h)
+{
+ unsigned long lock_flags;
+ unsigned long enable_for;
+ unsigned char* mmio =
+ EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: callback_h=0x%p", callback_h);
+
+ if (callback_h == ALL_PORT_CALLBACKS) {
+ /* Need to do some push-ups in order to get interrupts disabled: */
+ spin_lock_irqsave(&vblank_lock_tnc, lock_flags);
+ enable_for = (VBLANK_INT4_PORT2 | VBLANK_INT4_PORT4);
+ if (!VBLANK_INTERRUPTS_ENABLED) {
+ /* Nothing has enabled interrupts, so there's no interrupt handler
+ * to unregister. Therefore, use a special value to prevent that:
+ */
+ vblank_interrupt_state = (VBLANK_INT4_PORT2 |
+ VBLANK_INT4_PORT4 | VBLANK_DISABLE_HW_ONLY);
+ } else {
+ vblank_interrupt_state = (VBLANK_INT4_PORT2 |
+ VBLANK_INT4_PORT4);
+ }
+ spin_unlock_irqrestore(&vblank_lock_tnc, lock_flags);
+
+ end_request_tnc(enable_for, mmio);
+
+ spin_lock_irqsave(&vblank_lock_tnc, lock_flags);
+ vblank_interrupt_state = 0;
+ spin_unlock_irqrestore(&vblank_lock_tnc, lock_flags);
+ } else {
+ emgd_vblank_callback_t *cb =
+ (emgd_vblank_callback_t *) callback_h;
+ enable_for = VBINT_REQUEST(VBINT_CB,
+ (cb->port_number == 2) ? VBINT_PORT2 : VBINT_PORT4);
+
+ end_request_tnc(enable_for, mmio);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+/*!
+ * checks if the port is enabled
+ */
+unsigned long get_port_control_tnc(unsigned long port_num, unsigned long port_reg)
+{
+ unsigned long port_value=0;
+
+ EMGD_TRACE_ENTER;
+ if( port_num == IGD_PORT_TYPE_SDVOB) {
+ port_value = READ_MMIO_REG_TNC(IGD_PORT_SDVO,port_reg);
+ } else {
+ port_value = READ_MMIO_REG_TNC(IGD_PORT_LVDS,port_reg);
+ }
+
+ EMGD_TRACE_EXIT;
+ return port_value;
+}
+
+
+/*!
+ * locks the plane
+ * set_surface() and set_display_base_tnc() will not update the registers
+ * when the planes are locked.
+ */
+void lock_planes(igd_display_h display_handle)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+
+ EMGD_TRACE_ENTER;
+ if(!display){
+ EMGD_ERROR_EXIT("Display is NULL");
+ return;
+ }
+ PLANE(display)->fb_info->lock = TRUE;
+ EMGD_TRACE_EXIT;
+}
+
+
+/*!
+ * unlocks the plane
+ * resets the lock flag and writes to plane registers
+ *
+ */
+int unlock_planes(igd_display_h display_handle, unsigned int scrn_num)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_handle;
+ unsigned long plane_reg;
+ unsigned long plane_control;
+ unsigned long visible_offset;
+
+ EMGD_TRACE_ENTER;
+ if(!display){
+ EMGD_ERROR_EXIT("Display is NULL");
+ return FALSE;
+ }
+
+ /* plane registers are always on 0:2:0, so no need to use _TNC macros */
+ plane_reg = PLANE(display)->plane_reg;
+ plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+
+ /*
+ * Write the current plane_control value to the plane_reg
+ * Write the surface stride to DSP_STRIDE_OFFSET
+ * Write the visible from start of plane to DSP_LINEAR_OFFSET
+ * Write the base surface offset to either:
+ */
+ PLANE(display)->fb_info->lock = FALSE;
+
+ if(scrn_num == PRIMARY_DISPLAY){
+ visible_offset = 0;
+ }else {
+ visible_offset = PLANE(display)->fb_info->visible_offset;
+ }
+
+ EMGD_DEBUG("visible offset= %lx", visible_offset);
+
+ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+ EMGD_WRITE32(PLANE(display)->fb_info->screen_pitch,
+ MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
+ EMGD_WRITE32(visible_offset,
+ MMIO(display) + plane_reg + DSP_LINEAR_OFFSET);
+ EMGD_WRITE32(PLANE(display)->fb_info->fb_base_offset,
+ MMIO(display) + plane_reg + DSP_START_OFFSET);
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+
+mode_full_dispatch_t mode_full_dispatch_tnc = {
+ igd_alter_cursor_pos_tnc,
+ igd_set_palette_entries_tnc,
+ igd_wait_vsync_tnc,
+ igd_query_in_vblank_tnc,
+ igd_get_scanline_tnc,
+ set_display_base_tnc,
+ program_cursor_tnc,
+ set_color_correct_tnc,
+ igd_get_surface_tnc,
+ igd_set_surface_tnc,
+ igd_query_event_tnc,
+ set_flip_pending_tnc,
+ check_flip_pending_tnc,
+ get_plane_info_tnc,
+ get_pipe_info_tnc,
+ get_port_info_tnc,
+ register_vblank_callback_tnc,
+ unregister_vblank_callback_tnc,
+ enable_vblank_callback_tnc,
+ disable_vblank_callback_tnc,
+ request_vblanks_tnc,
+ end_request_tnc,
+ vblank_occured_tnc,
+ get_port_control_tnc,
+ lock_planes,
+ unlock_planes,
+};
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
new file mode 100644
index 0000000..98d667e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_tnc.h
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+typedef struct _mode_data_tnc {
+ unsigned long plane_a_preserve;
+ unsigned long plane_b_c_preserve;
+ unsigned long pipe_preserve;
+ unsigned long dsp_arb;
+ unsigned long fifo_watermark1;
+ unsigned long fifo_watermark2;
+ unsigned long fifo_watermark3;
+ unsigned long fifo_watermark4;
+ unsigned long fifo_watermark5;
+ unsigned long fifo_watermark6;
+} mode_data_tnc_t;
+
+#define CHECK_VGA(a) MODE_IS_VGA(a)
+
+#ifdef DEBUG_BUILD_TYPE
+#define FLAG(a) a
+#else
+/* Turn all workaround for release driver */
+#define FLAG(a) 1
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c b/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
new file mode 100755
index 0000000..31e7fd2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
@@ -0,0 +1,528 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains all the necessary common functions for port driver
+ * module. These functions are called only from hardware specific port
+ * drivers. These are exported via pd.h.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+
+#include <memory.h>
+#include <sched.h>
+
+#include <mode.h>
+#include <pd.h>
+#include <pi.h>
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*!
+ *
+ * @param size
+ *
+ * @return void
+ */
+void *pd_malloc(unsigned long size)
+{
+ return OS_ALLOC(size);
+} /* end pd_malloc */
+
+/*!
+ *
+ * @param address
+ * @param c
+ * @size
+ *
+ * @return void
+ */
+void *pd_memset(void *address, int c, unsigned long size)
+{
+ return OS_MEMSET(address, c, size);
+} /* end pd_memset */
+
+/*!
+ *
+ * @param dst
+ * @param src
+ * @param size
+ *
+ * @return void
+ */
+void *pd_memcpy(void *dst, void *src, unsigned long size)
+{
+ return OS_MEMCPY(dst, src, size);
+} /* end pd_memcpy */
+
+/*!
+ *
+ * @param size
+ *
+ * @return void
+ */
+void pd_free(void *ptr)
+{
+ OS_FREE(ptr);
+} /* end pd_free */
+
+/*!
+ *
+ * @param usec
+ *
+ * @return void
+ */
+void pd_usleep(unsigned long usec)
+{
+
+ if (usec <= 1000) {
+ OS_SLEEP(usec);
+ } else {
+ os_alarm_t alarm = OS_SET_ALARM((usec+999)/1000);
+ do {
+ OS_SCHEDULE();
+ } while (!OS_TEST_ALARM(alarm));
+ }
+
+}
+
+/*!
+ *
+ * @param usec
+ *
+ * @return void
+ */
+void pd_ui_usleep(unsigned long usec)
+{
+ OS_UISLEEP(usec);
+
+}
+
+/*!
+ *
+ * @param dest
+ * @param src
+ *
+ * @return dest
+ */
+char *pd_strcpy(char *dest, const char *src)
+{
+ int i = 0;
+ /* This can be optimized by assigning 32 bit quantities instead
+ * of 8 bit quantities. This requires knowing the length first then
+ * move the quantities. For now, this is OK. */
+ while (src[i] != '\0') {
+ dest[i] = src[i];
+ i++;
+ }
+ dest[i] = '\0';
+ return (dest);
+}
+
+/*!
+ *
+ * @param handle
+ * @param driver
+ *
+ * @return pi_pd_register()
+ */
+int pd_register(void *handle, pd_driver_t *driver)
+{
+ return (pi_pd_register(driver));
+} /* end pd_register */
+
+/*!
+ *
+ * @param curr
+ * @param in
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_INVALID_ATTR or PD_ERR_INCORR_ATTR_VALUE on failure
+ */
+int pd_check_attr(pd_attr_t *curr, pd_attr_t *in)
+{
+ if (!curr || !in) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ if (curr->id != in->id) {
+ return PD_ERR_INVALID_ATTR;
+ }
+
+ switch (curr->type) {
+ case PD_ATTR_TYPE_RANGE:
+ if ((in->current_value < RATTR(curr)->min) ||
+ (in->current_value > RATTR(curr)->max)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ case PD_ATTR_TYPE_LIST:
+ if ((in->current_value < 1) ||
+ (in->current_value > LHATTR(curr)->num_entries)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ case PD_ATTR_TYPE_BOOL:
+ if ((in->current_value != TRUE) &&
+ (in->current_value != FALSE)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ default:
+ return PD_ERR_INVALID_ATTR;
+ }
+ return PD_SUCCESS;
+}
+
+/*!
+ * This function searches for the requested attr_id in the attribute list
+ * and returns the pointer.
+ *
+ * In case of LIST attribute, it will return the proper list entry.
+ *
+ * @param attr_list
+ * @param num_attr
+ * @param attr_id
+ * @param flag
+ *
+ * @return pd_attr_t on success
+ * @return NULL on failure
+ */
+pd_attr_t *pd_get_attr(pd_attr_t *attr_list, unsigned long num_attrs,
+ unsigned long attr_id, unsigned long flag)
+{
+ unsigned long i;
+
+ if (!attr_list) {
+ return NULL;
+ }
+
+ for (i = 0; i < num_attrs; i++) {
+ if (attr_list[i].id == attr_id) {
+ if (attr_list[i].type == PD_ATTR_TYPE_LIST) {
+ if (flag == PD_GET_ATTR_LIST_ENTRY) {
+ return (&(attr_list[i+attr_list[i].current_value]));
+ } else {
+ return (&(attr_list[i]));
+ }
+ }
+ return (&(attr_list[i]));
+ }
+ }
+ return NULL;
+} /* end pd_get_attr() */
+
+/*!
+ * Common mode filter algorithm for all port drivers
+ *
+ * @param call_back
+ * @param in_list
+ * @param out_list
+ * @param dvo_info
+ * @param display_info
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_NULL_PTR or PD_ERR_NOMEM on failure
+ */
+int pd_filter_timings(
+ void *callback_context,
+ pd_timing_t *in_list,
+ pd_timing_t **out_list,
+ pd_dvo_info_t *dvo_info,
+ pd_display_info_t *display_info)
+{
+ igd_display_port_t *port = (igd_display_port_t *)callback_context;
+ pd_timing_t *timing = NULL, *native_dtd = NULL;
+ int j;
+ int count = 0;
+ unsigned short fp_refresh = 60;
+ pd_timing_t *olist = NULL;
+ unsigned long fixed_timing = 0;
+ int i, ret;
+
+ if (!port || !in_list || !out_list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ /* Start with fixed_res = 0 */
+ display_info->fixed_res = 0;
+
+ /* DisplayID FP width are specified */
+ if (port->firmware_type == PI_FIRMWARE_DISPLAYID) {
+ display_info->width = port->displayid->display_params.horz_pixels;
+ display_info->height = port->displayid->display_params.vert_pixels;
+ fixed_timing = port->displayid->display_params.fixed_timing;
+ display_info->fixed_res = port->displayid->display_params.fixed_res;
+ }
+
+ /* Overwrite DisplayID FP values with config fpinfo, later
+ * these will be overwritten by native DTD width, height */
+ if (port->fp_info) {
+ /* This is done for backward compatibility:
+ * Set width, height from display port fp_info
+ * This also required dropping fp_info width and height attributes
+ * from all port drivers */
+ display_info->width = (unsigned short) port->fp_info->fp_width;
+ display_info->height = (unsigned short) port->fp_info->fp_height;
+ /* Backward compatibility: If width and height are specified,
+ * that means it is a fixed resolution panel */
+ if (port->fp_info->fp_width && port->fp_info->fp_height) {
+ display_info->fixed_res = 1;
+ fp_refresh = 60;
+ }
+ }
+
+ /* If fixed timing also comes from user attributes then override DisplayID
+ * fixed timing and fpinfo values */
+ ret = pi_get_port_init_attr(port, PD_ATTR_ID_FIXED_TIMING, &fixed_timing);
+ if (fixed_timing) {
+ display_info->fixed_res = 1;
+ fp_refresh = 60;
+ }
+
+ /* Do gmch filtering:
+ * There is no way to get the mode context inorder to reach the
+ * gmch filtering function */
+
+ /* First find the native resolution */
+ get_native_dtd(in_list, PI_SUPPORTED_TIMINGS,
+ &display_info->native_dtd, PD_MODE_DTD_FP_NATIVE);
+
+ /* If no FP Native DTD provided, then get the native DTD
+ * either user DTD or edid DTD */
+ if (!display_info->native_dtd) {
+ get_native_dtd(in_list, PI_SUPPORTED_TIMINGS,
+ &display_info->native_dtd, PD_MODE_DTD_USER);
+ }
+ if (!display_info->native_dtd) {
+ get_native_dtd(in_list, PI_SUPPORTED_TIMINGS,
+ &display_info->native_dtd, PD_MODE_DTD);
+ }
+
+ /* Set up the fp width, height and refresh for the comparison */
+ if (display_info->native_dtd) {
+#ifndef CONFIG_MICRO
+ /* If fp width, height doesn' match with native width and height,
+ * Configuration isn't correct */
+ if ((display_info->width &&
+ (display_info->width != display_info->native_dtd->width)) &&
+ (display_info->height &&
+ (display_info->height != display_info->native_dtd->height))) {
+ EMGD_DEBUG("FP Width Height doesn't match with Native DTD.");
+ }
+#endif
+ /* Overwrite native width height as panel width and height */
+ display_info->width = display_info->native_dtd->width;
+ display_info->height = display_info->native_dtd->height;
+ fp_refresh = display_info->native_dtd->refresh;
+ } else if (ret &&
+ port->firmware_type != PI_FIRMWARE_DISPLAYID &&
+ dvo_info->upscale) {
+ /* TODO:
+ * For time being this function has to assume all upscaling encoders
+ * are connected to a fixed timing panel if no fixed_timing is
+ * specified.
+ *
+ * Once fixed_timing init-time attribute becomes mandatory, below check
+ * can be removed.
+ *
+ * If customer uses old config system and didn't specified init time
+ * fixed_timing attribute, then driver assumes it is a fixed-resolution
+ * panel. If user do specifies fixed_timing attribute, then above check
+ * will fail, and algorithm continues with whatever value set to
+ * fixed_res attr.
+ *
+ * ret != 0 means no fixed_timing user attribute
+ * firmware_type == DISPLAYID means firmware provided fixed_timing,
+ * so don't change it.
+ */
+ display_info->fixed_res = 1;
+ }
+
+ /* Check native_dtd for fixed_res display */
+ if (display_info->fixed_res && !display_info->native_dtd) {
+ /* This happens if user provides fp_width, fp_height and didn't set
+ * fixed res parameter. In this case native_dtd will be set as part
+ * of the while loop while filtering the modes */
+ EMGD_DEBUG("pd_filter_timings: No native dtd for fixed_resolution");
+ }
+
+ if (!display_info->width && !display_info->height) {
+ /* If fp width and height isn't known, then enable all modes as
+ * non-fixed res display */
+ display_info->fixed_res = 0;
+ }
+
+ EMGD_DEBUG("fixed_res = %u fixed_timing = %lu",
+ display_info->fixed_res, fixed_timing);
+ EMGD_DEBUG("fp_width = %u, fp_height = %u, fp_refresh = %u",
+ display_info->width, display_info->height, fp_refresh);
+ EMGD_DEBUG("min_dclk = %lu, max_dclk = %lu",
+ dvo_info->min_dclk, dvo_info->max_dclk);
+
+ /* This function can be called with following
+ * ---------------------------------------------------------------
+ * DVO device PanelFit Display AvailableModes
+ * DOWN UP Fixed?
+ * --------------------------------------------------------
+ * 0 0 0 0 All supported modes
+ * 1 0 0 0 All supported modes
+ * 0 1 0 0 All supported modes
+ * 1 1 0 0 All supported modes
+ * 0 0 1 0 All supported modes
+ * 1 0 1 0 All supported modes
+ * 0 1 1 0 All supported modes
+ * 1 1 1 0 All supported modes
+ *
+ * 0 0 0 Y Only one mode
+ * 1 0 0 Y Only one mode
+ * 0 1 0 Y Only one mode
+ * 1 1 0 Y Only one mode
+ * 0 0 1 Y Only one mode
+ *
+ * 0 1 1 Y All upscalable modes
+ * 1 0 1 Y All downscalable modes
+ *
+ * 1 1 1 Y All UP & DOWN scalable modes
+ * -------------------------------------------------------------------------
+ */
+
+ for (i = 0; i < 2; ++i) {
+ j = 0;
+ timing = in_list;
+ while(timing->width != PD_TIMING_LIST_END) {
+ /* If mode supported and dclk is within the range */
+ if ((timing->mode_info_flags & PD_MODE_SUPPORTED) &&
+ ((!dvo_info->max_dclk || (timing->dclk <= dvo_info->max_dclk))&&
+ (!dvo_info->min_dclk || (timing->dclk >= dvo_info->min_dclk)))){
+
+ if (
+ /* fixed_res = 0 */
+ !display_info->fixed_res ||
+
+ /* no panel fit */
+ (!display_info->panel_fit &&
+ timing->refresh == fp_refresh &&
+ timing->width == display_info->width &&
+ timing->height == display_info->height) ||
+
+ /* panel fit and upscale or downscale */
+ (display_info->panel_fit &&
+ timing->refresh == fp_refresh &&
+ ((dvo_info->upscale &&
+ timing->width <= display_info->width &&
+ timing->height <= display_info->height &&
+ (!dvo_info->upscale_min_width ||
+ timing->width >= dvo_info->upscale_min_width) &&
+ (!dvo_info->upscale_min_height ||
+ timing->height >= dvo_info->upscale_min_height))
+#if 0
+ ||
+ (dvo_info->downscale &&
+ timing->width >= display_info->width &&
+ timing->height >= display_info->height &&
+ (!dvo_info->downscale_max_width ||
+ timing->width <= dvo_info->downscale_max_width) &&
+ (!dvo_info->downscale_max_height ||
+ timing->height >= dvo_info->downscale_max_height))
+#endif
+ ))){
+
+ if((port->pd_driver->type & (PD_DISPLAY_CRT_EXT |PD_DISPLAY_CRT)) &&
+ (timing->width % 8 != 0) &&
+ !(timing->mode_info_flags&PD_MODE_DTD_USER||timing->mode_info_flags&PD_MODE_DTD)){
+
+ /*Filter non-standard build-in timing at vga display,
+ Do NOT filter User timing and EDID timing*/
+ EMGD_DEBUG("pd_filter_timings**********: NON_CRT_TIMING: %ux%u@%u",
+ timing->width,
+ timing->height,
+ timing->refresh);
+
+ } else if(!i){
+ count++;
+ } else {
+
+ /* copy timing */
+ olist[j] = *timing;
+
+ /* save the native_dtd timing */
+ if ((timing->width == display_info->width) &&
+ (timing->height == display_info->height) &&
+ (timing->refresh == fp_refresh)) {
+ native_dtd = &(olist[j]);
+ }
+
+ /* The native DTD pointer is pointing in the in_list,
+ * reset this pointer to point in the out_list */
+ if (timing == display_info->native_dtd) {
+ display_info->native_dtd = &olist[j];
+ }
+
+ j++;
+ }
+ }
+ }
+ timing++;
+ if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+ if(!i) {
+ count++;
+ olist = (pd_timing_t *) pd_malloc(count * sizeof(pd_timing_t));
+ if(!olist) {
+ return PD_ERR_NOMEM;
+ }
+ } else {
+ /* Copy the END of LIST entry */
+ olist[j] = *timing;
+ }
+ }
+
+ /* If there is no native_dtd, then use the first matching
+ * resolution with fp width and height as native dtd */
+ if (!display_info->native_dtd) {
+ display_info->native_dtd = native_dtd;
+ }
+ if (display_info->native_dtd) {
+ EMGD_DEBUG("pd_filter_timings: NativeDTD: %ux%u@%u",
+ display_info->native_dtd->width,
+ display_info->native_dtd->height,
+ display_info->native_dtd->refresh);
+ display_info->native_dtd->mode_info_flags |= PD_MODE_DTD_FP_NATIVE;
+ }
+
+ *out_list = olist;
+ return PD_SUCCESS;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
new file mode 100644
index 0000000..186ce7d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
@@ -0,0 +1,1109 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: displayid.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains functions to parse DisplayID into a data strucuture.
+ * Supported DisplayID versions:
+ * VESA DisplayID Standard Verion 1 12/13/2007
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd_errno.h>
+
+#include <displayid.h>
+#include <pi.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+#ifndef CONFIG_NO_DISPLAYID
+
+/* IMP NOTE:
+ * Keep the order of datablocks as it is.
+ * DisplayID parser directly access the offset using tag as an index.
+ */
+unsigned short db_offset[] = {
+#ifdef CONFIG_MICRO
+ OS_OFFSETOF(displayid_t, dummy_db), /* PRODUCTID 0x00 */
+ OS_OFFSETOF(displayid_t, display_params), /* DISPLAY_PARAMS 0x01 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* COLOR_CHARS 0x02 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_1_DETAIL 0x03 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_2_DETAIL 0x04 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_3_SHORT 0x05 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_4_DMTID 0x06 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* VESA_TIMING_STD 0x07 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* CEA_TIMING_STD 0x08 */
+ OS_OFFSETOF(displayid_t, timing_range), /* VIDEO_RANGE 0x09 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* SERIAL_NUMBER 0x0A */
+ OS_OFFSETOF(displayid_t, dummy_db), /* ASCII_STRING 0x0B */
+ OS_OFFSETOF(displayid_t, display_dev), /* DISPLAY_DEVICE 0x0C */
+ OS_OFFSETOF(displayid_t, lvds), /* LVDS_INTERFACE 0x0D */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TRANSFER_CHAR 0x0E */
+ OS_OFFSETOF(displayid_t, display_intf), /* DISPLAY_INTF 0x0F */
+ OS_OFFSETOF(displayid_t, dummy_db), /* STEREO_INTF 0x10 */
+#else
+ OS_OFFSETOF(displayid_t, productid), /* PRODUCTID 0x00 */
+ OS_OFFSETOF(displayid_t, display_params), /* DISPLAY_PARAMS 0x01 */
+ OS_OFFSETOF(displayid_t, color_char), /* COLOR_CHARS 0x02 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_1_DETAIL 0x03 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_2_DETAIL 0x04 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_3_SHORT 0x05 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* TIMING_4_DMTID 0x06 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* VESA_TIMING_STD 0x07 */
+ OS_OFFSETOF(displayid_t, dummy_db), /* CEA_TIMING_STD 0x08 */
+ OS_OFFSETOF(displayid_t, timing_range), /* VIDEO_RANGE 0x09 */
+ OS_OFFSETOF(displayid_t, serial_num), /* SERIAL_NUMBER 0x0A */
+ OS_OFFSETOF(displayid_t, general_string), /* ASCII_STRING 0x0B */
+ OS_OFFSETOF(displayid_t, display_dev), /* DISPLAY_DEVICE 0x0C */
+ OS_OFFSETOF(displayid_t, lvds), /* LVDS_INTERFACE 0x0D */
+ OS_OFFSETOF(displayid_t, transfer_char), /* TRANSFER_CHAR 0x0E */
+ OS_OFFSETOF(displayid_t, display_intf), /* DISPLAY_INTF 0x0F */
+ OS_OFFSETOF(displayid_t, stereo_intf), /* STEREO_INTF 0x10 */
+#endif
+
+
+#if 0
+ /* Vendor specific tag is out of order, so it cannot be here. See
+ * case DATABLOCK_VENDOR_SPECIFIC for implementation. */
+ OS_OFFSETOF(displayid_t, vendor), /* VENDOR_SPECIFIC 0x7F */
+#endif
+};
+
+type_std_t vesa_std_lookup[] =
+{
+ /* width height refresh flags */
+ /* byte 0 bit 0->7 */
+ { 640, 350, 85, 0 }, /* bit 0 */
+ { 640, 400, 85, 0 }, /* bit 1 */
+ { 720, 400, 85, 0 }, /* bit 2 */
+ { 640, 480, 60, 0 }, /* bit 3 */
+ { 640, 480, 72, 0 }, /* bit 4 */
+ { 640, 480, 75, 0 }, /* bit 5 */
+ { 640, 480, 85, 0 }, /* bit 6 */
+ { 800, 600, 56, 0 }, /* bit 7 */
+
+ /* byte 1 bit 0->7 */
+ { 800, 600, 60, 0 }, /* bit 0 */
+ { 800, 600, 72, 0 }, /* bit 1 */
+ { 800, 600, 75, 0 }, /* bit 2 */
+ { 800, 600, 85, 0 }, /* bit 3 */
+ { 800, 600, 120, PD_MODE_RB }, /* bit 4 */
+ { 848, 480, 60, 0 }, /* bit 5 */
+ { 1024, 768, 43, PD_SCAN_INTERLACE }, /* bit 6 */
+ { 1024, 768, 60, 0 }, /* bit 7 */
+
+ /* byte 2 bit 0->7 */
+ { 1024, 768, 70, 0 }, /* bit 0 */
+ { 1024, 768, 75, 0 }, /* bit 1 */
+ { 1024, 768, 85, 0 }, /* bit 2 */
+ { 1024, 768, 120, PD_MODE_RB }, /* bit 3 */
+ { 1152, 864, 75, 0 }, /* bit 4 */
+ { 1280, 768, 60, PD_MODE_RB }, /* bit 5 */
+ { 1280, 768, 60, 0 }, /* bit 6 */
+ { 1280, 768, 75, 0 }, /* bit 7 */
+
+ /* byte 3 bit 0->7 */
+ { 1280, 768, 85, 0 }, /* bit 0 */
+ { 1280, 768, 120, PD_MODE_RB }, /* bit 1 */
+ { 1280, 800, 60, PD_MODE_RB }, /* bit 2 */
+ { 1280, 800, 60, 0 }, /* bit 3 */
+ { 1280, 800, 75, 0 }, /* bit 4 */
+ { 1280, 800, 85, 0 }, /* bit 5 */
+ { 1280, 800, 120, PD_MODE_RB }, /* bit 6 */
+ { 1280, 960, 60, 0 }, /* bit 7 */
+
+ /* byte 4 bit 0->7 */
+ { 1280, 960, 85, 0 }, /* bit 0 */
+ { 1280, 960, 120, PD_MODE_RB }, /* bit 1 */
+ { 1280, 1024, 60, 0 }, /* bit 2 */
+ { 1280, 1024, 75, 0 }, /* bit 3 */
+ { 1280, 1024, 85, 0 }, /* bit 4 */
+ { 1280, 1024, 120, PD_MODE_RB }, /* bit 5 */
+ { 1360, 768, 60, 0 }, /* bit 6 */
+ { 1360, 768, 120, PD_MODE_RB }, /* bit 7 */
+
+ /* byte 5 bit 0->7 */
+ { 1400, 1050, 60, PD_MODE_RB }, /* bit 0 */
+ { 1400, 1050, 60, 0 }, /* bit 1 */
+ { 1400, 1050, 75, 0 }, /* bit 2 */
+ { 1400, 1050, 85, 0 }, /* bit 3 */
+ { 1400, 1050, 120, PD_MODE_RB }, /* bit 4 */
+ { 1440, 900, 60, PD_MODE_RB }, /* bit 5 */
+ { 1440, 900, 60, 0 }, /* bit 6 */
+ { 1440, 900, 75, 0 }, /* bit 7 */
+
+ /* byte 6 bit 0->7 */
+ { 1440, 900, 85, 0 }, /* bit 0 */
+ { 1440, 900, 120, PD_MODE_RB }, /* bit 1 */
+ { 1600, 1200, 60, 0 }, /* bit 2 */
+ { 1600, 1200, 65, 0 }, /* bit 3 */
+ { 1600, 1200, 70, 0 }, /* bit 4 */
+ { 1600, 1200, 75, 0 }, /* bit 5 */
+ { 1600, 1200, 85, 0 }, /* bit 6 */
+ { 1600, 1200, 120, PD_MODE_RB }, /* bit 7 */
+
+ /* byte 7 bit 0->7 */
+ { 1680, 1050, 60, PD_MODE_RB }, /* bit 0 */
+ { 1680, 1050, 60, 0 }, /* bit 1 */
+ { 1680, 1050, 75, 0 }, /* bit 2 */
+ { 1680, 1050, 85, 0 }, /* bit 3 */
+ { 1680, 1050, 120, PD_MODE_RB }, /* bit 4 */
+ { 1792, 1344, 60, 0 }, /* bit 5 */
+ { 1792, 1344, 75, 0 }, /* bit 6 */
+ { 1792, 1344, 120, PD_MODE_RB }, /* bit 7 */
+
+ /* byte 8 bit 0->7 */
+ { 1856, 1392, 60, 0 }, /* bit 0 */
+ { 1856, 1392, 75, 0 }, /* bit 1 */
+ { 1856, 1392, 120, PD_MODE_RB }, /* bit 2 */
+ { 1920, 1200, 60, PD_MODE_RB }, /* bit 3 */
+ { 1920, 1200, 60, 0 }, /* bit 4 */
+ { 1920, 1200, 75, 0 }, /* bit 5 */
+ { 1920, 1200, 85, 0 }, /* bit 6 */
+ { 1920, 1200, 120, PD_MODE_RB }, /* bit 7 */
+
+ /* byte 9 bit 0->7 */
+ { 1920, 1440, 60, 0 }, /* bit 0 */
+ { 1920, 1440, 75, 0 }, /* bit 1 */
+ { 1920, 1440, 120, PD_MODE_RB }, /* bit 2 */
+ { 2560, 1600, 60, PD_MODE_RB }, /* bit 3 */
+ { 2560, 1600, 60, 0 }, /* bit 4 */
+ { 2560, 1600, 75, 0 }, /* bit 5 */
+ { 2560, 1600, 85, 0 }, /* bit 6 */
+ { 2560, 1600, 120, PD_MODE_RB }, /* bit 7 */
+};
+
+#ifndef CONFIG_MICRO
+/*!
+ * Function to replace common timings in 1st list with 2nd list, 2nd list
+ * is unchanged.
+ *
+ * @param dtds1
+ * @param dtds2
+ *
+ * @return void
+ */
+void replace_vesa_dtds_with_cea_dtds(igd_timing_info_t *dtds1,
+ igd_timing_info_t *dtds2)
+{
+ igd_timing_info_t *temp;
+
+ if (!dtds2 || !dtds1) {
+ return;
+ }
+
+ while (dtds1->width != IGD_TIMING_TABLE_END) {
+ temp = dtds2;
+
+ while (temp->width != IGD_TIMING_TABLE_END) {
+ if ((temp->width == dtds1->width) &&
+ (temp->height == dtds1->height) &&
+ (temp->refresh == dtds1->refresh)) {
+ dtds1->mode_info_flags &= ~PD_MODE_SUPPORTED;
+ }
+ temp++;
+ }
+ dtds1++;
+ }
+}
+#endif
+
+#ifdef DEBUG_FIRMWARE
+/*!
+ *
+ * @param db
+ *
+ * @return void
+ */
+void displayid_print_datablock(datablock_t *db)
+{
+ unsigned char payload_string[800];
+ unsigned char i, j;
+
+ /* Get the payload data into a string */
+ OS_MEMSET(payload_string, 0, sizeof(payload_string));
+ for (i=0, j=0; i<db->payload; i++,j+=5) {
+ payload_string[j] = '0';
+ payload_string[j+1] = 'x';
+ if ((db->payload_data[i]>>4) <= 0x9) {
+ payload_string[j+2] = '0' + (db->payload_data[i]>>4);
+ } else {
+ payload_string[j+2] = 'A' + (db->payload_data[i]>>4) - 0xA;
+ }
+ if ((db->payload_data[i] & 0x0F) <= 0x9) {
+ payload_string[j+3] = '0' + (db->payload_data[i]&0x0F);
+ } else {
+ payload_string[j+3] = 'A' + (db->payload_data[i]&0x0F) - 0xA;
+ }
+ payload_string[j+4] = ' ';
+ }
+ payload_string[j] = '\0';
+
+ EMGD_DEBUG("Tag = %u", db->tag);
+ EMGD_DEBUG("Version = %u", db->revision);
+ EMGD_DEBUG("Payload = %u", db->payload);
+ EMGD_DEBUG("Payload data = %s", payload_string);
+}
+
+/*!
+ *
+ * @param buffer
+ * @param did
+ *
+ * @return void
+ */
+void displayid_print(unsigned char *buffer, displayid_t *did)
+{
+ unsigned short i;
+ display_params_t *dp = &did->display_params;
+ timing_range_t *tr = &did->timing_range;
+ lvds_display_t *ld = &did->lvds;
+ display_dev_t *dd = &did->display_dev;
+ display_intf_t *di = &did->display_intf;
+#ifndef CONFIG_MICRO
+ productid_t *pi = &did->productid;
+ color_char_t *cc = &did->color_char;
+ serial_number_t *sn = &did->serial_num;
+ general_string_t *gs = &did->general_string;
+ transfer_char_t *tc = &did->transfer_char;
+ stereo_intf_t *si = &did->stereo_intf;
+ vendor_t *vi = &did->vendor;
+#endif
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("DisplayID Version: %d", did->version);
+ EMGD_DEBUG("DisplayID Revision: %d", did->revision);
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("Size of different structures:");
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG(" displayid_t = %d", sizeof(displayid_t));
+ EMGD_DEBUG("display_params_t = %d", sizeof(display_params_t));
+ EMGD_DEBUG(" type1_dtd_t = %d", sizeof(type1_dtd_t));
+ EMGD_DEBUG(" type2_dtd_t = %d", sizeof(type2_dtd_t));
+ EMGD_DEBUG(" type3_cvt_t = %d", sizeof(type3_cvt_t));
+ EMGD_DEBUG(" type_std_t = %d", sizeof(type_std_t));
+ EMGD_DEBUG(" timing_range_t = %d", sizeof(timing_range_t));
+ EMGD_DEBUG(" display_dev_t = %d", sizeof(display_dev_t));
+ EMGD_DEBUG(" lvds_display_t = %d", sizeof(lvds_display_t));
+ EMGD_DEBUG(" display_intf_t = %d", sizeof(display_intf_t));
+ EMGD_DEBUG(" dummy_db = %d", 256);
+ EMGD_DEBUG(" timings = %d",
+ sizeof(pd_timing_t)*DISPLAYID_MAX_NUM_TIMINGS);
+ EMGD_DEBUG(" attrs = %d",
+ sizeof(pd_attr_t)*DISPLAYID_MAX_ATTRS);
+
+#ifndef CONFIG_MICRO
+ EMGD_DEBUG(" productid_t = %d", sizeof(productid_t));
+ EMGD_DEBUG(" color_char_t = %d", sizeof(color_char_t));
+ EMGD_DEBUG(" serial_number_t = %d", sizeof(serial_number_t));
+ EMGD_DEBUG("general_string_t = %d", sizeof(general_string_t));
+ EMGD_DEBUG(" transfer_char_t = %d", sizeof(transfer_char_t));
+ EMGD_DEBUG(" stereo_intf_t = %d", sizeof(stereo_intf_t));
+ EMGD_DEBUG(" vendor_t = %d", sizeof(vendor_t));
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("PRODUCT ID DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)pi);
+ EMGD_DEBUG(" vendor = %c%c%c",
+ pi->vendor[0], pi->vendor[1], pi->vendor[2]);
+ EMGD_DEBUG(" product_code = %u", pi->product_code);
+ EMGD_DEBUG("serial_number = %lu", pi->serial_number);
+ EMGD_DEBUG(" manf_week = %u", pi->manf_week);
+ EMGD_DEBUG(" manf_year = %u", pi->manf_year+2000);
+ EMGD_DEBUG(" string_len = %u", pi->string_size);
+ EMGD_DEBUG(" string = %s", pi->string);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("COLOR CHARACTERISTICS DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)cc);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("SERIAL NUMBER DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)sn);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("GENERAL PURPOSE ASCII STRING DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)gs);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("TRANSFER CHARACTERISTICS DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)tc);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("STEREO INTERFACE DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)si);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("VENDOR SPECIFIC DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)vi);
+#endif
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("DISPLAY PARAMETERS DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)dp);
+ EMGD_DEBUG("horz_image_size = %u", dp->horz_image_size);
+ EMGD_DEBUG("vert_image_size = %u", dp->vert_image_size);
+ EMGD_DEBUG(" horz_pixels = %u", dp->horz_pixels);
+ EMGD_DEBUG(" vert_pixels = %u", dp->vert_pixels);
+ EMGD_DEBUG(" deinterlacable = %u", dp->deinterlacing);
+ EMGD_DEBUG(" fixed_timing = %u", dp->fixed_timing);
+ EMGD_DEBUG(" fixed_res = %u", dp->fixed_res);
+ EMGD_DEBUG(" aspect_ratio = %u", dp->aspect_ratio);
+ EMGD_DEBUG(" native_color_depth(bppc) = %u", dp->native_color_depth+1);
+ EMGD_DEBUG("overall_color_depth(bppc) = %u", dp->overall_color_depth+1);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("VIDEO TIMING RANGESS DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)tr);
+ EMGD_DEBUG(" min_dclk = %lu KHz", tr->min_dclk);
+ EMGD_DEBUG(" max_dclk = %lu KHz", tr->max_dclk);
+ EMGD_DEBUG(" min_hrate = %u KHz", tr->min_hrate);
+ EMGD_DEBUG(" max_hrate = %u KHz", tr->max_hrate);
+ EMGD_DEBUG("min_hblank = %u pixels", tr->min_hblank);
+ EMGD_DEBUG(" min_vrate = %u Hz", tr->min_vrate);
+ EMGD_DEBUG(" max_vrate = %u Hz", tr->max_vrate);
+ EMGD_DEBUG("min_vblank = %u lines", tr->min_vblank);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("LVDS DISPLAY DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)ld);
+ EMGD_DEBUG("min_T1 = %u ms", ld->min_t1/10);
+ EMGD_DEBUG("max_T1 = %u ms", ld->max_t1*2);
+ EMGD_DEBUG("max_T2 = %u ms", ld->max_t2*2);
+ EMGD_DEBUG("max_T3 = %u ms", ld->max_t3*2);
+ EMGD_DEBUG("min_T4 = %u ms", ld->min_t4*10);
+ EMGD_DEBUG("min_T5 = %u ms", ld->min_t5*10);
+ EMGD_DEBUG("min_T6 = %u ms", ld->min_t6*10);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("DISPLAY DEVICE DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)dd);
+ EMGD_DEBUG(" horz_pixel_count = %u", dd->horz_pixel_count);
+ EMGD_DEBUG(" vert_pixel_count = %u", dd->vert_pixel_count);
+ EMGD_DEBUG("display_color_depth = %u", dd->display_color_depth);
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("DISPLAY INTERFACE DATA BLOCK");
+ DISPLAYID_PRINT_LINE();
+ displayid_print_datablock((datablock_t *)di);
+ EMGD_DEBUG(" num_channels = %u", di->num_channels);
+ EMGD_DEBUG(" intf_type = %u", di->intf_type);
+ EMGD_DEBUG(" RGB_color_depth = %u", di->rgb_color_depth);
+ EMGD_DEBUG("YCrCb_444_color_depth = %u", di->ycbcr_444_color_depth);
+ EMGD_DEBUG("YCrCb_422_color_depth = %u", di->ycbcr_422_color_depth);
+ if(di->intf_type == INTERFACE_LVDS) {
+ EMGD_DEBUG(" openldi = %u", di->lvds.openldi);
+ }
+
+ DISPLAYID_PRINT_LINE();
+ EMGD_DEBUG("Detailed Timing Descriptors");
+ DISPLAYID_PRINT_LINE();
+
+ for (i=0; i<did->num_timings; i++) {
+ EMGD_DEBUG("DTD: %u", i+1);
+ EMGD_DEBUG(" dclk = %lu", did->timings[i].dclk);
+ EMGD_DEBUG(" hactive = %u", did->timings[i].width);
+ EMGD_DEBUG(" htotal = %u", did->timings[i].htotal);
+ EMGD_DEBUG(" hblank_start = %u", did->timings[i].hblank_start);
+ EMGD_DEBUG(" hsync_start = %u", did->timings[i].hsync_start);
+ EMGD_DEBUG(" hsync_end = %u", did->timings[i].hsync_end);
+ EMGD_DEBUG(" hblank_end = %u", did->timings[i].hblank_end);
+ EMGD_DEBUG(" vactive = %u", did->timings[i].height);
+ EMGD_DEBUG(" vtotal = %u", did->timings[i].vtotal);
+ EMGD_DEBUG(" vblank_start = %u", did->timings[i].vblank_start);
+ EMGD_DEBUG(" vsync_start = %u", did->timings[i].vsync_start);
+ EMGD_DEBUG(" vsync_end = %u", did->timings[i].vsync_end);
+ EMGD_DEBUG(" vblank_end = %u", did->timings[i].vblank_end);
+ EMGD_DEBUG(" native = %u",
+ (did->timings[i].mode_info_flags&PD_MODE_DTD_FP_NATIVE)?1:0);
+ EMGD_DEBUG(" interlace = %u",
+ (did->timings[i].mode_info_flags&PD_SCAN_INTERLACE)?1:0);
+ EMGD_DEBUG("hsync_polarity = %s",
+ (did->timings[i].mode_info_flags & PD_HSYNC_HIGH)?
+ "ACTIVE HIGH":"ACTIVE LOW");
+ EMGD_DEBUG("vsync_polarity = %s",
+ (did->timings[i].mode_info_flags & PD_VSYNC_HIGH)?
+ "ACTIVE HIGH":"ACTIVE LOW");
+ DISPLAYID_PRINT_LINE();
+ }
+
+ /* Print the attributes */
+ if (did->num_attrs) {
+ EMGD_DEBUG("\tAttr\tID\tVALUE");
+ EMGD_DEBUG("----------------------");
+ for (i=0; i<did->num_attrs; i++) {
+ EMGD_DEBUG("\t%u\t%lu\t%lu", i+1, did->attr_list[i].id,
+ did->attr_list[i].current_value);
+ }
+ EMGD_DEBUG("----------------------");
+ }
+}
+#endif
+
+/*!
+ * Function to convert Type I - Detailed to pd_timing_t
+ *
+ * @param timing
+ * @param dtd
+ *
+ * @return void
+ */
+void convert_type1_to_pd(pd_timing_t *timing, type1_dtd_t *dtd)
+{
+ unsigned long refresh;
+ timing->dclk = /* change to KHz */
+ ((unsigned long)dtd->dclk.lsb_dclk|
+ ((unsigned long)dtd->dclk.msb_dclk<<16))*10;
+
+ /* DisplayID fields are 0 based but should be interpreted as 1-based.
+ * For example hsync_width value can be read as 0-65,535 pixels but
+ * interpreted as 1-65,536. So, to get the right value add 1.
+ * But pd_timing_t values are 0 based except width and height,
+ * so care should be taken while converting DisplayID fields into
+ * pd_timing_t values */
+ timing->hblank_start = dtd->hactive;
+ timing->width = dtd->hactive + 1;
+ timing->hblank_end = timing->hblank_start + dtd->hblank + 1;
+ timing->hsync_start = timing->hblank_start + dtd->hsync_offset + 1;
+ timing->hsync_end = timing->hsync_start + dtd->hsync_width + 1;
+ timing->htotal = timing->hblank_end;
+
+ timing->vblank_start = dtd->vactive;
+ timing->height = dtd->vactive + 1;
+ timing->vblank_end = timing->vblank_start + dtd->vblank + 1;
+ timing->vsync_start = timing->vblank_start + dtd->vsync_offset + 1;
+ timing->vsync_end = timing->vsync_start + dtd->vsync_width + 1;
+ timing->vtotal = timing->vblank_end;
+
+ refresh = ((timing->dclk * 1000L)/timing->htotal)/timing->vtotal;
+ timing->refresh = (unsigned short) refresh;
+
+ timing->mode_info_flags = PD_MODE_DTD|PD_MODE_SUPPORTED;
+ if (dtd->hsync_polarity) {
+ timing->mode_info_flags |= PD_HSYNC_HIGH;
+ }
+ if (dtd->vsync_polarity) {
+ timing->mode_info_flags |= PD_VSYNC_HIGH;
+ }
+ if (dtd->interlaced) {
+ timing->mode_info_flags |= PD_SCAN_INTERLACE;
+ }
+ if (dtd->preferred) {
+ timing->mode_info_flags |= PD_MODE_DTD_FP_NATIVE;
+ }
+}
+
+/*!
+ * Function to convert Type II - Detailed to pd_timing_t
+ *
+ * @param timing
+ * @param dtd
+ *
+ * @return void
+ */
+void convert_type2_to_pd(pd_timing_t *timing, type2_dtd_t *dtd)
+{
+ unsigned long refresh;
+ timing->dclk = /* change to KHz */
+ ((unsigned long)dtd->dclk.lsb_dclk|
+ ((unsigned long)dtd->dclk.msb_dclk<<16))*10;
+
+ /* DisplayID fields are 0 based but should be interpreted as 1-based.
+ * For example hsync_width value can be read as 0-15 OCTETs but
+ * interpreted as 1-16 OCTETs. So, to get the right value add 1.
+ * But pd_timing_t values are 0 based except width and height,
+ * so care should be taken while converting DisplayID fields into
+ * pd_timing_t values */
+ timing->width = (dtd->hactive + 1) * 8; /* change to pixels */
+ timing->hblank_start = timing->width - 1;
+ timing->hblank_end = timing->hblank_start + (dtd->hblank + 1) * 8;
+ timing->hsync_start = timing->hblank_start + (dtd->hsync_offset + 1) * 8;
+ timing->hsync_end = timing->hsync_start + (dtd->hsync_width + 1) * 8;
+ timing->htotal = timing->hblank_end;
+
+ timing->vblank_start = dtd->vactive;
+ timing->height = dtd->vactive + 1;
+ timing->vblank_end = timing->vblank_start + dtd->vblank + 1;
+ timing->vsync_start = timing->vblank_start + dtd->vsync_offset + 1;
+ timing->vsync_end = timing->vsync_start + dtd->vsync_width + 1;
+ timing->vtotal = timing->vblank_end;
+
+ refresh = ((timing->dclk * 1000L)/timing->htotal)/timing->vtotal;
+ timing->refresh = (unsigned short) refresh;
+
+ timing->mode_info_flags = PD_MODE_DTD|PD_MODE_SUPPORTED;
+ if (dtd->interlaced) {
+ timing->mode_info_flags |= PD_SCAN_INTERLACE;
+ }
+ if (dtd->preferred) {
+ timing->mode_info_flags |= PD_MODE_DTD_FP_NATIVE;
+ }
+}
+
+/*!
+ * Function to filter timing table based on range block
+ *
+ * @param tt
+ * @param range
+ * @param firmware_type
+ *
+ * @return void
+ */
+void displayid_filter_range_timings(pd_timing_t *tt, timing_range_t *range,
+ unsigned char firmware_type)
+{
+ unsigned short hfreq;
+
+#define _HUNDRETHS(_n, _d) ((100*_n)/_d)-((100*_n_d)/100),
+
+ #ifdef DEBUG_FIRMWARE
+ char result_str[60];
+ unsigned char pass_count = 0;
+ unsigned char fail_count = 0;
+
+ EMGD_DEBUG("Range limits:");
+ EMGD_DEBUG("\tmin_dclk = %lu KHz max_dclk = %lu KHz",
+ range->min_dclk, range->max_dclk);
+ EMGD_DEBUG("\t h_min = %u h_max = %u KHz",
+ range->min_hrate, range->max_hrate);
+ EMGD_DEBUG("\t v_min = %u v_max = %u",
+ range->min_vrate,range->max_vrate);
+ EMGD_DEBUG("WIDTH\tHEIGHT\tREFRESH\tH-FREQ\tDOTCLOCK\tRESULT");
+ EMGD_DEBUG(" \t \t (Hz) \t (KHz)\t (MHz) \t ");
+ EMGD_DEBUG("=====\t======\t=======\t======\t========\t======");
+#endif
+
+ /* If the display is a discreate frequency display, don't enable any
+ * intermediate timings. Only continuous frequency displays requires
+ * enabling range timings */
+ if (range->discrete_display) {
+ EMGD_DEBUG("Discrete display: Ranges aren't used.");
+ return;
+ }
+
+ /* If no timing table return */
+ if (tt == NULL) {
+ return;
+ }
+
+ /* Mark the timings that fall in the ranges */
+ /* Compare
+ * dclk in KHz
+ * hfreq in KHz
+ * vfreq in Hz */
+ while(tt->width != IGD_TIMING_TABLE_END) {
+ hfreq = (unsigned short)(tt->dclk/(unsigned long)tt->htotal); /* KHz */
+ if ((tt->dclk >= (unsigned long)range->min_dclk)&& /* compare KHz */
+ (tt->dclk <= (unsigned long)range->max_dclk)&& /* compare KHz */
+ (tt->refresh >= range->min_vrate) && /* compare Hz */
+ (tt->refresh <= range->max_vrate) && /* compare Hz */
+ (hfreq >= range->min_hrate) && /* compare KHz */
+ (hfreq <= range->max_hrate) && /* compare KHz */
+ (tt->hblank_end - tt->hblank_start) > range->min_hblank &&
+ (tt->vblank_end - tt->vblank_start) > range->min_vblank) {
+ tt->mode_info_flags |= PD_MODE_SUPPORTED;
+#ifdef DEBUG_FIRMWARE
+ if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
+ EMGD_DEBUG("%5u\t%6u\t%7u\t%6u.%2u\t%8u.%2u\tPASSED",
+ tt->width, tt->height, tt->refresh,
+ tt->dclk/tt->htotal,
+ _HUNDRETHS(tt->dclk,tt->htotal),
+ tt->dclk/1000,
+ _HUNDRETHS(tt->dclk,1000);
+
+ pass_count++;
+ } else {
+ }
+#endif
+ } else {
+ /* Unmark the mode that falls out of range */
+ /* DTD, FACTORY and NATIVE timings are "GOLD" even if they
+ * fall outside the range limits */
+ if (!(tt->mode_info_flags &
+ (PD_MODE_DTD|PD_MODE_FACTORY|PD_MODE_DTD_FP_NATIVE))) {
+#ifdef DEBUG_FIRMWARE
+ if ((tt->dclk < /* compare KHz */
+ (unsigned long)range->min_dclk)||
+ (tt->dclk >
+ (unsigned long)range->max_dclk)) {
+ OS_MEMCPY(result_str, "FAILED DCLK \0", 16);
+ fail_count++;
+ } else if ((tt->refresh > range->max_vrate) ||
+ (tt->refresh < range->min_vrate)) {
+ OS_MEMCPY(result_str, "FAILED REFRESH \0", 16);
+ fail_count++;
+ } else if ((hfreq < range->min_hrate) ||
+ (hfreq > range->max_hrate)) {
+ OS_MEMCPY(result_str, "FAILED H-FREQ \0", 16);
+ fail_count++;
+ } else if ((tt->hblank_end-tt->hblank_start) <
+ range->min_hblank){
+ OS_MEMCPY(result_str, "FAILED MIN_HBLK\0", 16);
+ } else if ((tt->vblank_end-tt->vblank_start) <
+ range->min_vblank){
+ OS_MEMCPY(result_str, "FAILED MIN_VBLK\0", 16);
+ }
+ EMGD_DEBUG("%5u\t%6u\t%7u\t%6u.%2u\t%8u.%2u\t%s",
+ tt->width, tt->height, tt->refresh,
+ tt->dclk/tt->htotal,
+ _HUNDRETHS(tt->dclk,tt->htotal),
+ tt->dclk/1000,
+ _HUNDRETHS(tt->dclk,1000),
+ result_str);
+ ((float) tt->dclk)/1000, result_str);
+
+ /* TODO: For multiple range blocks, don't disable the modes
+ * that are outside the range. We already started with
+ * an "empty supported table" */
+
+ /* But above assertion of "empty supported table" broke
+ * if EDID ETF rules were met to enable all timings.
+ * See edid.c for ETF conditions. So below line
+ * cannot be commented out to support multiple range
+ * blocks for DisplayID. */
+#endif
+ tt->mode_info_flags &= ~PD_MODE_SUPPORTED;
+ }
+ }
+ tt++;
+ if (tt->width == IGD_TIMING_TABLE_END && tt->extn_ptr) {
+ tt = tt->extn_ptr;
+ }
+ }
+#ifdef DEBUG_FIRMWARE
+ EMGD_DEBUG("pass count = %u, fail count = %u total = %u",
+ pass_count, fail_count, pass_count+fail_count);
+#endif
+} /* end displayid_filter_range_timings() */
+
+#define VESA_STD 1
+#define CEA_STD 2
+
+/*!
+ * Function to enable std timings: VESA STD or CEA STD
+ *
+ * @param tt1
+ * @param db_data
+ * @param lookup
+ * @param num_lookup
+ * @param std_type
+ *
+ * @return void
+ */
+void displayid_enable_std_timings(pd_timing_t *tt1, unsigned char *db_data,
+ type_std_t *lookup, unsigned short num_lookup, unsigned char std_type)
+{
+ unsigned short i;
+ pd_timing_t *tt;
+ /* If no timing table return. This can happen if no edid_avail set not to
+ * use std timings */
+ if (!tt1) {
+ return;
+ }
+
+ /* For every factory supported mode, enable it in the timing table */
+ for (i = 0; i < num_lookup; i++) {
+ tt = tt1;
+ /* i>>3 is nothing but dividing by 8, that gives the byte number,
+ * i&0x7 is nothing but getting the bit position in that byte */
+ if (db_data[i>>3] & 1<<(i&0x7)) {
+ while(tt->width != IGD_TIMING_TABLE_END) {
+ if (lookup[i].width == tt->width &&
+ lookup[i].height == tt->height &&
+#if 0
+ (!((lookup[i].flags & (PD_SCAN_INTERLACE|PD_MODE_RB)) ^
+ (tt->mode_info_flags & (PD_SCAN_INTERLACE|PD_MODE_RB)))) &&
+#endif
+ (!((lookup[i].flags & PD_SCAN_INTERLACE) ^
+ (tt->mode_info_flags & PD_SCAN_INTERLACE))) &&
+ (!((lookup[i].flags & PD_ASPECT_16_9) ^
+ (tt->mode_info_flags & PD_ASPECT_16_9))) &&
+ lookup[i].refresh == tt->refresh) {
+ tt->mode_info_flags |= (PD_MODE_FACTORY|PD_MODE_SUPPORTED);
+ break;
+ }
+ tt++;
+ if (tt->width == IGD_TIMING_TABLE_END && tt->extn_ptr) {
+ tt = tt->extn_ptr;
+ }
+ }
+ }
+ }
+}
+
+static void displayid_parse_orientation_info (unsigned char orientation_blob,
+ igd_DID_rotation_info_t * rotation_info) {
+
+ unsigned int def_orientation = DEFAULT_ORIENTATION(orientation_blob);
+ unsigned int zero_pixel = ZERO_PIXEL(orientation_blob);
+ unsigned int scan_dir = SCAN_DIRECTION(orientation_blob);
+
+ /* Start with no rotation */
+ rotation_info->rotation = 0;
+ rotation_info->flip = 0;
+
+
+ if (def_orientation >= DEF_ORIENTATION_UNKNOWN) {
+ /* Display ID blob is corrupted or unknown configuration set */
+ EMGD_DEBUG("DisplayID: Unknown default orientation value: %d",
+ def_orientation);
+ return;
+ }
+
+ if (scan_dir == SCAN_DIRECTION_LONG) {
+ if (def_orientation == DEF_ORIENTATION_PORTRAIT) {
+ rotation_info->flip =
+ (zero_pixel == ZP_UPPER_LEFT || zero_pixel == ZP_LOWER_RIGHT);
+ rotation_info->rotation += 90;
+ } else { /* Landscape */
+ rotation_info->flip =
+ (zero_pixel == ZP_UPPER_RIGHT || zero_pixel == ZP_LOWER_LEFT);
+ }
+
+ } else if (scan_dir == SCAN_DIRECTION_SHORT) {
+ if (def_orientation == DEF_ORIENTATION_PORTRAIT) {
+ rotation_info->flip =
+ (zero_pixel == ZP_UPPER_RIGHT || zero_pixel == ZP_LOWER_LEFT);
+ }
+ else { /* Landscape */
+ rotation_info->flip =
+ (zero_pixel == ZP_UPPER_LEFT || zero_pixel == ZP_LOWER_RIGHT);
+ rotation_info->rotation += 90;
+ }
+ } else { /* Unknown scan direction */
+ EMGD_DEBUG("DisplayID: Unknown scan direction value: %d", scan_dir);
+ return;
+ }
+
+ /* zero pixel is in the lower-half: need to rotate by 180 degs */
+ if (zero_pixel == ZP_LOWER_LEFT || zero_pixel == ZP_LOWER_RIGHT)
+ rotation_info->rotation += 180;
+}
+
+/*!
+ * Function to parse DisplayID
+ *
+ * @param buffer
+ * @param did
+ * @param timing_table
+ * @param count
+ * @param upscale
+ *
+ * @return void
+ */
+int displayid_parse(
+ unsigned char *buffer,
+ displayid_t *did,
+ pd_timing_t *timing_table,
+ int count,
+ unsigned char upscale)
+{
+ //unsigned char e = 0;
+ unsigned char checksum = 0, bytes_left;
+ unsigned short i;
+ unsigned short did_size;
+#ifndef CONFIG_MICRO
+ pd_timing_t *cea_tmg_table;
+#endif
+ /* Read 4 bytes: (DisplayID Header)
+ * version, revision
+ * payload
+ * display product type identifier
+ * number of extensions */
+ *(unsigned long *) did = *(unsigned long *)buffer;
+
+ /* Check for version and revision */
+ if (did->version != 1 && did->revision != 0) {
+ EMGD_DEBUG("DisplayID Version %d.%d Unknown. Will Ignore.",
+ did->version, did->revision);
+ return DISPLAYID_NOT_SUPPORTED;
+ }
+
+ if (did->payload > 251) {
+ EMGD_DEBUG("DispID: Error: payload = %u not in [0..251]", did->payload);
+ return DISPLAYID_ERROR_PARSE;
+ }
+
+ /* Check sum check */
+ /* +5 is for 5 mandatory bytes */
+ did_size = (unsigned short) (did->payload + 5);
+ EMGD_DEBUG("DisplayID size = %u", did_size);
+ for (i = 0; i < did_size; i++) {
+ checksum += buffer[i];
+ }
+
+ /* bytes_left starts without DisplayID header */
+ bytes_left = did->payload;
+ /* current pointer is at 4 not at 5, because checksum byte is at the end */
+ buffer += 4;
+
+ if (checksum) {
+ EMGD_DEBUG("DisplayID checksum is incorrect! Will ignore.");
+ return DISPLAYID_ERROR_PARSE;
+ }
+
+ /* DisplayID parsing should start by disabling all modes.
+ * Based on DisplayID data blocks modes will be enabled. */
+ enable_disable_timings(timing_table, 0);
+
+ /* Repeat for all extensions */
+ //e = did->num_extensions;
+ //while (e) {
+ {
+ //if (e != did->num_extensions) {
+ /* TODO: If there aren't enough bytes left in the buffer,
+ * call I2C read function to read next DisplayID section */
+
+ /* Skip next section header 4 bytes */
+ //bytes_left -= 4;
+ //break;
+ //}
+
+ /* Parse Data Blocks */
+ /* Check minimum number of bytes required for Data Block were left */
+ while ((bytes_left > 3) && (bytes_left >= (buffer[2]+3))) {
+ unsigned char *db_data;
+ unsigned char payload = buffer[2] + 3;
+
+ /* displayid->datablock = buffer (for payload bytes) */
+ if (buffer[0] < sizeof(db_offset)/sizeof(unsigned short)) {
+ OS_MEMCPY(((unsigned char*)did) + db_offset[buffer[0]],
+ buffer, payload);
+ }
+
+ /* db_data points to payload data after db header (3 bytes),
+ * Note: dummy_db offset is used for some DATA BLOCKS. See
+ * db_offset table above. */
+ db_data = (unsigned char *) &did->dummy_db[3];
+
+ switch (buffer[0]) {
+ /* Supported in Driver and VBIOS */
+ case DATABLOCK_DISPLAY_PARAMS:
+ /* Use following fields for fp_info:
+ * embedded use: fixed timing
+ * horizontal pixels: fp_width
+ * vertical pixels: fp_height */
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_PANEL_DEPTH;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ (did->display_params.overall_color_depth+1)*3;
+ break;
+
+ case DATABLOCK_TIMING_1_DETAIL:
+ /* One Type I block can have multiple DTDs */
+ while (payload>=20&&did->num_timings<DISPLAYID_MAX_NUM_TIMINGS){
+ convert_type1_to_pd(&did->timings[did->num_timings++],
+ (type1_dtd_t *)db_data);
+ db_data += 20;
+ payload -= 20;
+ bytes_left -= 20;
+ buffer += 20;
+ }
+ /* Mark the end of the list */
+ did->timings[did->num_timings].width = IGD_TIMING_TABLE_END;
+ break;
+
+ case DATABLOCK_TIMING_2_DETAIL:
+ /* One Type II block can have multiple DTDs */
+ while (payload>=11&&did->num_timings<DISPLAYID_MAX_NUM_TIMINGS){
+ convert_type2_to_pd(&did->timings[did->num_timings++],
+ (type2_dtd_t *)db_data);
+ db_data += 11;
+ payload -= 11;
+ bytes_left -= 11;
+ buffer += 11;
+ }
+ did->timings[did->num_timings].width = IGD_TIMING_TABLE_END;
+ break;
+
+ case DATABLOCK_VESA_TIMING_STD:
+ /* VESA Standard Timings */
+ displayid_enable_std_timings(
+ timing_table,
+ db_data,
+ vesa_std_lookup,
+ sizeof(vesa_std_lookup)/sizeof(type_std_t),
+ VESA_STD);
+ break;
+
+ case DATABLOCK_VIDEO_RANGE:
+ /* convert from Hz/10,000 -> KHz by multiplying by 10 */
+ did->timing_range.min_dclk =
+ ((unsigned long)did->timing_range.mindclk.lsb_min_dclk|
+ ((unsigned long)did->timing_range.mindclk.msb_min_dclk
+ <<16))*10;
+
+ did->timing_range.max_dclk =
+ ((unsigned long)did->timing_range.maxdclk.lsb_max_dclk|
+ ((unsigned long)did->timing_range.maxdclk.msb_max_dclk
+ <<16))*10;
+ displayid_filter_range_timings(timing_table,&did->timing_range,
+ PI_FIRMWARE_DISPLAYID);
+ break;
+
+ case DATABLOCK_DISPLAY_DEVICE:
+ /* Get panel color depth */
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_PANEL_DEPTH;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ (did->display_dev.display_color_depth+1)*3;
+ displayid_parse_orientation_info(did->display_dev.orientation,
+ &(did->rotation_info));
+ break;
+
+ case DATABLOCK_LVDS_INTERFACE:
+ /* Get T1-T5 values */
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T1;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->lvds.max_t1*2 + did->lvds.max_t2*2;
+
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T2;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->lvds.min_t5*10;
+
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T3;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->lvds.min_t6*10;
+
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T4;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->lvds.max_t3*2;
+
+ did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T5;
+ did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->lvds.min_t4*10 + did->lvds.max_t1*2;
+ break;
+
+ case DATABLOCK_DISPLAY_INTF:
+ if (did->display_intf.intf_type == INTERFACE_LVDS) {
+ /* Get number of channels: 0=singlechannel 1=dualchannel */
+ did->attr_list[did->num_attrs].id =
+ PD_ATTR_ID_2_CHANNEL_PANEL;
+ did->attr_list[did->num_attrs].flags =
+ PD_ATTR_FLAG_VALUE_CHANGED;
+ if (did->display_intf.num_channels == 2) {
+ did->attr_list[did->num_attrs++].current_value = 1;
+ }
+
+ /* Get panel type value: 0=normal 1=OpenLDI */
+ did->attr_list[did->num_attrs].id =
+ PD_ATTR_ID_LVDS_PANEL_TYPE;
+ did->attr_list[did->num_attrs].flags =
+ PD_ATTR_FLAG_VALUE_CHANGED;
+ did->attr_list[did->num_attrs++].current_value =
+ did->display_intf.lvds.openldi;
+ }
+
+ break;
+
+#ifndef CONFIG_MICRO
+ /* Support in Driver only */
+ case DATABLOCK_PRODUCTID:
+ break;
+
+ case DATABLOCK_SERIAL_NUMBER:
+ break;
+
+ case DATABLOCK_ASCII_STRING:
+ break;
+
+ case DATABLOCK_VENDOR_SPECIFIC:
+ /* Because vendor specific datablock tag is out-of-order,
+ * copy data from buffer to vendor structure */
+ OS_MEMCPY(&did->vendor, buffer, buffer[2] + 3);
+ break;
+
+ /* Future support in Driver and VBIOS */
+ case DATABLOCK_TIMING_3_SHORT:
+ break;
+
+ case DATABLOCK_TIMING_4_DMTID:
+ break;
+
+ /* Future support in Driver */
+ case DATABLOCK_COLOR_CHARS:
+ break;
+
+ case DATABLOCK_CEA_TIMING_STD:
+ cea_tmg_table = (igd_timing_info_t *)
+ OS_ALLOC(cea_timing_table_size);
+ OS_MEMCPY(cea_tmg_table, cea_timing_table,
+ cea_timing_table_size);
+ /* Disable the CEA timings */
+ enable_disable_timings(cea_tmg_table, 0);
+ displayid_enable_std_timings(
+ cea_tmg_table,
+ db_data,
+ cea_std_lookup,
+ (unsigned short)cea_std_lookup_size,
+ CEA_STD);
+
+ replace_vesa_dtds_with_cea_dtds(timing_table, cea_tmg_table);
+ cea_tmg_table[cea_timing_table_size-1].extn_ptr =
+ (void *)timing_table;
+ timing_table = cea_tmg_table;
+ break;
+#endif
+ case DATABLOCK_TRANSFER_CHAR:
+ break;
+ }
+
+ /* Subtract data block payload */
+ bytes_left -= payload;
+ buffer += payload;
+ }
+ /* Extension count */
+ //e--;
+ }
+
+ return 0;
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
new file mode 100644
index 0000000..d8a3c36
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
@@ -0,0 +1,1187 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: edid.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is contains all necessary functions for EDID reading and
+ * parsing into a data strucutures.
+ * Supported EDID versions:
+ * EDID 1.3 (backward compatible with 1.1, 1.2)
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+
+#include <igd_errno.h>
+
+#include <memory.h>
+#include <displayid.h>
+#include <edid.h>
+#include <pi.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Function to read EDID */
+/* Local functions */
+static void edid_mark_standard_timings(
+ unsigned char *buffer,
+ pd_timing_t *timings,
+ int established);
+
+static void edid_mark_detailed_timings(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timings,
+ unsigned char upscale);
+
+static void edid_parse_monitor_name(
+ unsigned char *buffer,
+ char *name);
+
+/* Edid Releated Constants */
+
+static const unsigned char name_blockid[] = {0x00, 0x00, 0x00, 0xfc};
+static const unsigned char range_blockid[] = {0x00, 0x00, 0x00, 0xfd};
+static const unsigned char st_blockid[] = {0x00, 0x00, 0x00, 0xfa};
+static const unsigned char timings_mask[] = {0xff, 0xff, 0xff, 0x00};
+extern igd_timing_info_t cea_timing_table[];
+/*
+ * Translation from the "Established" bit field position to a
+ * hactive, vactive, refresh that can be searched for in the
+ * timings list.
+ */
+static unsigned char established_table[] = {
+ /* 800x600 @ 60Hz */
+ 0x20, 0x03, 0x58, 0x02, 0x3c, 0x00,
+ /* 800x600 @ 56Hz */
+ 0x20, 0x03, 0x58, 0x02, 0x38, 0x00,
+ /* 640x480 @ 75Hz */
+ 0x80, 0x02, 0xe0, 0x01, 0x4b, 0x00,
+ /* 640x480 @ 72Hz */
+ 0x80, 0x02, 0xe0, 0x01, 0x48, 0x00,
+ /* 640x480 @ 67Hz */
+ 0x80, 0x02, 0xe0, 0x01, 0x43, 0x00,
+ /* 640x480 @ 60Hz */
+ 0x80, 0x02, 0xe0, 0x01, 0x3c, 0x00,
+ /* 720x400 @ 88Hz */
+ 0xd0, 0x02, 0x90, 0x01, 0x58, 0x00,
+ /* 720x400 @ 70Hz */
+ 0xd0, 0x02, 0x90, 0x01, 0x46, 0x00,
+
+ /* 1280x1024 @ 75Hz */
+ 0x00, 0x05, 0x00, 0x04, 0x4b, 0x00,
+ /* 1024x768 @ 75Hz */
+ 0x00, 0x04, 0x00, 0x03, 0x4b, 0x00,
+ /* 1024x768 @ 70Hz */
+ 0x00, 0x04, 0x00, 0x03, 0x46, 0x00,
+ /* 1024x768 @ 60Hz */
+ 0x00, 0x04, 0x00, 0x03, 0x3c, 0x00,
+ /* 1024x768 @ 43Hz (i) */
+ 0x00, 0x04, 0x00, 0x03, 0x2b, 0x00,
+ /* 832x624 @ 75Hz */
+ 0x40, 0x03, 0x70, 0x02, 0x4b, 0x00,
+ /* 800x600 @ 75Hz */
+ 0x20, 0x03, 0x58, 0x02, 0x4b, 0x00,
+ /* 800x600 @ 72Hz */
+ 0x20, 0x03, 0x58, 0x02, 0x48, 0x00,
+
+ /* 1152x870 @ 75Hz */
+ 0x80, 0x04, 0x66, 0x03, 0x4b, 0x00
+};
+
+#ifdef DEBUG_FIRMWARE
+/*!
+ *
+ * @param timing
+ * @param edid
+ *
+ * @return void
+ */
+static void print_supported_timings(
+ pd_timing_t *timing, edid_t *edid)
+{
+ unsigned short i, count = 0;
+ if (timing != NULL) {
+ while (timing->width != IGD_TIMING_TABLE_END) {
+ if (timing->mode_info_flags & PD_MODE_SUPPORTED) {
+ EMGD_DEBUG("\t%4u\t%4u\t%4u", timing->width,
+ timing->height, timing->refresh);
+ count++;
+ }
+
+ timing++;
+ if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+ }
+
+ if (edid && edid->num_timings) {
+ for (i=0; i<edid->num_timings; i++) {
+ if (edid->timings[i].mode_info_flags & PD_MODE_SUPPORTED) {
+ EMGD_DEBUG("\t%4u\t%4u\t%4u", edid->timings[i].width,
+ edid->timings[i].height, edid->timings[i].refresh);
+ count++;
+ }
+ }
+ }
+ EMGD_DEBUG("Total supported timings = %u", count);
+}
+
+/*!
+ * Dump the EDID to the kernel messages for debug
+ *
+ * @param buffer
+ * @param size
+ *
+ * @return void
+ */
+void firmware_dump(unsigned char *buffer, unsigned short size)
+{
+ unsigned short i;
+ EMGD_DEBUG("---------------------------------------------------------");
+ if (*(unsigned long *) &buffer[0] == 0xFFFFFF00 &&
+ *(unsigned long *) &buffer[4] == 0x00FFFFFF) {
+ size = 128;
+ EMGD_DEBUG("EDID DUMP (size = %u):", size);
+ } else {
+ /* For DisplayID payload is at byte 2 */
+ /* +5 is for 5 mandatory bytes */
+ size = buffer[1]+5;
+ EMGD_DEBUG("DisplayID DUMP (size = %u):", size);
+ }
+ EMGD_DEBUG("-------+-------------------------------------------------");
+ EMGD_DEBUG("Offset | Data.....");
+ EMGD_DEBUG("-------+-------------------------------------------------");
+
+ for (i=0; i<size; i+=8) {
+ EMGD_DEBUG(" 0x%2.2x | 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x",
+ i, buffer[i], buffer[i+1], buffer[i+2], buffer[i+3],
+ buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7]);
+ }
+ if (i>size) {
+ EMGD_DEBUG("Note: Ignore last row last %u bytes.", i-size);
+ }
+ EMGD_DEBUG("-------+-------------------------------------------------");
+ EMGD_DEBUG(" ");
+} /* edid_dump() */
+
+/*!
+ * Print the EDID Structure
+ *
+ * @param buffer
+ * @param size
+ *
+ * @return void
+ */
+void edid_print(edid_t *edid)
+{
+ int i;
+
+ EMGD_DEBUG("EDID Version: %d", edid->version);
+ EMGD_DEBUG("EDID Revision: %d", edid->revision);
+ EMGD_DEBUG("Vendor %s", edid->vendor);
+ EMGD_DEBUG("Model: %s", edid->name);
+ EMGD_DEBUG("Product Code: %ld", edid->product_code);
+ EMGD_DEBUG("Serial Number: %lu", edid->serial_number);
+ EMGD_DEBUG("Manufactored week: %d", edid->manf_week);
+ EMGD_DEBUG("Manufactored year: %ld", edid->manf_year);
+ EMGD_DEBUG("DPMS Flags: 0x%u", edid->dpms);
+ EMGD_DEBUG("Max Pixel Clock: %lu KHz", edid->range.max_dclk);
+ EMGD_DEBUG("H Range: %u - %u KHz",
+ edid->range.min_hrate, edid->range.max_hrate);
+ EMGD_DEBUG("V Range: %u - %u Hz",
+ edid->range.min_vrate, edid->range.max_vrate);
+
+ for (i=0; i<edid->num_timings; i++) {
+ EMGD_DEBUG("Detailied Timing Descriptor(DTD) %u", i+1);
+ EMGD_DEBUG(" dclk = %lu", edid->timings[i].dclk);
+ EMGD_DEBUG(" hactive = %u", edid->timings[i].width);
+ EMGD_DEBUG(" htotal = %u", edid->timings[i].htotal);
+ EMGD_DEBUG(" hblank_start = %u", edid->timings[i].hblank_start);
+ EMGD_DEBUG(" hsync_start = %u", edid->timings[i].hsync_start);
+ EMGD_DEBUG(" hsync_end = %u", edid->timings[i].hsync_end);
+ EMGD_DEBUG(" hblank_end = %u", edid->timings[i].hblank_end);
+ EMGD_DEBUG(" vactive = %u", edid->timings[i].height);
+ EMGD_DEBUG(" vtotal = %u", edid->timings[i].vtotal);
+ EMGD_DEBUG(" vblank_start = %u", edid->timings[i].vblank_start);
+ EMGD_DEBUG(" vsync_start = %u", edid->timings[i].vsync_start);
+ EMGD_DEBUG(" vsync_end = %u", edid->timings[i].vsync_end);
+ EMGD_DEBUG(" vblank_end = %u", edid->timings[i].vblank_end);
+ EMGD_DEBUG(" interlace = %u",
+ (edid->timings[i].mode_info_flags&PD_SCAN_INTERLACE)?1:0);
+ EMGD_DEBUG("hsync_polarity = %s",
+ (edid->timings[i].mode_info_flags & PD_HSYNC_HIGH)?
+ "ACTIVE HIGH":"ACTIVE LOW");
+ EMGD_DEBUG("vsync_polarity = %s",
+ (edid->timings[i].mode_info_flags & PD_VSYNC_HIGH)?
+ "ACTIVE HIGH":"ACTIVE LOW");
+ }
+} /* edid_print() */
+#endif
+
+/*!
+ * Function to disable all timings before marking supportecd timings
+ *
+ * @param timing
+ * @param enable
+ *
+ * @return void
+ */
+void enable_disable_timings(pd_timing_t *timing, unsigned char enable)
+{
+ if (!timing) {
+ return;
+ }
+
+ while(timing->width != IGD_TIMING_TABLE_END) {
+ if (enable) {
+ timing->mode_info_flags |= PD_MODE_SUPPORTED;
+ } else {
+ timing->mode_info_flags &= ~PD_MODE_SUPPORTED;
+ }
+ timing++;
+ if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+}
+
+/*!
+ * Function to enable timings based on port driver flags
+ *
+ * @param timing
+ * @param enable
+ *
+ * @return void
+ */
+void enable_scaled_timings(pd_timing_t *timing, pd_timing_t *dtd,
+ unsigned char upscale)
+{
+
+ if (!upscale || !dtd || !timing) {
+ return;
+ }
+
+ /* If port driver supports up scaling, enable all smaller modes. */
+ while(timing->width != IGD_TIMING_TABLE_END) {
+ if ((timing->width <= dtd->width) &&
+ (timing->height <= dtd->height) &&
+ (timing->refresh <= dtd->refresh)) {
+ timing->mode_info_flags |= IGD_MODE_SUPPORTED;
+ }
+ timing++;
+
+ /* If reached the first table END,
+ * then check for the added modes */
+ if (timing->width == IGD_TIMING_TABLE_END &&
+ timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+}
+
+/*!
+ * Parse an Edid Structure from a provided 128 byte buffer of data.
+ * This function will return EDID_READ_AGAIN if the driver should
+ * read another 128 bytes and call this function again. This will
+ * happen with EDID structures with one or more extended 128 byte regions.
+ * count is 0 on the first call and incremented with each extra 128
+ * byte buffer.
+ *
+ * This parser skips information that is not important to the driver.
+ * There should be an interface to provide the whole EDID to userspace
+ * where more advanced parsing can happen. If you need something exotic
+ * out of the EDID consider having a user app do it instead of making
+ * This in-kernel EDID parser large.
+ *
+ * Timings found in the "Established" and "Standard" bitfields or
+ * extension blocks will be looked up in the provided timings list.
+ * If a match is found the timings will be marked with
+ * PD_MODE_SUPPORTED.
+ *
+ * If the EDID provides frequency ranges all timings within the range will
+ * be marked with PD_MODE_SUPPORTED in timing_table.
+ *
+ * If a driver uses a single timings list for multiple displays the driver
+ * will have to copy the flags mentioned above into a bit range specific
+ * to each display (in the driver specific bit range).
+ *
+ * @param buffer
+ * @param edid
+ * @param timing_table
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return EDID_ERROR_PARSE on failure
+ */
+int edid_parse(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timing_table,
+ int count,
+ unsigned char upscale)
+{
+ int chksum = 0, i, j;
+ unsigned long version, vendor, temp32;
+ pd_timing_t *timing;
+
+ if (!edid || !buffer) {
+ return EDID_ERROR_PARSE;
+ }
+
+ /* No count means, edid_parse() called for first time */
+ if (!count) {
+ OS_MEMSET(edid, 0, sizeof(edid_t));
+ }
+
+ /* Check the checksum */
+ for (i=0; i<128; i++) {
+ chksum += buffer[i];
+ }
+
+ if ((chksum & 0xff) != 0) {
+ EMGD_DEBUG("EDID checksum is incorrect! Will ignore.");
+ return EDID_ERROR_PARSE;
+ }
+
+ /* FIXME: Verify this, I think extra EDID blocks have no header */
+ if (count) {
+ /* goto BLOCKS; */
+ return EDID_ERROR_PARSE;
+ }
+
+ /* Header already checked. Skip 8 bytes */
+ buffer+=8;
+
+ /* Vendor Name */
+ vendor = (buffer[0]<<8) | buffer[1];
+ *(unsigned long *)edid->vendor = ((vendor>>10) + 0x40) +
+ ((((vendor>>5) & 0x1f) + 0x40)<<8) +
+ ((unsigned long)((vendor & 0x1f) + 0x40)<<16);
+ buffer+=2;
+
+ /* Product Code */
+ edid->product_code = (buffer[1]<<8) | buffer[0];
+ buffer+=2;
+
+ /* Serial Number 4 bytes (SKIP)*/
+ edid->serial_number = buffer[0] |
+ (buffer[1]<<8) |
+ ((unsigned long)(buffer[2])<<16) |
+ ((unsigned long)(buffer[3])<<24);
+ buffer += 4;
+
+ /* Manufactured Week 1 byte (SKIP) */
+ edid->manf_week = buffer[0];
+ buffer++;
+
+ /* Manufactured Year 1 byte (SKIP) */
+ edid->manf_year = 1990 + buffer[0];
+ buffer++;
+
+ /* EDID Version/Revision 0x12-0x13 */
+ version = (buffer[0]<<8) | buffer[1];
+ edid->version = buffer[0];
+ edid->revision = buffer[1];
+ buffer += 2;
+
+ switch(version) {
+ case 0x0:
+ case 0x0101:
+ case 0x0102:
+ case 0x0103:
+ /* Possibly do something based on this */
+ break;
+ default:
+ EMGD_DEBUG("EDID Version %d.%d Unknown. Will Ignore.",
+ edid->version, edid->revision);
+ return EDID_ERROR_PARSE;
+ break;
+ }
+
+ /* Basic Display Params (SKIP) */
+ buffer+=4;
+
+ /* DPMS and Features 1 byte */
+ edid->dpms = (buffer[0]>>5);
+ edid->display_type = (buffer[0]>>3) & 0x3;
+ edid->standard_color = (buffer[0]>>2) & 0x1;
+ edid->preferred_timing = (buffer[0]>>1) & 0x1;
+ edid->gtf = (buffer[0] & 0x1);
+ buffer++;
+
+ /* Color 10 bytes (SKIP)*/
+ buffer+=10;
+
+ /* EDID parsing should start by disabling all modes.
+ * Based on EDID data, modes will be enabled. */
+ enable_disable_timings(timing_table, 0);
+
+ /* Based on the established timings provided in the EDID, mark the
+ * timings in the table as below (as per meeting with MikeD on 7/11/03):
+ *
+ * 1. If all VESA ETF and 640x480 modes are supported,
+ * then mark all modes in the table as supported + DTD modes
+ * 2. If all VESA ETF 60Hz modes are supported,
+ * then mark all 60Hz modes in the table as supported + DTD modes
+ * 3. Default:
+ * Enable only ETF modes in the table + DTD modes
+ *
+ * Established Timings 3 bytes (SKIP bits 6:0 of byte 3 which contains
+ * manufactorer's proprietary timings), so there are 17 established
+ * timings. */
+
+ /* Move byte2 bit7 to byte2 bit0. This is done to maintain
+ * continuation along with other 16 established timings */
+ temp32 = buffer[0] | ((unsigned long)(buffer[1])<<8) |
+ ((unsigned long)(buffer[2]>>7)<<16);
+
+ /* Here are the bit definitions:
+ * Byte 0
+ * bit 0 - 800 x 600 @ 60Hz VESA
+ * bit 1 - 800 x 600 @ 56Hz VESA
+ * bit 2 - 640 x 480 @ 75Hz VESA
+ * bit 3 - 640 x 480 @ 72Hz VESA
+ * bit 4 - 640 x 480 @ 67Hz Apple, Mac II
+ * bit 5 - 640 x 480 @ 60Hz IBM, VGA
+ * bit 6 - 720 x 400 @ 88Hz IBM, XGA2
+ * bit 7 - 720 x 400 @ 70Hz IBM, VGA
+ * Byte 1
+ * bit 0 - 1280 x 1024 @ 75Hz VESA
+ * bit 1 - 1024 x 768 @ 75Hz VESA
+ * bit 2 - 1024 x 768 @ 70Hz VESA
+ * bit 3 - 1024 x 768 @ 60Hz VESA
+ * bit 4 - 1024 x 768 @ 87Hz IBM (Interlaced)
+ * bit 5 - 832 x 624 @ 75Hz Apple, Mac II
+ * bit 6 - 800 x 600 @ 75Hz VESA
+ * bit 7 - 800 x 600 @ 72Hz VESA
+ * Byte 2
+ * bit 0 - 1152 x 870 @ 75Hz Apple, Mac II
+ *
+ * Note:
+ * Byte2 bit 0 used to be at Byte 2 bit 7 but moved to bit 0 for sake of
+ * continuality.
+ */
+ for (i=0; i<=16; i++) {
+ if (temp32 & (1L<<i)) {
+ edid_mark_standard_timings(&established_table[i*6],
+ timing_table, 1);
+ }
+ }
+
+#ifdef DEBUG_FIRMWARE
+ EMGD_DEBUG("Supported timings after FIRST established timings.");
+ print_supported_timings(timing_table, edid);
+#endif
+
+ if (timing_table != NULL) {
+ /* Mark the other timings in the table, as per above notes. */
+ timing = timing_table;
+ while (timing->width != IGD_TIMING_TABLE_END) {
+ if ((temp32 & 0xCF2F) == 0xCF2F) { /* Case 1 */
+ timing->mode_info_flags |= PD_MODE_SUPPORTED;
+ } else if (((temp32 & 0xCF2F) == 0x821) && /* Case 2 */
+ (timing->refresh == 60)) {
+ timing->mode_info_flags |= PD_MODE_SUPPORTED;
+ }
+
+ timing++;
+ if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+ }
+
+ buffer+=3;
+
+ /* Standard Timings 16 bytes, Look these up in the standard
+ * timings table to find the match. Skip any that are not found
+ * in the table.
+ */
+ for (i=0; i<8; i++) {
+ /* First 8 standard timings */
+ edid_mark_standard_timings(buffer, timing_table, 0);
+ buffer+=2;
+ }
+
+#ifdef DEBUG_FIRMWARE
+ EMGD_DEBUG("Supported timings after SECOND established timings.");
+ print_supported_timings(timing_table, edid);
+#endif
+
+ /* BLOCKS: */
+ /* Blocks of Data */
+ for (i=0; i<4; i++) {
+ if (*(unsigned long *)buffer == *(unsigned long *)name_blockid) {
+ /* Monitor Name */
+ edid_parse_monitor_name(&buffer[5], edid->name);
+ buffer+=18;
+ continue;
+ }
+ if (*(unsigned long *)buffer == *(unsigned long *)range_blockid) {
+ /* Monitor Limits */
+ edid->range_set = 1;
+ edid->range.min_vrate = buffer[5]; /* Hz */
+ edid->range.max_vrate = buffer[6]; /* Hz */
+ edid->range.min_hrate = buffer[7]; /* KHz */
+ edid->range.max_hrate = buffer[8]; /* KHz */
+ edid->range.max_dclk =
+ (unsigned long)buffer[9]*10000L; /* convert from MHz/10->KHz */
+ /* Following are always zero:
+ * edid->range.min_dclk
+ * edid->range->min_hblank
+ * edid->range->min_vblank */
+
+ /* Call common function to filter timings based on range limits */
+ displayid_filter_range_timings(timing_table, &edid->range,
+ PI_FIRMWARE_EDID);
+
+ /* Fixme GTF */
+ buffer+=18;
+ continue;
+ }
+ if (*(unsigned long *)buffer == *(unsigned long *)st_blockid) {
+ /* Additional 6 Standard Timings */
+ buffer+=5;
+ for (j=0; j<12; j+=2) {
+ edid_mark_standard_timings(&buffer[j], timing_table, 0);
+ }
+ buffer+=13;
+ continue;
+ }
+ if (*(unsigned long *)buffer & *(unsigned long *)timings_mask) {
+ /* Detailed Timings */
+ if (edid->num_timings >= NUM_TIMINGS-1) {
+ continue;
+ }
+ edid_mark_detailed_timings(buffer, edid, timing_table, upscale);
+ buffer+=18;
+ continue;
+ }
+ /* Don't handle Block types that don't matter */
+ buffer+=18;
+ } /* end for loop */
+
+#ifdef DEBUG_FIRMWARE
+ EMGD_DEBUG("FINAL supported timings .");
+ print_supported_timings(timing_table, edid);
+#endif
+
+ /* Extensions */
+ if (*buffer) {
+ return EDID_READ_AGAIN;
+ }
+
+ return 0;
+} /* end edid_parse() */
+
+/*!
+ * Given the two byte Standard Timings Identifier, Mark the timing
+ * that matches in the timings array.
+ * If "established" is set, the two byte "EDID id" will be used,
+ * otherwise the buffer should contain the hactive, followed by
+ * the vactive followed by the refresh, all in 16 bit LSB format.
+ *
+ * @param buffer
+ * @param timings
+ * @param established
+ *
+ * @return void
+ */
+static void edid_mark_standard_timings(
+ unsigned char *buffer,
+ pd_timing_t *timings,
+ int established)
+{
+ int hactive, vactive=0, refresh, aspect;
+
+ if ((!established) && (buffer[0] == 0x01) && (buffer[1] == 0x01)) {
+ return;
+ }
+ if (established) {
+ hactive = buffer[0] | (buffer[1]<<8);
+ vactive = buffer[2] | (buffer[3]<<8);
+ refresh = buffer[4] | (buffer[5]<<8);
+ }
+ else {
+ hactive = (buffer[0] + 31)<<3;
+ refresh = (buffer[1] & 0x1f) + 60;
+ aspect = buffer[1]>>6;
+ switch(aspect) {
+ case 0x0:
+ vactive = (hactive*10)>>4;
+ break;
+ case 0x1:
+ vactive = (hactive*3)>>2;
+ break;
+ case 0x2:
+ vactive = (hactive<<2)/5;
+ break;
+ case 0x3:
+ vactive = (hactive*9)>>4;
+ break;
+ default:
+ EMGD_ERROR("Invalid aspect ratio in EDID.");
+ return;
+ }
+ }
+
+ if (timings != NULL) {
+ /* Look for mode in table */
+ while (timings->width != IGD_TIMING_TABLE_END) {
+ /* By default no mode is supported. */
+ if ((timings->refresh == refresh) &&
+ (timings->width == hactive) &&
+ (timings->height == vactive)) {
+ timings->mode_info_flags |= PD_MODE_SUPPORTED;
+ return;
+ }
+
+ timings++;
+
+ if (timings->width == IGD_TIMING_TABLE_END && timings->extn_ptr) {
+ timings = timings->extn_ptr;
+ }
+ }
+ }
+
+ return;
+} /* end edid_mark_standard_timings() */
+
+/*!
+ * Parse a detailed timing block from the buffer provided and set the
+ * data in the pd_timing_t structure provided.
+ *
+ * @param buffer
+ * @param edid
+ * @param timing_table
+ * @param upscale
+ *
+ * @return void
+ */
+static void edid_mark_detailed_timings(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timing_table,
+ unsigned char upscale)
+{
+ unsigned long temp;
+ pd_timing_t *timings = &(edid->timings[edid->num_timings]);
+
+ timings->dclk = ((unsigned long)(buffer[1]<<8) | buffer[0]) * 10; /* KHz */
+ timings->width = ((buffer[4] & 0xf0)<<4) | buffer[2];
+ if (timings->width == 0) {
+ /* Bail out as DTD is invalid. This happens as we are estimating the
+ * amount of availabel DTD since manufacturer does not follow CEA
+ * format */
+ timings->width = IGD_TIMING_TABLE_END;
+ return;
+ }
+ timings->hblank_start = timings->width - 1;
+ timings->hblank_end = timings->width +
+ (((buffer[4]& 0xf)<<8) | buffer[3]) - 1;
+ timings->height = ((buffer[7] & 0xf0)<<4) | buffer[5];
+ timings->vblank_start = timings->height - 1;
+ timings->vblank_end = timings->height +
+ (((buffer[7]& 0xf)<<8)| buffer[6]) - 1;
+ timings->hsync_start = timings->hblank_start +
+ (((buffer[11] & 0xc0)<<2) | buffer[8]);
+ timings->hsync_end = timings->hsync_start +
+ (((buffer[11] & 0x30)<<4) | buffer[9]);
+ timings->vsync_start = timings->vblank_start +
+ (((buffer[11] & 0xc)<<2) | (buffer[10]>>4));
+ timings->vsync_end = timings->vsync_start +
+ (((buffer[11] & 0x3)<<4) | (buffer[10] & 0xf));
+ timings->htotal = timings->hblank_end;
+ timings->vtotal = timings->vblank_end;
+
+ /* SKIP BORDER */
+ timings->mode_info_flags |= (buffer[17] & 0x80)?PD_SCAN_INTERLACE:0;
+
+ /* Need to divide width by 2 and set PIXEL_DOUBLE flag in order to properly */
+ /* handle clock doubled modes like 1440(720)x480i and 1440(720)x576i */
+ if( (timings->mode_info_flags & PD_SCAN_INTERLACE) && (timings->width == 1440) &&
+ ((timings->height == 480) || (timings->height == 576)) )
+ {
+ timings->width /= 2;
+ timings->mode_info_flags |= IGD_PIXEL_DOUBLE;
+ }else if((timings->mode_info_flags & PD_SCAN_INTERLACE)){
+ /* The height needs to be multiplied by 2 here so OS would prepare the
+ correct frame buffer size. Pipe programming needs to be aware of this */
+ timings->height *= 2;
+ timings->vtotal *= 2;
+ timings->vblank_start *= 2;
+ timings->vblank_end *= 2;
+ timings->vsync_start *= 2;
+ timings->vsync_end *= 2;
+ }
+
+ /* Set sync polarities */
+ if((buffer[17] & 0x18)==0x18) { /* Bit 4 and 3 above = 11*/
+ /* if Bit 2 = 1, then vsync polarity = positive */
+ timings->mode_info_flags |= (buffer[17] & 0x04)? IGD_VSYNC_HIGH: 0;
+ /* if Bit 1 = 1, then hsync polarity = positive */
+ timings->mode_info_flags |= (buffer[17] & 0x02)? IGD_HSYNC_HIGH: 0;
+ }
+
+ if((buffer[17] & 0x18)==0x10) { /* Bit 4 and 3 above = 10*/
+ /* if Bit 1 = 1, then hsync polarity = positive */
+ timings->mode_info_flags |= (buffer[17] & 0x02)? IGD_HSYNC_HIGH: 0;
+ }
+
+ if (timings->dclk == 0) {
+ timings->dclk = 1;
+ }
+ if (timings->htotal == 0) {
+ timings->htotal = 1;
+ }
+ if (timings->vtotal == 0) {
+ timings->vtotal = 1;
+ }
+
+ temp = (unsigned long)timings->htotal * (unsigned long)timings->vtotal;
+ timings->refresh = (unsigned short)((timings->dclk * 1000)/temp);
+ timings->mode_info_flags |= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+
+ /* Save in the detailed timings of EDID */
+ edid->num_timings++;
+ /* Mark the end of the list */
+ edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+
+ /* Enable scale timings */
+ enable_scaled_timings(timing_table, timings, upscale);
+} /* end edid_mark_detailed_timings() */
+
+/*!
+ * Get the 13 (or less) character Monitor name from the buffer and
+ * pad with nulls.
+ *
+ * @param buffer
+ * @param name
+ *
+ * @return void
+ */
+static void edid_parse_monitor_name(unsigned char *buffer, char *name)
+{
+ int i;
+ for (i=0; i<13; i++) {
+ if (buffer[i] == 0x0a) {
+ name[i] = 0;
+ break;
+ }
+ name[i] = buffer[i];
+ }
+ while (i<14) {
+ name[i] = 0;
+ i++;
+ }
+} /* edid_parse_monitor_name() */
+
+#ifndef CONFIG_MICRO
+/*!
+ *
+ * @param edid
+ *
+ * @return 0
+ */
+int parse_audio_block(edid_t *edid)
+{
+ int i;
+ cea_audio_format_t *tmp_audio;
+
+ for(i=0; i<(edid->cea->total_short_audio_desc); i++){
+ tmp_audio = edid->cea->short_audio_desc + i;
+ if(tmp_audio->audio_format_code == CEA_AUDIO_LPCM){
+ if(tmp_audio->_48khz){
+ edid->cea->audio_cap[0].max_channels = tmp_audio->max_channels;
+ edid->cea->audio_cap[0]._20bit = tmp_audio->_20bit;
+ edid->cea->audio_cap[0]._24bit = tmp_audio->_24bit;
+ }
+ if(tmp_audio->_96khz){
+ edid->cea->audio_cap[1].max_channels = tmp_audio->max_channels;
+ edid->cea->audio_cap[1]._20bit = tmp_audio->_20bit;
+ edid->cea->audio_cap[1]._24bit = tmp_audio->_24bit;
+ if(tmp_audio->_88khz){
+ edid->cea->_44ms = 1;
+ }
+ }
+ if(tmp_audio->_192khz){
+ edid->cea->audio_cap[2].max_channels = tmp_audio->max_channels;
+ edid->cea->audio_cap[2]._20bit = tmp_audio->_20bit;
+ edid->cea->audio_cap[2]._24bit = tmp_audio->_24bit;
+ if(tmp_audio->_176khz){
+ edid->cea->_44ms = 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ *
+ * @param buffer
+ * @param list
+ * @param block_size
+ * @param total_bytes
+ *
+ * @return 0 no read will happen
+ * @return total_blocks
+ */
+int read_data_block_collection(unsigned char *buffer,
+ char **list,
+ unsigned int block_size,/* Block size in byte */
+ unsigned int total_bytes)
+{
+ unsigned int total_blocks;
+ unsigned int i;
+
+ total_blocks = total_bytes/block_size;
+ if(total_bytes <= 0 ){
+ /* No read will happen */
+ return 0;
+ }
+
+ if(*list !=NULL){
+ OS_FREE(*list);
+ }
+
+ *list = OS_ALLOC((sizeof(char)*total_bytes));
+ for(i=0;i<total_blocks;i++){
+ OS_MEMCPY(*list+i, buffer, block_size);
+ buffer+=block_size;
+ }
+
+ return total_blocks;
+}
+
+/*!
+ *
+ * @param buffer
+ * @param edid
+ * @param timings
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return EDID_ERROR_PARSE on failure
+ */
+int edid_parse_cea (unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timings,
+ int count,
+ unsigned char upscale)
+{
+ unsigned int offset,i = 4,timing_in_edid = 0, j;
+ unsigned int tag_code, chksum=0;
+ unsigned char *data_block_buffer;
+ pd_timing_t *cea_timings = NULL;
+ pd_timing_t *temp_timings;
+ unsigned short header;
+
+ if (!buffer) {
+ return EDID_ERROR_PARSE;
+ }
+ /* This holds the buffer */
+ offset = buffer[2];
+ /* Check the checksum */
+ for( i=0; i<128; i++) {
+ chksum += buffer[i];
+ }
+ if ((chksum & 0xff) != 0) {
+ EMGD_ERROR("EDID checksum is incorrect! Will ignore.");
+ return EDID_ERROR_PARSE;
+ }
+
+ header = buffer[0];
+
+ /* DI-Extension(header == 0x40) Unsupported for now */
+ if(header != 0x02){ /* CEA-Extension */
+ EMGD_ERROR("Unknown Extension");
+ return EDID_ERROR_PARSE;
+ }
+
+ if(edid->cea == NULL){
+ edid->cea = (cea_extension_t *) OS_ALLOC(sizeof(cea_extension_t));
+ }
+ if(edid->cea == NULL){
+ EMGD_ERROR("Run out of memory");
+ return 1;
+ }
+ OS_MEMSET(edid->cea, 0 , (sizeof(cea_extension_t)));
+ edid->cea->rev_number = buffer [1];
+ edid->cea->caps = buffer [3];
+
+ // no data block found or data block exceeds maximum buffer size
+ if(offset == 0 || offset > 124) {
+ EMGD_ERROR("No data block and no DTD ");
+ return 1;
+ }
+
+ /* General Format of CEA Data Block Collection
+ // -----------+--------------------+--------------------------------------+
+ // |Byte# |Bits5-7 | Bits 0-4 |
+ // -----------|--------------------+--------------------------------------+
+ // | 1 | Video Tag |Length = total #of video |
+ // | | Code |bytes following this byte (L1) |
+ // |--------------------+--------------------------------------+
+ // Video | 2 | CEA Short Video Descriptor 1 |
+ // Data |--------+--------------------------------------------------|
+ // Block | 3 | CEA Short Video Descriptor 2 |
+ // |--------+--------------------------------------------------|
+ // | ... | ... |
+ // |-----------------------------------------------------------+
+ // | 1+L1 | CEA Short Video Descriptor L1 |
+ // -----------+--------------------+--------------------------------------+
+ // | 2+L1 | Audio Tag |Length = total #of audio bytes |
+ // | | Code |following this byte (L2) |
+ // |--------------------+--------------------------------------+
+ // Audio | 3+L1 | |
+ // Data |--------+ |
+ // Block | 4+L1 | CEA Short Audio Descriptor 1 |
+ // |--------+ |
+ // | 5+L1 | |
+ // |-----------------------------------------------------------+
+ // | ... | |
+ // | | |
+ // | | |
+ // | ... | |
+ // |------------------------------------------------------------
+ // |L1+L2 | |
+ // |--------| |
+ // |1+L1+L2 | CEA Short Audio Descriptor L2/3 |
+ // |--------| |
+ // |2+L1+L2 | |
+ // -----------+-----------------------------------------------------------+
+ // |3+L1+L2 | Speaker |Length = total #of SA bytes following |
+ // | | Tag Code |this byte (L1) |
+ // Speaker |-----------------------------------------------------------+
+ // Allocation|4+L1+L2 | |
+ // Data |--------| |
+ // Block |5+L1+L2 | Speaker Allocation Data Block Payload(3 bytes) |
+ // |--------| |
+ // |6+L1+L2 | |
+ // -----------+-----------------------------------------------------------+
+ // |7+L1+L2 | VSDB Tag |Length = total #of VSDB bytes |
+ // | | Code |following this byte (L1) |
+ // Vendor |-----------------------------------------------------------+
+ // Specific |8+L1+L2 | |
+ // Data |--------| |
+ // Block |9+L1+L2 | 24-bit IEEE Registration Identifier (LSB first) |
+ // |--------| |
+ // |10+L1+L2| |
+ // |-----------------------------------------------------------+
+ // | ... | Vendor Specific Data block Payload |
+ // -----------+-----------------------------------------------------------+*/
+ data_block_buffer=&buffer[4];
+ /* Start reading data block collection */
+ i = 0;
+ while(i<offset){
+ unsigned int total_bytes;
+ tag_code = (unsigned int)*data_block_buffer & 0xE0;
+ total_bytes = (unsigned int)*data_block_buffer & 0x1F;
+ data_block_buffer++;
+ i++;
+ switch(tag_code){
+ case CEA_VIDEO_DATA_BLOCK:
+ /* Reading Short Video Descriptor block */
+ edid->cea->total_short_video_desc =read_data_block_collection
+ (data_block_buffer,
+ (char **)&edid->cea->short_video_desc,
+ 1,/* Block size in byte */
+ total_bytes);
+ break;
+ case CEA_AUDIO_DATA_BLOCK:
+ /* Reading Short Audio Descriptor block */
+ edid->cea->total_short_audio_desc = read_data_block_collection
+ (data_block_buffer,
+ (char **)&edid->cea->short_audio_desc,
+ 3,/* Block size in byte */
+ total_bytes);
+ /* uncomment this codes if this info is requred in the future */
+ /*for(j=0; j<total_bytes; j+=3){
+ OS_MEMCPY
+ (&edid->cea->misc_data[j],
+ (edid->cea->short_audio_desc + (j/3)),
+ sizeof(cea_audio_format_t));
+ }
+ edid->cea->sadc = (unsigned char)
+ edid->cea->total_short_audio_desc; */
+ break;
+ case CEA_VENDOR_DATA_BLOCK:
+ /* Reading Vendor Specific Descriptor block */
+ edid->cea->vendor_block.vendor_block_size = (unsigned char)total_bytes;
+ OS_MEMCPY(edid->cea->vendor_block.vendor_ieee_id, data_block_buffer, 3);
+ read_data_block_collection
+ (data_block_buffer,
+ (char **)&edid->cea->vendor_data_block,
+ 3,
+ total_bytes);
+ break;
+ case CEA_SPEAKER_DATA_BLOCK:
+ /* Reading Speaker Data Descriptor block */
+ for(j=0; j<3; j++){
+ edid->cea->speaker_alloc_block[j] = data_block_buffer[j];
+ }
+ break;
+ default:
+ /* Ignore unknown block? */
+ EMGD_ERROR("Unknown Tag Code! : CEA extended data block");
+ break;
+ }
+ data_block_buffer+=(total_bytes);
+ i+=(total_bytes);
+ };
+
+ /* DPG codes show that they are manufacturer who doesn't follow the spec
+ Calculate the maximum possible DTD from whatever empty space left.
+ The Maximum DTD is 6*/
+ i=(unsigned int)(128-offset-1)/18;
+ i = (i>6)?6:i;
+
+ buffer+=offset;
+ while(i>0){
+ if (edid->num_timings >= NUM_TIMINGS-1) {
+ break;
+ }
+ edid_mark_detailed_timings(buffer, edid, timings, upscale);
+ buffer+=18;
+ i--;
+ };
+
+ /* Parse audio block to know panel audio capability */
+ parse_audio_block(edid);
+
+ cea_timings = (igd_timing_info_t *) OS_ALLOC(cea_timing_table_size);
+ OS_MEMCPY(cea_timings, cea_timing_table, cea_timing_table_size);
+
+ for(i=0; i<(unsigned int)edid->cea->total_short_video_desc; i++){
+ EMGD_DEBUG("Video Code %d",(int)(edid->cea->short_video_desc + i)->code);
+ temp_timings = cea_timings;
+ timing_in_edid = 0;
+ while (temp_timings->width != IGD_TIMING_TABLE_END){
+ /* Look for matching tag code */
+ if((edid->cea->short_video_desc + i)->code == temp_timings->mode_number){
+ j=0;
+ while(j<edid->num_timings){
+ /* Ignore if we have already read the timng through DTD
+ dclk would be sufficient to differentiate between progressive
+ and interlace */
+ if(temp_timings->width == edid->timings[j].width &&
+ temp_timings->height == edid->timings[j].height &&
+ temp_timings->refresh == edid->timings[j].refresh &&
+ temp_timings->dclk == edid->timings[j].dclk){
+ timing_in_edid = 1;
+ break;
+ }
+ j++;
+ }
+ /* Add the timing if we have not done so through DTD */
+ if(!(timing_in_edid)){
+ if (edid->num_timings >= NUM_TIMINGS-1) {
+ break;
+ }
+ OS_MEMCPY(&edid->timings[edid->num_timings],
+ temp_timings, sizeof(pd_timing_t));
+ edid->timings[edid->num_timings].mode_number = 0;
+ edid->timings[edid->num_timings].mode_info_flags
+ |= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+ edid->num_timings++;
+ edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+ /*enable_scaled_timings(timings,
+ &edid->timings[edid->num_timings], upscale);*/
+ }
+ break;
+ }
+ temp_timings++;
+ }
+ }
+
+ OS_FREE(cea_timings);
+
+#ifdef DEBUG_FIRMWARE
+ EMGD_ERROR("FINAL supported timings after CEA .");
+ print_supported_timings(timings, edid);
+#endif
+ return 0;
+}
+#endif
+
+/*!
+ *
+ * @param buffer
+ * @param edid
+ * @param timings
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int edid_ext_parse(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timings,
+ int count,
+ unsigned char upscale)
+{
+ unsigned int timing_in_edid = 0, j;
+#ifndef CONFIG_MICRO
+ if(edid_parse_cea(buffer, edid, timings, count, upscale)){
+ EMGD_ERROR("Reading cea extension ERROR!");
+ return 1;
+ }
+#endif
+
+ /* Check to see if 640x480 is part of EDID timing if not add it in.
+ CEA panels does not support standard timing 640x480 */
+ for(j=0; j<edid->num_timings; j++){
+ if(edid->timings[j].width == 640 &&
+ edid->timings[j].height == 480 &&
+ edid->timings[j].refresh == 60 ){
+ timing_in_edid = 1;
+ break;
+ }
+ }
+ if((!timing_in_edid) && (edid->num_timings < NUM_TIMINGS-1)){
+ OS_MEMCPY(&edid->timings[edid->num_timings],
+ cea_timing_table, sizeof(pd_timing_t));
+ edid->timings[edid->num_timings].mode_number = 0x101;
+ edid->timings[edid->num_timings].mode_info_flags
+ |= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+ edid->num_timings++;
+ edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+ }
+
+ return 0;
+}/* end edid_parse_ext() */
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
new file mode 100755
index 0000000..ae98630
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _I2C_DISPATCH_H
+#define _I2C_DISPATCH_H
+
+/*
+ * IO.h is needed to resolve the FAR define
+ * context.h is needed for the igd_display_context_t
+ */
+
+#include <io.h>
+#include <context.h>
+#include <mode.h>
+
+#include <pd.h>
+
+#define I2C_DEFAULT_SPEED 100 /* Default I2C bus speed in KHz */
+#define DDC_DEFAULT_SPEED 10 /* Default DDC bus speed in KHz */
+
+/*
+ * Flags for Write Reg List
+ *
+ * Serial Write: Write a Reg Value, Data Value repeatedly within one
+ * write cycle.
+ */
+#define IGD_I2C_SERIAL_WRITE 0x1
+#define IGD_I2C_WRITE_FW 0x2
+
+typedef struct _i2c_dispatch {
+ int (*i2c_read_regs)(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags);
+ int (*i2c_write_reg_list)(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags);
+} i2c_dispatch_t;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
new file mode 100644
index 0000000..1cf54ce
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
@@ -0,0 +1,260 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pi.c
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Callback functions to give to port drivers. All functions are provided
+ * to port driver as callback functions. Only port driver should call
+ * these functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <context.h>
+
+#include <memory.h>
+#include <sched.h>
+
+/* #include <igd_pi.h> */
+#include <igd_debug.h>
+
+#include <pi.h>
+#include <pd.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*!
+ * Function to register with main driver.
+ *
+ * @param handle
+ * @param pd_driver
+ *
+ * @return pi_pd_register()
+ */
+int igd_pd_register(void *handle, void *pd_driver)
+{
+ return pi_pd_register(pd_driver);
+} /* igd_pd_register */
+
+/*!
+ * Function to allocate memory
+ *
+ * @param handle
+ * @param pd_driver
+ *
+ * @return void
+ */
+void *igd_pd_malloc(unsigned long size)
+{
+ return OS_ALLOC(size);
+} /* end igd_pd_malloc */
+
+/*!
+ * Function to set the memory
+ *
+ * @param address
+ * @param c
+ * @param size
+ *
+ * @return void
+ */
+void *igd_pd_memset(void *address, int c, unsigned long size)
+{
+ return OS_MEMSET(address, c, size);
+} /* end igd_pd_memset */
+
+/*!
+ * Function to copy block of memory
+ *
+ * @param dst
+ * @param src
+ * @param size
+ *
+ * @return void
+ */
+void *igd_pd_memcpy(void *dst, void *src, unsigned long size)
+{
+ return OS_MEMCPY(dst, src, size);
+} /* end igd_pd_memcpy */
+
+/* Functions to free memory */
+void igd_pd_free(void *ptr)
+{
+ OS_FREE(ptr);
+} /* end igd_pd_free */
+
+/*!
+ * Function to sleep in micro seconds. This can be called with millisecond
+ * ranges.
+ *
+ * @param usec
+ *
+ * @return void
+ */
+void igd_pd_usleep(unsigned long usec)
+{
+ if (usec <= 1000) {
+ OS_SLEEP(usec);
+ } else {
+ os_alarm_t alarm = OS_SET_ALARM((usec+999)/1000);
+ do {
+ OS_SCHEDULE();
+ } while (!OS_TEST_ALARM(alarm));
+ }
+} /* end igd_pd_usleep() */
+
+/*!
+ * Function to do a string copy
+ *
+ * @param dest
+ * @param src
+ *
+ * @return dest
+ */
+char *igd_pd_strcpy(char *dest, char const *src)
+{
+ int i = 0;
+ /* This can be optimized by assigning 32 bit quantities instead
+ * of 8 bit quantities. This requires knowing the length first then
+ * move the quantities. For now, this is OK. */
+ while (src[i] != '\0') {
+ dest[i] = src[i];
+ i++;
+ }
+ dest[i] = '\0';
+ return (dest);
+} /* end igd_pd_strcpy() */
+
+/*!
+ * Function to check value of an attribute
+ *
+ * @param curr
+ * @param in
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_NULL_PTR,PD_ERR_INVALID_ATTR, or PD_ERR_INCORR_ATTR_VALUE
+ * on failure
+ */
+int igd_pd_check_attr(pd_attr_t *curr, pd_attr_t *in)
+{
+ if (!curr || !in) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ if (curr->id != in->id) {
+ return PD_ERR_INVALID_ATTR;
+ }
+
+ switch (curr->type) {
+ case PD_ATTR_TYPE_RANGE:
+ if ((in->current_value < RATTR(curr)->min) ||
+ (in->current_value > RATTR(curr)->max)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ case PD_ATTR_TYPE_LIST:
+ if ((in->current_value < 1) ||
+ (in->current_value > LHATTR(curr)->num_entries)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ case PD_ATTR_TYPE_BOOL:
+ if ((in->current_value != TRUE) &&
+ (in->current_value != FALSE)) {
+ return PD_ERR_INCORR_ATTR_VALUE;
+ }
+ break;
+ default:
+ return PD_ERR_INVALID_ATTR;
+ }
+ return PD_SUCCESS;
+} /* end igd_pd_check_attr() */
+
+/*!
+ * This function searches for the requested attr_id in the attribute list
+ * and returns the pointer.
+ *
+ * In case of LIST attribute, it will return the proper list entry.
+ *
+ * @param attr_list
+ * @param num_attrs
+ * @param attr_id
+ * @param flag
+ *
+ * @return attr_list on success
+ * @return NULL on failure
+ */
+pd_attr_t *igd_pd_get_attr(pd_attr_t *attr_list, unsigned long num_attrs,
+ unsigned long attr_id, unsigned long flag)
+{
+ unsigned long i;
+
+ if (!attr_list) {
+ return NULL;
+ }
+
+ for (i = 0; i < num_attrs; i++) {
+ if (attr_list[i].id == attr_id) {
+ if (attr_list[i].type == PD_ATTR_TYPE_LIST) {
+ if (flag == PD_GET_ATTR_LIST_ENTRY) {
+ return (&(attr_list[i+attr_list[i].current_value]));
+ } else {
+ return (&(attr_list[i]));
+ }
+ }
+ return (&(attr_list[i]));
+ }
+ }
+ return NULL;
+} /* end igd_pd_get_attr() */
+
+/*!
+ * Common mode filter algorithm for all port drivers
+ *
+ * @param context
+ * @param ilist
+ * @param olist
+ * @param dvo
+ * @param display
+ *
+ * @return pd_filter_timings()
+ */
+int igd_pd_filter_timings(
+ void *context,
+ pd_timing_t *ilist,
+ pd_timing_t **olist,
+ pd_dvo_info_t *dvo,
+ pd_display_info_t *display)
+{
+ return pd_filter_timings(context, ilist, olist, dvo, display);
+}
+
+igd_debug_t *igd_pd_get_igd_debug( void )
+{
+ return emgd_debug;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
new file mode 100644
index 0000000..d698875
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
@@ -0,0 +1,2545 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_table.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the mode resolution parameters.
+ *-----------------------------------------------------------------------------
+ */
+
+#define TRUE 1
+#define FALSE 0
+
+#include <config.h>
+#include <mode.h>
+
+/*
+ * If CONFIG_LIMIT_MODES is not defined then ALL modes should be included.
+ * Keep the defines here so that when adding new modes it is apparent that
+ * you should add it to the list below.
+ */
+#ifndef CONFIG_LIMIT_MODES
+#define CONFIG_MODE_640x480x60
+#define CONFIG_MODE_640x480x70
+#define CONFIG_MODE_640x480x72
+#define CONFIG_MODE_640x480x75
+#define CONFIG_MODE_640x480x85
+#define CONFIG_MODE_640x480x100
+#define CONFIG_MODE_640x480x120
+#define CONFIG_MODE_720x480x60
+#define CONFIG_MODE_720x576x50
+#define CONFIG_MODE_800x480x60
+#define CONFIG_MODE_800x600x60
+#define CONFIG_MODE_800x600x70
+#define CONFIG_MODE_800x600x72
+#define CONFIG_MODE_800x600x75
+#define CONFIG_MODE_800x600x85
+#define CONFIG_MODE_800x600x100
+#define CONFIG_MODE_800x600x120
+#define CONFIG_MODE_960x540x60
+#define CONFIG_MODE_1024x768x60
+#define CONFIG_MODE_1024x768x70
+#define CONFIG_MODE_1024x768x75
+#define CONFIG_MODE_1024x768x85
+#define CONFIG_MODE_1024x768x100
+#define CONFIG_MODE_1024x768x120
+#define CONFIG_MODE_1152x864x60
+#define CONFIG_MODE_1152x864x70
+#define CONFIG_MODE_1152x864x72
+#define CONFIG_MODE_1152x864x75
+#define CONFIG_MODE_1152x864x85
+#define CONFIG_MODE_1152x864x100
+#define CONFIG_MODE_1280x720x60
+#define CONFIG_MODE_1280x720x75
+#define CONFIG_MODE_1280x720x85
+#define CONFIG_MODE_1280x720x100
+#define CONFIG_MODE_1280x768x60
+#define CONFIG_MODE_1280x768x75
+#define CONFIG_MODE_1280x768x85
+#define CONFIG_MODE_1280x960x60
+#define CONFIG_MODE_1280x960x75
+#define CONFIG_MODE_1280x960x85
+#define CONFIG_MODE_1280x1024x60
+#define CONFIG_MODE_1280x1024x70
+#define CONFIG_MODE_1280x1024x72
+#define CONFIG_MODE_1280x1024x75
+#define CONFIG_MODE_1280x1024x85
+#define CONFIG_MODE_1280x1024x100
+#define CONFIG_MODE_1280x1024x120
+#define CONFIG_MODE_1366x768x60
+#define CONFIG_MODE_1400x1050x60
+#define CONFIG_MODE_1400x1050x75
+#define CONFIG_MODE_1400x1050x85
+#define CONFIG_MODE_1600x900x60
+#define CONFIG_MODE_1600x900x75
+#define CONFIG_MODE_1600x900x85
+#define CONFIG_MODE_1600x900x100
+#define CONFIG_MODE_1600x900x120
+#define CONFIG_MODE_1600x1200x60
+#define CONFIG_MODE_1600x1200x65
+#define CONFIG_MODE_1600x1200x70
+#define CONFIG_MODE_1600x1200x72
+#define CONFIG_MODE_1600x1200x75
+#define CONFIG_MODE_1600x1200x85
+#define CONFIG_MODE_1600x1200x100
+#define CONFIG_MODE_1600x1200x120
+#define CONFIG_MODE_1856x1392x60
+#define CONFIG_MODE_1856x1392x75
+#define CONFIG_MODE_1920x1080x50
+#define CONFIG_MODE_1920x1080x60
+#define CONFIG_MODE_1920x1080x75
+#define CONFIG_MODE_1920x1080x85
+#define CONFIG_MODE_1920x1080x100
+#define CONFIG_MODE_1920x1200x60
+#define CONFIG_MODE_1920x1200x75
+#define CONFIG_MODE_1920x1440x60
+#define CONFIG_MODE_1920x1440x75
+#define CONFIG_MODE_1920x1440x85
+#define CONFIG_MODE_2048x1536x60
+#define CONFIG_MODE_2048x1536x75
+/* CEA timings */
+#define CONFIG_CEA_MODE_640x480px60
+#ifndef CONFIG_MICRO
+/* These are timings that has duplicate except the difference in aspect
+ ratio. Since IEGD does not support diffrent aspect ratio removing
+ these CEA timings for now */
+/*
+#define CONFIG_CEA_MODE_720x480px60
+#define CONFIG_CEA_MODE_720x576px50*/
+#define CONFIG_CEA_MODE_720x480p_ax60
+#define CONFIG_CEA_MODE_720x576p_ax50
+#define CONFIG_CEA_MODE_1280x720p_ax50
+#define CONFIG_CEA_MODE_1280x720p_ax60
+#define CONFIG_CEA_MODE_1920x1080p_ax50
+#define CONFIG_CEA_MODE_1920x1080p_ax60
+#define CONFIG_CEA_MODE_1920x1080i_ax50
+#define CONFIG_CEA_MODE_1920x1080i_ax60
+#endif /* CONFIG_MICRO */
+
+#endif
+
+/*---------------------------------------------------------------------------
+ * Timing tables for CRT modes.
+ *---------------------------------------------------------------------------
+ */
+
+igd_timing_info_t crt_timing_table[] =
+{
+/* TODO: Add VESA standard REDUCED BLANKING (RB) timings to the table */
+#ifdef CONFIG_MODE_640x480x60
+ {
+ 640, 480, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 647, 791, /* hblank_start, hblank_end */
+ 655, 751, /* hsync_start, hsync_end */
+ 524, /* vtotal */
+ 487, 516, /* vblank_start, vblank_end */
+ 489, 491, /* vsync_start, vsync_end */
+ 0x101, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x70
+ {
+ 640, 480, /* width, height */
+ 70, 28560, /* refresh, dot clock */
+ 815, /* htotal */
+ 639, 815, /* hblank_start, hblank_end */
+ 663, 727, /* hsync_start, hsync_end */
+ 499, /* vtotal */
+ 479, 499, /* vblank_start, vblank_end */
+ 480, 483, /* vsync_start, vsync_end */
+ 0x101, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x72
+ {
+ 640, 480, /* width, height */
+ 72, 31500, /* refresh, dot clock */
+ 831, /* htotal */
+ 647, 823, /* hblank_start, hblank_end */
+ 663, 703, /* hsync_start, hsync_end */
+ 519, /* vtotal */
+ 487, 511, /* vblank_start, vblank_end */
+ 488, 491, /* vsync_start, vsync_end */
+ 0x101, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x75
+ {
+ 640, 480, /* width, height */
+ 75, 31500, /* refresh, dot clock */
+ 839, /* htotal */
+ 639, 839, /* hblank_start, hblank_end */
+ 655, 719, /* hsync_start, hsync_end */
+ 499, /* vtotal */
+ 479, 499, /* vblank_start, vblank_end */
+ 480, 483, /* vsync_start, vsync_end */
+ 0x101, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x85
+ {
+ 640, 480, /* width, height */
+ 85, 36000, /* refresh, dot clock */
+ 831, /* htotal */
+ 639, 831, /* hblank_start, hblank_end */
+ 695, 751, /* hsync_start, hsync_end */
+ 508, /* vtotal */
+ 479, 508, /* vblank_start, vblank_end */
+ 480, 483, /* vsync_start, vsync_end */
+ 0x101, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x100
+ {
+ 640, 480, /* width, height */
+ 100, 43163, /* refresh, dot clock */
+ 847, /* htotal */
+ 639, 847, /* hblank_start, hblank_end */
+ 679, 743, /* hsync_start, hsync_end */
+ 508, /* vtotal */
+ 479, 508, /* vblank_start, vblank_end */
+ 480, 483, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_640x480x120
+ {
+ 640, 480, /* width, height */
+ 120, 52406, /* refresh, dot clock */
+ 847, /* htotal */
+ 639, 847, /* hblank_start, hblank_end */
+ 679, 743, /* hsync_start, hsync_end */
+ 514, /* vtotal */
+ 479, 514, /* vblank_start, vblank_end */
+ 480, 483, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_720x400x70
+ /* NOTE: The above define is not auto-enabled. This is the VGA magic mode */
+ { /* VGA Mode 2+,3+ */
+ 720, 400, /* width, height */
+ 70, 28322, /* refresh, dot clock */
+ 899, /* htotal */
+ 719, 899, /* hblank_start, hblank_end */
+ 773, 881, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 399, 448, /* vblank_start, vblank_end */
+ 412, 414, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_VSYNC_HIGH |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_720x480x60
+ {
+ 720, 480, /* width, height */
+ 60, 27000, /* refresh, dot clock */
+ 857, /* htotal */
+ 719, 857, /* hblank_start, hblank_end */
+ 735, 797, /* hsync_start, hsync_end */
+ 524, /* vtotal */
+ 479, 524, /* vblank_start, vblank_end */
+ 488, 494, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_720x576x50
+ {
+ 720, 576, /* width, height */
+ 50, 27500, /* refresh, dot clock */
+ 864, /* htotal */
+ 719, 864, /* hblank_start, hblank_end */
+ 732, 795, /* hsync_start, hsync_end */
+ 625, /* vtotal */
+ 575, 625, /* vblank_start, vblank_end */
+ 581, 587, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+ /* OFF BY Default, enable when PLB is merged */
+#ifdef CONFIG_MODE_800x480x60
+ {
+ 800, 480, /* width, height */
+ 60, 33231, /* refresh, dot clock */
+ 1055, /* htotal */
+ 799, 1055, /* hblank_start, hblank_end */
+ 863, 991, /* hsync_start, hsync_end */
+ 524, /* vtotal */
+ 479, 524, /* vblank_start, vblank_end */
+ 500, 502, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x60
+ {
+ 800, 600, /* width, height */
+ 60, 40000, /* refresh, dot clock */
+ 1055, /* htotal */
+ 799, 1055, /* hblank_start, hblank_end */
+ 839, 967, /* hsync_start, hsync_end */
+ 627, /* vtotal */
+ 599, 627, /* vblank_start, vblank_end */
+ 600, 604, /* vsync_start, vsync_end */
+ 0x103, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x70
+ {
+ 800, 600, /* width, height */
+ 70, 45500, /* refresh, dot clock */
+ 1039, /* htotal */
+ 799, 1039, /* hblank_start, hblank_end */
+ 839, 919, /* hsync_start, hsync_end */
+ 624, /* vtotal */
+ 599, 624, /* vblank_start, vblank_end */
+ 600, 603, /* vsync_start, vsync_end */
+ 0x103, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x72
+ {
+ 800, 600, /* width, height */
+ 72, 50000, /* refresh, dot clock */
+ 1039, /* htotal */
+ 799, 1039, /* hblank_start, hblank_end */
+ 855, 975, /* hsync_start, hsync_end */
+ 665, /* vtotal */
+ 599, 665, /* vblank_start, vblank_end */
+ 636, 642, /* vsync_start, vsync_end */
+ 0x103, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x75
+ {
+ 800, 600, /* width, height */
+ 75, 49500, /* refresh, dot clock */
+ 1055, /* htotal */
+ 799, 1055, /* hblank_start, hblank_end */
+ 815, 895, /* hsync_start, hsync_end */
+ 624, /* vtotal */
+ 599, 624, /* vblank_start, vblank_end */
+ 600, 603, /* vsync_start, vsync_end */
+ 0x103, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x85
+ {
+ 800, 600, /* width, height */
+ 85, 56250, /* refresh, dot clock */
+ 1047, /* htotal */
+ 799, 1047, /* hblank_start, hblank_end */
+ 831, 895, /* hsync_start, hsync_end */
+ 630, /* vtotal */
+ 599, 630, /* vblank_start, vblank_end */
+ 600, 603, /* vsync_start, vsync_end */
+ 0x103, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x100
+ {
+ 800, 600, /* width, height */
+ 100, 68179, /* refresh, dot clock */
+ 1071, /* htotal */
+ 799, 1071, /* hblank_start, hblank_end */
+ 847, 935, /* hsync_start, hsync_end */
+ 635, /* vtotal */
+ 599, 635, /* vblank_start, vblank_end */
+ 600, 603, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_800x600x120
+ {
+ 800, 600, /* width, height */
+ 120, 83950, /* refresh, dot clock */
+ 1087, /* htotal */
+ 799, 1087, /* hblank_start, hblank_end */
+ 855, 943, /* hsync_start, hsync_end */
+ 642, /* vtotal */
+ 599, 642, /* vblank_start, vblank_end */
+ 600, 603, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_960x540x60
+ {
+ 960, 540, /* width, height */
+ 60, 40785, /* refresh, dot clock */
+ 1215, /* htotal */
+ 959, 1215, /* hblank_start, hblank_end */
+ 991, 1087, /* hsync_start, hsync_end */
+ 558, /* vtotal */
+ 539, 558, /* vblank_start, vblank_end */
+ 540, 543, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x60
+ {
+ 1024, 768, /* width, height */
+ 60, 65000, /* refresh, dot clock */
+ 1343, /* htotal */
+ 1023, 1343, /* hblank_start, hblank_end */
+ 1047, 1183, /* hsync_start, hsync_end */
+ 805, /* vtotal */
+ 767, 805, /* vblank_start, vblank_end */
+ 770, 776, /* vsync_start, vsync_end */
+ 0x105, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x70
+ {
+ 1024, 768, /* width, height */
+ 70, 75000, /* refresh, dot clock */
+ 1327, /* htotal */
+ 1023, 1327, /* hblank_start, hblank_end */
+ 1047, 1183, /* hsync_start, hsync_end */
+ 805, /* vtotal */
+ 767, 805, /* vblank_start, vblank_end */
+ 770, 776, /* vsync_start, vsync_end */
+ 0x105, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x75
+ {
+ 1024, 768, /* width, height */
+ 75, 78750, /* refresh, dot clock */
+ 1311, /* htotal */
+ 1023, 1311, /* hblank_start, hblank_end */
+ 1039, 1135, /* hsync_start, hsync_end */
+ 799, /* vtotal */
+ 767, 799, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x105, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x85
+ {
+ 1024, 768, /* width, height */
+ 85, 94500, /* refresh, dot clock */
+ 1375, /* htotal */
+ 1023, 1375, /* hblank_start, hblank_end */
+ 1071, 1167, /* hsync_start, hsync_end */
+ 807, /* vtotal */
+ 767, 807, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x105, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x100
+ {
+ 1024, 768, /* width, height */
+ 100, 113310, /* refresh, dot clock */
+ 1391, /* htotal */
+ 1023, 1391, /* hblank_start, hblank_end */
+ 1095, 1207, /* hsync_start, hsync_end */
+ 813, /* vtotal */
+ 767, 813, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1024x768x120
+ {
+ 1024, 768, /* width, height */
+ 120, 139050, /* refresh, dot clock */
+ 1407, /* htotal */
+ 1023, 1407, /* hblank_start, hblank_end */
+ 1103, 1215, /* hsync_start, hsync_end */
+ 822, /* vtotal */
+ 767, 822, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity H+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x60
+ {
+ 1152, 864, /* width, height */
+ 60, 81624, /* refresh, dot clock */
+ 1519, /* htotal */
+ 1151, 1519, /* hblank_start, hblank_end */
+ 1215, 1335, /* hsync_start, hsync_end */
+ 894, /* vtotal */
+ 863, 894, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x70
+ {
+ 1152, 864, /* width, height */
+ 70, 97000, /* refresh, dot clock */
+ 1535, /* htotal */
+ 1151, 1535, /* hblank_start, hblank_end */
+ 1223, 1343, /* hsync_start, hsync_end */
+ 899, /* vtotal */
+ 863, 899, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x72
+ {
+ 1152, 864, /* width, height */
+ 72, 100000, /* refresh, dot clock */
+ 1535, /* htotal */
+ 1151, 1535, /* hblank_start, hblank_end */
+ 1223, 1343, /* hsync_start, hsync_end */
+ 900, /* vtotal */
+ 863, 900, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x75
+ {
+ 1152, 864, /* width, height */
+ 75, 108000, /* refresh, dot clock */
+ 1599, /* htotal */
+ 1151, 1599, /* hblank_start, hblank_end */
+ 1215, 1343, /* hsync_start, hsync_end */
+ 899, /* vtotal */
+ 863, 899, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x85
+ {
+ 1152, 864, /* width, height */
+ 85, 120000, /* refresh, dot clock */
+ 1551, /* htotal */
+ 1151, 1551, /* hblank_start, hblank_end */
+ 1223, 1351, /* hsync_start, hsync_end */
+ 906, /* vtotal */
+ 863, 906, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1152x864x100
+ {
+ 1152, 864, /* width, height */
+ 100, 144000, /* refresh, dot clock */
+ 1567, /* htotal */
+ 1151, 1567, /* hblank_start, hblank_end */
+ 1231, 1359, /* hsync_start, hsync_end */
+ 914, /* vtotal */
+ 863, 914, /* vblank_start, vblank_end */
+ 864, 867, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x720x60
+ {
+ 1280, 720, /* width, height */
+ 60, 74481, /* refresh, dot clock */
+ 1663, /* htotal */
+ 1279, 1663, /* hblank_start, hblank_end */
+ 1335, 1471, /* hsync_start, hsync_end */
+ 745, /* vtotal */
+ 719, 745, /* vblank_start, vblank_end */
+ 720, 723, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x720x75
+ {
+ 1280, 720, /* width, height */
+ 75, 96000, /* refresh, dot clock */
+ 1695, /* htotal */
+ 1279, 1695, /* hblank_start, hblank_end */
+ 1351, 1487, /* hsync_start, hsync_end */
+ 751, /* vtotal */
+ 719, 751, /* vblank_start, vblank_end */
+ 720, 723, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x720x85
+ {
+ 1280, 720, /* width, height */
+ 85, 110000, /* refresh, dot clock */
+ 1711, /* htotal */
+ 1279, 1711, /* hblank_start, hblank_end */
+ 1359, 1495, /* hsync_start, hsync_end */
+ 755, /* vtotal */
+ 719, 755, /* vblank_start, vblank_end */
+ 720, 723, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x720x100
+ {
+ 1280, 720, /* width, height */
+ 100, 131850, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1367, 1503, /* hsync_start, hsync_end */
+ 762, /* vtotal */
+ 719, 762, /* vblank_start, vblank_end */
+ 720, 723, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x768x60
+ {
+ 1280, 768, /* width, height */
+ 60, 80136, /* refresh, dot clock */
+ 1679, /* htotal */
+ 1279, 1679, /* hblank_start, hblank_end */
+ 1343, 1479, /* hsync_start, hsync_end */
+ 794, /* vtotal */
+ 767, 794, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x768x75
+ {
+ 1280, 768, /* width, height */
+ 75, 102977, /* refresh, dot clock */
+ 1711, /* htotal */
+ 1279, 1711, /* hblank_start, hblank_end */
+ 1359, 1495, /* hsync_start, hsync_end */
+ 801, /* vtotal */
+ 767, 801, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x768x85
+ {
+ 1280, 768, /* width, height */
+ 85, 118532, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1367, 1503, /* hsync_start, hsync_end */
+ 806, /* vtotal */
+ 767, 806, /* vblank_start, vblank_end */
+ 768, 771, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x960x60
+ {
+ 1280, 960, /* width, height */
+ 60, 108000, /* refresh, dot clock */
+ 1799, /* htotal */
+ 1279, 1799, /* hblank_start, hblank_end */
+ 1375, 1487, /* hsync_start, hsync_end */
+ 999, /* vtotal */
+ 959, 999, /* vblank_start, vblank_end */
+ 960, 963, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x960x75
+ {
+ 1280, 960, /* width, height */
+ 75, 129859, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1367, 1503, /* hsync_start, hsync_end */
+ 1001, /* vtotal */
+ 959, 1001, /* vblank_start, vblank_end */
+ 960, 963, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x960x85
+ {
+ 1280, 960, /* width, height */
+ 85, 148500, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1343, 1503, /* hsync_start, hsync_end */
+ 1010, /* vtotal */
+ 959, 1010, /* vblank_start, vblank_end */
+ 960, 963, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x60
+ {
+ 1280, 1024, /* width, height */
+ 60, 108000, /* refresh, dot clock */
+ 1687, /* htotal */
+ 1279, 1687, /* hblank_start, hblank_end */
+ 1327, 1439, /* hsync_start, hsync_end */
+ 1065, /* vtotal */
+ 1023, 1065, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x107, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x70
+ {
+ 1280, 1024, /* width, height */
+ 70, 129000, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1367, 1503, /* hsync_start, hsync_end */
+ 1065, /* vtotal */
+ 1023, 1065, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x107, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x72
+ {
+ 1280, 1024, /* width, height */
+ 72, 133000, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1367, 1503, /* hsync_start, hsync_end */
+ 1066, /* vtotal */
+ 1023, 1066, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x107, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x75
+ {
+ 1280, 1024, /* width, height */
+ 75, 135000, /* refresh, dot clock */
+ 1687, /* htotal */
+ 1279, 1687, /* hblank_start, hblank_end */
+ 1295, 1439, /* hsync_start, hsync_end */
+ 1065, /* vtotal */
+ 1023, 1065, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x107, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x85
+ {
+ 1280, 1024, /* width, height */
+ 85, 157500, /* refresh, dot clock */
+ 1727, /* htotal */
+ 1279, 1727, /* hblank_start, hblank_end */
+ 1343, 1503, /* hsync_start, hsync_end */
+ 1071, /* vtotal */
+ 1023, 1071, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x107, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x100
+ {
+ 1280, 1024, /* width, height */
+ 100, 190960, /* refresh, dot clock */
+ 1759, /* htotal */
+ 1279, 1759, /* hblank_start, hblank_end */
+ 1375, 1519, /* hsync_start, hsync_end */
+ 1084, /* vtotal */
+ 1023, 1084, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1280x1024x120
+ {
+ 1280, 1024, /* width, height */
+ 120, 233790, /* refresh, dot clock */
+ 1775, /* htotal */
+ 1279, 1775, /* hblank_start, hblank_end */
+ 1383, 1527, /* hsync_start, hsync_end */
+ 1096, /* vtotal */
+ 1023, 1096, /* vblank_start, vblank_end */
+ 1024, 1027, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1366x768x60
+ {
+ 1366, 768, /* width, height */
+ 60, 74057, /* refresh, dot clock */
+ 1663, /* htotal */
+ 1365, 1663, /* hblank_start, hblank_end */
+ 1429, 1557, /* hsync_start, hsync_end */
+ 775, /* vtotal */
+ 767, 775, /* vblank_start, vblank_end */
+ 768, 769, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH | /* polarity V+ */
+ IGD_HSYNC_HIGH, /* polarity H+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+
+#ifdef CONFIG_MODE_1400x1050x60
+ {
+ 1400, 1050, /* width, height */
+ 60, 122000, /* refresh, dot clock */
+ 1879, /* htotal */
+ 1399, 1879, /* hblank_start, hblank_end */
+ 1487, 1639, /* hsync_start, hsync_end */
+ 1086, /* vtotal */
+ 1049, 1086, /* vblank_start, vblank_end */
+ 1050, 1053, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1400x1050x75
+ {
+ 1400, 1050, /* width, height */
+ 75, 155851, /* refresh, dot clock */
+ 1895, /* htotal */
+ 1399, 1895, /* hblank_start, hblank_end */
+ 1495, 1647, /* hsync_start, hsync_end */
+ 1095, /* vtotal */
+ 1049, 1095, /* vblank_start, vblank_end */
+ 1050, 1053, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1400x1050x85
+ {
+ 1400, 1050, /* width, height */
+ 85, 179260, /* refresh, dot clock */
+ 1911, /* htotal */
+ 1399, 1911, /* hblank_start, hblank_end */
+ 1503, 1655, /* hsync_start, hsync_end */
+ 1102, /* vtotal */
+ 1049, 1102, /* vblank_start, vblank_end */
+ 1050, 1053, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x900x60
+ {
+ 1600, 900, /* width, height */
+ 60, 119000, /* refresh, dot clock */
+ 2127, /* htotal */
+ 1599, 2127, /* hblank_start, hblank_end */
+ 1695, 1863, /* hsync_start, hsync_end */
+ 931, /* vtotal */
+ 899, 931, /* vblank_start, vblank_end */
+ 900, 903, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x900x75
+ {
+ 1600, 900, /* width, height */
+ 75, 152000, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1703, 1879, /* hsync_start, hsync_end */
+ 939, /* vtotal */
+ 899, 939, /* vblank_start, vblank_end */
+ 900, 903, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x900x85
+ {
+ 1600, 900, /* width, height */
+ 85, 175000, /* refresh, dot clock */
+ 2175, /* htotal */
+ 1599, 2175, /* hblank_start, hblank_end */
+ 1711, 1887, /* hsync_start, hsync_end */
+ 944, /* vtotal */
+ 899, 944, /* vblank_start, vblank_end */
+ 900, 903, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x900x100
+ {
+ 1600, 900, /* width, height */
+ 100, 208900, /* refresh, dot clock */
+ 2191, /* htotal */
+ 1599, 2191, /* hblank_start, hblank_end */
+ 1719, 1895, /* hsync_start, hsync_end */
+ 952, /* vtotal */
+ 899, 952, /* vblank_start, vblank_end */
+ 900, 903, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x900x120
+ {
+ 1600, 900, /* width, height */
+ 120, 255686, /* refresh, dot clock */
+ 2207, /* htotal */
+ 1599, 2207, /* hblank_start, hblank_end */
+ 1727, 1903, /* hsync_start, hsync_end */
+ 964, /* vtotal */
+ 899, 964, /* vblank_start, vblank_end */
+ 900, 903, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x60
+ {
+ 1600, 1200, /* width, height */
+ 60, 162000, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1663, 1855, /* hsync_start, hsync_end */
+ 1249, /* vtotal */
+ 1199, 1249, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x65
+ {
+ 1600, 1200, /* width, height */
+ 65, 175500, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1663, 1855, /* hsync_start, hsync_end */
+ 1249, /* vtotal */
+ 1199, 1249, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x70
+ {
+ 1600, 1200, /* width, height */
+ 70, 189000, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1663, 1855, /* hsync_start, hsync_end */
+ 1249, /* vtotal */
+ 1199, 1249, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x72
+ {
+ 1600, 1200, /* width, height */
+ 72, 195000, /* refresh, dot clock */
+ 2175, /* htotal */
+ 1599, 2175, /* hblank_start, hblank_end */
+ 1711, 1887, /* hsync_start, hsync_end */
+ 1250, /* vtotal */
+ 1199, 1250, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x75
+ {
+ 1600, 1200, /* width, height */
+ 75, 202500, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1663, 1855, /* hsync_start, hsync_end */
+ 1249, /* vtotal */
+ 1199, 1249, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x85
+ {
+ 1600, 1200, /* width, height */
+ 85, 229500, /* refresh, dot clock */
+ 2159, /* htotal */
+ 1599, 2159, /* hblank_start, hblank_end */
+ 1663, 1855, /* hsync_start, hsync_end */
+ 1249, /* vtotal */
+ 1199, 1249, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_HSYNC_HIGH| /* polarity H+ */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x100
+ {
+ 1600, 1200, /* width, height */
+ 100, 280640, /* refresh, dot clock */
+ 2207, /* htotal */
+ 1599, 2207, /* hblank_start, hblank_end */
+ 1727, 1903, /* hsync_start, hsync_end */
+ 1270, /* vtotal */
+ 1199, 1270, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1600x1200x120
+ {
+ 1600, 1200, /* width, height */
+ 120, 343210, /* refresh, dot clock */
+ 2223, /* htotal */
+ 1599, 2223, /* hblank_start, hblank_end */
+ 1735, 1911, /* hsync_start, hsync_end */
+ 1285, /* vtotal */
+ 1199, 1285, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1856x1392x60
+ {
+ 1856, 1392, /* width, height */
+ 60, 218250, /* refresh, dot clock */
+ 2527, /* htotal */
+ 1855, 2527, /* hblank_start, hblank_end */
+ 1951, 2175, /* hsync_start, hsync_end */
+ 1438, /* vtotal */
+ 1391, 1438, /* vblank_start, vblank_end */
+ 1392, 1395, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1856x1392x75
+ {
+ 1856, 1392, /* width, height */
+ 75, 288000, /* refresh, dot clock */
+ 2559, /* htotal */
+ 1855, 2559, /* hblank_start, hblank_end */
+ 1983, 2207, /* hsync_start, hsync_end */
+ 1499, /* vtotal */
+ 1391, 1499, /* vblank_start, vblank_end */
+ 1392, 1395, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1080x50
+ {
+ 1920, 1080, /* width, height */
+ 50, 141446, /* refresh, dot clock */
+ 2543, /* htotal */
+ 1919, 2543, /* hblank_start, hblank_end */
+ 2031, 2231, /* hsync_start, hsync_end */
+ 1111, /* vtotal */
+ 1079, 1111, /* vblank_start, vblank_end */
+ 1080, 1083, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1080x60
+ {
+ 1920, 1080, /* width, height */
+ 60, 172800, /* refresh, dot clock */
+ 2575, /* htotal */
+ 1919, 2575, /* hblank_start, hblank_end */
+ 2039, 2247, /* hsync_start, hsync_end */
+ 1117, /* vtotal */
+ 1079, 1117, /* vblank_start, vblank_end */
+ 1080, 1083, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1080x75
+ {
+ 1920, 1080, /* width, height */
+ 75, 220640, /* refresh, dot clock */
+ 2607, /* htotal */
+ 1919, 2607, /* hblank_start, hblank_end */
+ 2055, 2263, /* hsync_start, hsync_end */
+ 1127, /* vtotal */
+ 1079, 1127, /* vblank_start, vblank_end */
+ 1080, 1083, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1080x85
+ {
+ 1920, 1080, /* width, height */
+ 85, 252930, /* refresh, dot clock */
+ 2623, /* htotal */
+ 1919, 2623, /* hblank_start, hblank_end */
+ 2063, 2271, /* hsync_start, hsync_end */
+ 1133, /* vtotal */
+ 1079, 1133, /* vblank_start, vblank_end */
+ 1080, 1083, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1080x100
+ {
+ 1920, 1080, /* width, height */
+ 100, 302020, /* refresh, dot clock */
+ 2639, /* htotal */
+ 1919, 2639, /* hblank_start, hblank_end */
+ 2071, 2279, /* hsync_start, hsync_end */
+ 1143, /* vtotal */
+ 1079, 1143, /* vblank_start, vblank_end */
+ 1080, 1083, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1200x60
+ {
+ 1920, 1200, /* width, height */
+ 60, 193156, /* refresh, dot clock */
+ 2591, /* htotal */
+ 1919, 2591, /* hblank_start, hblank_end */
+ 2047, 2255, /* hsync_start, hsync_end */
+ 1241, /* vtotal */
+ 1199, 1241, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1200x75
+ {
+ 1920, 1200, /* width, height */
+ 75, 246590, /* refresh, dot clock */
+ 2623, /* htotal */
+ 1919, 2623, /* hblank_start, hblank_end */
+ 2063, 2271, /* hsync_start, hsync_end */
+ 1252, /* vtotal */
+ 1199, 1252, /* vblank_start, vblank_end */
+ 1200, 1203, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1440x60
+ {
+ 1920, 1440, /* width, height */
+ 60, 234000, /* refresh, dot clock */
+ 2599, /* htotal */
+ 1919, 2599, /* hblank_start, hblank_end */
+ 2047, 2255, /* hsync_start, hsync_end */
+ 1499, /* vtotal */
+ 1439, 1499, /* vblank_start, vblank_end */
+ 1440, 1443, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1440x75
+ {
+ 1920, 1440, /* width, height */
+ 75, 297000, /* refresh, dot clock */
+ 2639, /* htotal */
+ 1919, 2639, /* hblank_start, hblank_end */
+ 2063, 2287, /* hsync_start, hsync_end */
+ 1499, /* vtotal */
+ 1439, 1499, /* vblank_start, vblank_end */
+ 1440, 1443, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_1920x1440x85
+ {
+ 1920, 1440, /* width, height */
+ 85, 341350, /* refresh, dot clock */
+ 2655, /* htotal */
+ 1919, 2655, /* hblank_start, hblank_end */
+ 2071, 2287, /* hsync_start, hsync_end */
+ 1511, /* vtotal */
+ 1439, 1511, /* vblank_start, vblank_end */
+ 1440, 1443, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_2048x1536x60
+ {
+ 2048, 1536, /* width, height */
+ 60, 266950, /* refresh, dot clock */
+ 2799, /* htotal */
+ 2047, 2799, /* hblank_start, hblank_end */
+ 2199, 2423, /* hsync_start, hsync_end */
+ 1588, /* vtotal */
+ 1535, 1588, /* vblank_start, vblank_end */
+ 1536, 1539, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_MODE_2048x1536x75
+ {
+ 2048, 1536, /* width, height */
+ 75, 340480, /* refresh, dot clock */
+ 2831, /* htotal */
+ 2047, 2831, /* hblank_start, hblank_end */
+ 2215, 2439, /* hsync_start, hsync_end */
+ 1602, /* vtotal */
+ 1535, 1602, /* vblank_start, vblank_end */
+ 1536, 1539, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE| /* mode info flags */
+ IGD_VSYNC_HIGH, /* polarity V+ */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+ PD_TIMING_TABLE_END
+};
+
+int crt_timing_table_size = sizeof(crt_timing_table);
+
+/*---------------------------------------------------------------------------
+ * Timing tables for VGA modes
+ *---------------------------------------------------------------------------
+ */
+igd_timing_info_t vga_timing_table[] =
+{
+ { /* VGA Mode 0 */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x00, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_LINE_DOUBLE |
+ IGD_PIXEL_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 1 */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x01, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_LINE_DOUBLE |
+ IGD_PIXEL_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 2 */
+ 640, 200, /* width, height */
+ 70, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 679, 775, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x02, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 3 */
+ 640, 200, /* width, height */
+ 70, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 679, 775, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x03, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 4 */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x04, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 5 */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x05, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 6 */
+ 640, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 784, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x06, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 7 */
+ 720, 350, /* width, height */
+ 60, 28322, /* refresh, dot clock */
+ 899, /* htotal */
+ 719, 881, /* hblank_start, hblank_end */
+ 764, 872, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x07, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode d */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x0d, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_PIXEL_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode e */
+ 640, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x0e, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode f */
+ 640, 350, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x11, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 10 */
+ 640, 350, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x12, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 0* */
+ 320, 350, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x13, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_PIXEL_DOUBLE |
+ IGD_MODE_TEXT |
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 1* */
+ 320, 350, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 399, /* htotal */
+ 319, 383, /* hblank_start, hblank_end */
+ 343, 383, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x14, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_PIXEL_DOUBLE |
+ IGD_MODE_TEXT |
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 2* */
+ 640, 350, /* width, height */
+ 70, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 679, 775, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x15, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 3* */
+ 640, 350, /* width, height */
+ 70, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 679, 775, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 354, 441, /* vblank_start, vblank_end */
+ 386, 388, /* vsync_start, vsync_end */
+ 0x16, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_HSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 0+,1+ */
+ 360, 400, /* width, height */
+ 60, 28322, /* refresh, dot clock */
+ 449, /* htotal */
+ 359, 431, /* hblank_start, hblank_end */
+ 386, 431, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x17, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_PIXEL_DOUBLE |
+ IGD_MODE_TEXT |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 2+,3+ */
+ 720, 400, /* width, height */
+ 70, 28322, /* refresh, dot clock */
+ 899, /* htotal */
+ 719, 881, /* hblank_start, hblank_end */
+ 764, 872, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x18, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 7+ */
+ 720, 400, /* width, height */
+ 60, 28322, /* refresh, dot clock */
+ 899, /* htotal */
+ 719, 881, /* hblank_start, hblank_end */
+ 764, 872, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x19, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_TEXT |
+ IGD_VSYNC_HIGH |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 11 */
+ 640, 480, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 524, /* vtotal */
+ 486, 515, /* vblank_start, vblank_end */
+ 489, 491, /* vsync_start, vsync_end */
+ 0x1A, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 12 */
+ 640, 480, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 524, /* vtotal */
+ 486, 515, /* vblank_start, vblank_end */
+ 489, 491, /* vsync_start, vsync_end */
+ 0x1B, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+ { /* VGA Mode 13 */
+ 320, 200, /* width, height */
+ 60, 25175, /* refresh, dot clock */
+ 799, /* htotal */
+ 639, 783, /* hblank_start, hblank_end */
+ 671, 767, /* hsync_start, hsync_end */
+ 448, /* vtotal */
+ 405, 440, /* vblank_start, vblank_end */
+ 411, 413, /* vsync_start, vsync_end */
+ 0x1C, /* mode number */
+ IGD_MODE_VESA | /* VESA/VGA mode */
+ IGD_LINE_DOUBLE |
+ IGD_PIXEL_DOUBLE |
+ IGD_MODE_SUPPORTED |
+ IGD_SCAN_PROGRESSIVE, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+
+ PD_TIMING_TABLE_END
+};
+
+/* CEA standard timings: Get them from CEA-861. This is following DPG.
+ We will replace the mode number to CEA*/
+igd_timing_info_t cea_timing_table[] =
+{
+#ifdef CONFIG_CEA_MODE_640x480px60
+ {
+ 640, 480, /* width, height */
+ 60, 25200, /* refresh, dot clock */
+ 800, /* htotal */
+ 640, 799, /* hblank_start, hblank_end */
+ 656, 751, /* hsync_start, hsync_end */
+ 525, /* vtotal */
+ 480, 524, /* vblank_start, vblank_end */
+ 490, 491, /* vsync_start, vsync_end */
+ 1, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA, /* mode info flags */
+ 0, 0, /* x, y offset */
+ 0, /* device dependant */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_720x480px60
+ {
+ 720, 480, /* width, height */
+ 60, 27000, /* refresh, dot clock */
+ 858, /* htotal */
+ 720, 857, /* hblank_start, hblank_end */
+ 736, 797, /* hsync_start, hsync_end */
+ 525, /* vtotal */
+ 480, 524, /* vblank_start, vblank_end */
+ 489, 494, /* vsync_start, vsync_end */
+ 2, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_720x480p_ax60
+ {
+ 720, 480, /* width, height */
+ 60, 27000, /* refresh, dot clock */
+ 858, /* htotal */
+ 720, 857, /* hblank_start, hblank_end */
+ 736, 797, /* hsync_start, hsync_end */
+ 525, /* vtotal */
+ 480, 524, /* vblank_start, vblank_end */
+ 489, 494, /* vsync_start, vsync_end */
+ 3, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA | /* mode info flags */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_720x576px50
+ {
+ 720, 576, /* width, height */
+ 50, 27000, /* refresh, dot clock */
+ 864, /* htotal */
+ 720, 863, /* hblank_start, hblank_end */
+ 732, 795, /* hsync_start, hsync_end */
+ 625, /* vtotal */
+ 575, 624, /* vblank_start, vblank_end */
+ 581, 585, /* vsync_start, vsync_end */
+ 17, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_720x576p_ax50
+ {
+ 720, 576, /* width, height */
+ 50, 27000, /* refresh, dot clock */
+ 864, /* htotal */
+ 720, 863, /* hblank_start, hblank_end */
+ 732, 795, /* hsync_start, hsync_end */
+ 625, /* vtotal */
+ 575, 624, /* vblank_start, vblank_end */
+ 581, 585, /* vsync_start, vsync_end */
+ 18, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA | /* mode info flags */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_1280x720p_ax50
+ {
+ 1280, 720, /* width, height */
+ 50, 74250, /* refresh, dot clock */
+ 1980, /* htotal */
+ 1280, 1979, /* hblank_start, hblank_end */
+ 1720, 1759, /* hsync_start, hsync_end */
+ 750, /* vtotal */
+ 720, 749, /* vblank_start, vblank_end */
+ 725, 729, /* vsync_start, vsync_end */
+ 19, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE |
+ PD_MODE_CEA | /* mode info flags */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_1280x720p_ax60
+ {
+ 1280, 720, /* width, height */
+ 60, 74250, /* refresh, dot clock */
+ 1650, /* htotal */
+ 1280, 1649, /* hblank_start, hblank_end */
+ 1390, 1429, /* hsync_start, hsync_end */
+ 750, /* vtotal */
+ 720, 749, /* vblank_start, vblank_end */
+ 725, 729, /* vsync_start, vsync_end */
+ 4, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE | /* mode info flags */
+ IGD_VSYNC_HIGH |
+ PD_MODE_CEA | /* polarity V+ */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+/* KIV. Not proper timimgs, rerefer to DPG updates */
+#ifdef CONFIG_CEA_MODE_1920x1080p_ax50
+ {
+ 1920, 1080, /* width, height */
+ 50, 148500, /* refresh, dot clock */
+ 2640, /* htotal */
+ 1920, 2639, /* hblank_start, hblank_end */
+ 2448, 2491, /* hsync_start, hsync_end */
+ 1125, /* vtotal */
+ 1080, 1124, /* vblank_start, vblank_end */
+ 1084, 1088, /* vsync_start, vsync_end */
+ 31, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE | /* mode info flags */
+ IGD_VSYNC_HIGH |
+ PD_MODE_CEA | /* polarity V+ */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080p_ax60
+ {
+ 1920, 1080, /* width, height */
+ 60, 148500, /* refresh, dot clock */
+ 2200, /* htotal */
+ 1920, 2199, /* hblank_start, hblank_end */
+ 2008, 2051, /* hsync_start, hsync_end */
+ 1125, /* vtotal */
+ 1080, 1124, /* vblank_start, vblank_end */
+ 1084, 1088, /* vsync_start, vsync_end */
+ 16, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_PROGRESSIVE | /* mode info flags */
+ IGD_VSYNC_HIGH |
+ PD_MODE_CEA | /* polarity V+ */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080i_ax50
+ {
+ 1920, 1080, /* width, height */
+ 25, 74250, /* refresh, dot clock */
+ 2640, /* htotal */
+ 1920, 2639, /* hblank_start, hblank_end */
+ 2448, 2491, /* hsync_start, hsync_end */
+ 1124, /* vtotal */
+ 1080, 1123, /* vblank_start, vblank_end */
+ 1084, 1093, /* vsync_start, vsync_end */
+ 20, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_INTERLACE | /* mode info flags */
+ IGD_VSYNC_HIGH |
+ PD_MODE_CEA | /* polarity V+ */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080i_ax60
+ {
+ 1920, 1080, /* width, height */
+ 30, 74250, /* refresh, dot clock */
+ 2200, /* htotal */
+ 1920, 2199, /* hblank_start, hblank_end */
+ 2008, 2051, /* hsync_start, hsync_end */
+ 1124, /* vtotal */
+ 1080, 1123, /* vblank_start, vblank_end */
+ 1084, 1093, /* vsync_start, vsync_end */
+ 5, /* mode number */
+ PD_MODE_SUPPORTED | /* enable the mode */
+ IGD_SCAN_INTERLACE | /* mode info flags */
+ IGD_VSYNC_HIGH |
+ PD_MODE_CEA | /* polarity V+ */
+ PD_ASPECT_16_9, /* Aspect ratio 16:9 */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extension pointer */
+ 0, /* device dependant */
+ 0 /* device dependant */
+ },
+#endif
+ PD_TIMING_TABLE_END
+};
+
+#ifndef CONFIG_MICRO
+int cea_timing_table_size = sizeof(cea_timing_table);
+
+/* CEA timings for parsing purpose */
+type_std_t cea_std_lookup[] =
+{
+ { 640, 400, 60, 0 },
+ { 720, 480, 60, 0 },
+ { 720, 480, 60, PD_ASPECT_16_9 },
+ { 1280, 720, 60, PD_ASPECT_16_9 },
+ { 1920, 1080, 60, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 480, 60, PD_SCAN_INTERLACE },
+ { 720, 480, 60, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 240, 60, 0 },
+
+ { 720, 240, 60, PD_ASPECT_16_9 },
+ { 2880, 480, 60, PD_SCAN_INTERLACE },
+ { 2880, 480, 60, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 2880, 240, 60, 0 },
+ { 2880, 240, 60, PD_ASPECT_16_9 },
+ { 1440, 480, 60, 0 },
+ { 1440, 480, 60, PD_ASPECT_16_9 },
+ { 1920, 1080, 60, PD_ASPECT_16_9 },
+
+ { 720, 576, 50, 0 },
+ { 720, 576, 50, PD_ASPECT_16_9 },
+ { 1280, 720, 50, PD_ASPECT_16_9 },
+ { 1920, 1080, 50, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 576, 50, PD_SCAN_INTERLACE },
+ { 720, 576, 50, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 288, 50, 0 },
+ { 720, 288, 50, PD_ASPECT_16_9 },
+
+ { 2880, 576, 50, PD_SCAN_INTERLACE },
+ { 2880, 576, 50, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 2880, 288, 50, 0 },
+ { 2880, 288, 50, PD_ASPECT_16_9 },
+ { 1440, 576, 50, 0 },
+ { 1440, 576, 50, PD_ASPECT_16_9 },
+ { 1920, 1080, 50, PD_ASPECT_16_9 },
+ { 1920, 1080, 24, PD_ASPECT_16_9 },
+
+ { 1920, 1080, 25, PD_ASPECT_16_9 },
+ { 1920, 1080, 30, PD_ASPECT_16_9 },
+ { 2880, 480, 60, 0 },
+ { 2880, 480, 60, PD_ASPECT_16_9 },
+ { 2880, 576, 50, 0 },
+ { 2880, 576, 50, PD_ASPECT_16_9 },
+ { 1920, 1080, 50, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 1920, 1080, 100, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+
+ { 1280, 720, 100, PD_ASPECT_16_9 },
+ { 720, 576, 100, 0 },
+ { 720, 576, 100, PD_ASPECT_16_9 },
+ { 720, 576, 100, PD_SCAN_INTERLACE },
+ { 720, 576, 100, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 1920, 1080, 120, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 1280, 720, 120, PD_ASPECT_16_9 },
+ { 720, 480, 120, 0 },
+
+ { 720, 480, 120, PD_ASPECT_16_9 },
+ { 720, 480, 120, PD_SCAN_INTERLACE },
+ { 720, 480, 120, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 576, 200, 0 },
+ { 720, 576, 200, PD_ASPECT_16_9 },
+ { 720, 576, 200, PD_SCAN_INTERLACE },
+ { 720, 576, 200, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 720, 480, 240, 0 },
+
+ { 720, 480, 240, PD_ASPECT_16_9 },
+ { 720, 480, 240, PD_SCAN_INTERLACE },
+ { 720, 480, 240, PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+ { 1280, 720, 24, PD_ASPECT_16_9 },
+ { 1280, 720, 25, PD_ASPECT_16_9 },
+ { 1280, 720, 30, PD_ASPECT_16_9 },
+};
+
+int cea_std_lookup_size = sizeof(cea_std_lookup)/sizeof(type_std_t);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
new file mode 100644
index 0000000..ba70fc8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
@@ -0,0 +1,215 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_init_all.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file controls the port drivers that are initialized as part of
+ * the HAL init. These must be statically linked with the HAL.
+ * NOTE: This file is visible to customers. It is used in source form as
+ * part of the vBIOS build procedure.
+ *-----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Enable Analog (CRT) port driver */
+#ifdef CONFIG_LINK_PD_ANALOG
+extern int analog_init(void *handle);
+#define ANALOG_INIT(handle) analog_init(handle)
+#else
+#define ANALOG_INIT(handle) 0
+#endif
+
+/* Enable Silicon Image 154/164 FP port driver */
+#ifdef CONFIG_LINK_PD_SII164
+extern int sii164_init(void *handle);
+#define SII164_INIT(handle) sii164_init(handle)
+#else
+#define SII164_INIT(handle) 0
+#endif
+
+/* Enable Texas Instruments 410 FP port driver */
+#ifdef CONFIG_LINK_PD_TI410
+extern int ti410_init(void *handle);
+#define TI410_INIT(handle) ti410_init(handle)
+#else
+#define TI410_INIT(handle) 0
+#endif
+
+/* Enable Chrontel 7009 TMDS & TVOut port driver */
+#ifdef CONFIG_LINK_PD_CH7009
+extern int ch7009_init(void *handle);
+#define CH7009_INIT(handle) ch7009_init(handle)
+#else
+#define CH7009_INIT(handle) 0
+#endif
+
+/* Enable National Semiconductor 2501 LVDS port driver */
+#ifdef CONFIG_LINK_PD_NS2501
+extern int ns2501_init(void *handle);
+#define NS2501_INIT(handle) ns2501_init(handle)
+#else
+#define NS2501_INIT(handle) 0
+#endif
+
+/* Enable TL955 port driver */
+#ifdef CONFIG_LINK_PD_TL955
+extern int tl955_init(void *handle);
+#define TL955_INIT(handle) tl955_init(handle)
+#else
+#define TL955_INIT(handle) 0
+#endif
+
+/* Enable Th164 port driver */
+#ifdef CONFIG_LINK_PD_TH164
+extern int th164_init(void *handle);
+#define TH164_INIT(handle) th164_init(handle)
+#else
+#define TH164_INIT(handle) 0
+#endif
+
+/* Enable FS454 port driver */
+#ifdef CONFIG_LINK_PD_FS454
+extern int fs454_init(void *handle);
+#define FS454_INIT(handle) fs454_init(handle)
+#else
+#define FS454_INIT(handle) 0
+#endif
+
+/* Enable NS387/389 port driver */
+#ifdef CONFIG_LINK_PD_NS387
+extern int ns387_init(void *handle);
+#define NS387_INIT(handle) ns387_init(handle)
+#else
+#define NS387_INIT(handle) 0
+#endif
+
+/* Enable connexant port driver */
+#ifdef CONFIG_LINK_PD_CX873
+extern int cx873_init(void *handle);
+#define CX873_INIT(handle) cx873_init(handle)
+#else
+#define CX873_INIT(handle) 0
+#endif
+
+/* Enable Internal LVDS port driver */
+#ifdef CONFIG_LINK_PD_LVDS
+extern int lvds_init(void *handle);
+#define LVDS_INIT(handle) lvds_init(handle)
+#else
+#define LVDS_INIT(handle) 0
+#endif
+
+/* Enable SDVO port driver */
+#ifdef CONFIG_LINK_PD_SDVO
+extern int sdvo_init(void *handle);
+#define SDVO_INIT(handle) sdvo_init(handle)
+#else
+#define SDVO_INIT(handle) 0
+#endif
+
+/* Enable Integrated TV port driver for NAPA */
+#ifdef CONFIG_LINK_PD_TV
+extern int tv_init(void *handle);
+#define TV_INIT(handle) tv_init(handle)
+#else
+#define TV_INIT(handle) 0
+#endif
+
+/* Enable FS460 port driver */
+#ifdef CONFIG_LINK_PD_FS460
+extern int fs460_init(void *handle);
+#define FS460_INIT(handle) fs460_init(handle)
+#else
+#define FS460_INIT(handle) 0
+#endif
+
+/* Enable FS450 port driver */
+#ifdef CONFIG_LINK_PD_FS450
+extern int fs450_init(void *handle);
+#define FS450_INIT(handle) fs450_init(handle)
+#else
+#define FS450_INIT(handle) 0
+#endif
+
+/* Enable Chrontel 7017 LVDS & TVOut port driver */
+#ifdef CONFIG_LINK_PD_CH7017
+extern int ch7017_init(void *handle);
+#define CH7017_INIT(handle) ch7017_init(handle)
+#else
+#define CH7017_INIT(handle) 0
+#endif
+
+/* Enable internal HDMI port driver */
+#ifdef CONFIG_LINK_PD_HDMI
+extern int hdmi_init(void *handle);
+#define HDMI_INIT(handle) hdmi_init(handle)
+#else
+#define HDMI_INIT(handle) 0
+#endif
+
+/* Enable Chrontel CH7036 port driver */
+#ifdef CONFIG_LINK_PD_CH7036
+extern int ch7036_init(void *handle);
+#define CH7036_INIT(handle) ch7036_init(handle)
+#else
+#define CH7036_INIT(handle) 0
+#endif
+
+
+/*!
+ *
+ * @param handle
+ *
+ * @return 0
+ */
+int pi_init_all(void *handle)
+{
+ int ret;
+
+ ret = ANALOG_INIT(handle);
+ ret = CH7009_INIT(handle);
+ ret = SII164_INIT(handle);
+ ret = NS2501_INIT(handle);
+ ret = TH164_INIT(handle);
+ ret = NS387_INIT(handle);
+ ret = FS454_INIT(handle);
+ ret = CH7017_INIT(handle);
+ ret = SDVO_INIT(handle);
+ ret = TI410_INIT(handle);
+ ret = TV_INIT(handle);
+ ret = HDMI_INIT(handle);
+ ret = CH7036_INIT(handle);
+ ret = LVDS_INIT(handle); /*LVDS need to be initiate only after CH7036.*/
+ /* ret = PD000_INIT(handle); */
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
new file mode 100755
index 0000000..3f8aeab2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
@@ -0,0 +1,1921 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pi.c
+ * $Revision: 1.25 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains all the necessary functions for port interface
+ * module. This module abstracts all hardware port interfaces and
+ * manages them.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <config.h>
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_pwr.h>
+
+#include <io.h>
+#include <pci.h>
+#include <sched.h>
+#include <memory.h>
+
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+#include <dsp.h>
+#include <debug.h>
+#include <pi.h>
+#include <pd.h>
+#include <pd_init.h>
+#include <intelpci.h>
+#include <dispatch.h>
+#include <mode_access.h>
+#include <edid.h>
+#include <displayid.h>
+#include <emgd_drv.h>
+
+#include "i2c_dispatch.h"
+#include <igd_vga.h>
+#include <context.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+typedef struct _pi_context {
+ igd_context_t *igd_context;
+ i2c_dispatch_t *i2c_dispatch;
+ unsigned long num_pi_drivers;
+} pi_context_t;
+
+/* Function to filter the modes using EDID or DisplayID*/
+int get_firmware_timings(igd_display_port_t *port,
+ unsigned char *firmware_data, pd_timing_t *timing_table);
+
+int pi_pd_init(igd_display_port_t *port, unsigned long port_feature,
+ unsigned long second_port_feature, int drm_load_time);
+#ifndef CONFIG_MICRO
+unsigned long get_magic_cookie(pd_driver_t *pd_driver);
+#endif
+void assign_dynamic_numbers(igd_timing_info_t *timing_table);
+int update_attrs(igd_display_port_t *port);
+pd_timing_t *get_user_timings(igd_param_dtd_list_t *in_list);
+
+
+extern int pi_init_all(void *handle);
+
+extern emgd_drm_config_t config_drm;
+extern i2c_dispatch_t i2c_dispatch_plb;
+extern i2c_dispatch_t i2c_dispatch_tnc;
+
+int null_func( void )
+{
+ return -IGD_ERROR_NODEV;
+}
+/* Not currently used
+static i2c_dispatch_t i2c_dispatch_null = {
+ (void *)null_func,
+ (void *)null_func,
+ (void *)null_func,
+ (void *)null_func
+}; */
+
+
+static dispatch_table_t i2c_dispatch_list[] = {
+
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &i2c_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &i2c_dispatch_tnc},
+#endif
+
+ {0, NULL}
+};
+
+static unsigned char firmware_data[256];
+
+static pi_context_t pi_context[1];
+
+/*----------------------------------------------------------------------
+ * FUNCTION DEFINITIONS
+ *----------------------------------------------------------------------*/
+#ifndef CONFIG_MICRO
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void pi_shutdown(igd_context_t *context)
+{
+ igd_display_port_t *port;
+
+ EMGD_TRACE_ENTER;
+
+ if (pi_context->igd_context == NULL) {
+ return;
+ }
+
+ /* Close the port drivers */
+ port = NULL;
+ while ((port = context->mod_dispatch.dsp_get_next_port(context, port, 0)) != NULL) {
+ if (port->pd_driver) {
+ port->pd_driver->pd_close(port->pd_context);
+ port->pd_driver = NULL;
+ /* pd_context is freed by port driver */
+ port->pd_context = NULL;
+ /* timing_table is freed by port driver */
+ port->timing_table = NULL;
+ port->num_timing = 0;
+ if (port->fp_info) {
+ OS_FREE(port->fp_info);
+ port->fp_info = NULL;
+ }
+ if (port->callback) {
+ OS_FREE(port->callback);
+ port->callback = NULL;
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+int pi_full_init(igd_context_t *context)
+{
+ /* Optional Inter-module interfaces */
+ context->mod_dispatch.pi_shutdown = pi_shutdown;
+ return 0;
+}
+
+#endif
+
+/*!
+ *
+ * @param context
+ * @param config_info
+ *
+ * @return 0
+ */
+static int pi_get_config_info(igd_context_t *context,
+ igd_config_info_t *config_info)
+{
+
+ igd_display_port_t *port = NULL;
+ igd_param_t *init_params = NULL;
+ igd_display_params_t *display_params = NULL;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_ASSERT(context, "Null context", -IGD_ERROR_INVAL);
+ EMGD_ASSERT(config_info, "Null config_info", -IGD_ERROR_INVAL);
+
+ config_info->num_act_dsp_ports = pi_context->num_pi_drivers;
+
+ init_params = pi_context->igd_context->mod_dispatch.init_params;
+
+ while ((port = pi_context->igd_context->mod_dispatch.
+ dsp_get_next_port(pi_context->igd_context, port, 0)) != NULL) {
+
+ /* Get the display params to check if the user enabled EDID */
+ for (i = 0; i < IGD_MAX_PORTS; i++) {
+ if (init_params->display_params[i].port_number == port->port_number) {
+ display_params = &init_params->display_params[i];
+ break;
+ }
+ }
+
+ /* If DID rotation info is available, pass it to user-space through the
+ * config_info struct */
+ if ((!display_params || (display_params->flags & IGD_DISPLAY_READ_EDID))
+ && (port->firmware_type == PI_FIRMWARE_DISPLAYID
+ && port->displayid != NULL)) {
+
+ config_info->displayid_rotation[port->port_number - 1].rotation =
+ port->displayid->rotation_info.rotation;
+ config_info->displayid_rotation[port->port_number - 1].flip =
+ port->displayid->rotation_info.flip;
+
+ } else {
+ config_info->displayid_rotation[port->port_number - 1].rotation = 0;
+ config_info->displayid_rotation[port->port_number - 1].flip = 0;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+int pi_init(igd_context_t *context)
+{
+ i2c_dispatch_t *i2c_dispatch;
+
+ EMGD_TRACE_ENTER;
+
+ OS_MEMSET(pi_context, 0, sizeof(pi_context_t));
+
+ /* Save igd_context in local_igd_context. */
+ pi_context->igd_context = context;
+
+ /* Get I2C dispatch table */
+ i2c_dispatch = (i2c_dispatch_t *)dispatch_acquire(context,
+ i2c_dispatch_list);
+ if(!i2c_dispatch) {
+ EMGD_DEBUG("No i2c Dispatch available for PI module");
+ }
+ pi_context->i2c_dispatch = i2c_dispatch;
+
+ /*
+ * If Dynamic Port drivers are not used then init the static drivers
+ * now.
+ */
+#ifndef IGD_DPD_ENABLED
+ {
+ void *handle = NULL;
+ int ret;
+ ret = pi_init_all(handle);
+ }
+#endif
+
+ /* Inter-module dispatch functions */
+ context->mod_dispatch.i2c_read_regs = i2c_dispatch->i2c_read_regs;
+ context->mod_dispatch.i2c_write_reg_list =
+ i2c_dispatch->i2c_write_reg_list;
+ context->mod_dispatch.pi_get_config_info = pi_get_config_info;
+
+ OPT_MICRO_CALL(pi_full_init(context));
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * Get a port with the requested feature set from the list. Don't allocate
+ * it just return it. Only consider ports that aren't already in use.
+ *
+ * @param feature
+ * @param last
+ *
+ * @return port on success
+ * @return NULL on failure
+ */
+igd_display_port_t *pi_get_feature_port(unsigned long feature,
+ igd_display_port_t *last)
+{
+ igd_display_port_t *port;
+ inter_module_dispatch_t *md = &pi_context->igd_context->mod_dispatch;
+
+ while ((port = md->dsp_get_next_port(pi_context->igd_context, last, 0))) {
+ if (!port->inuse) {
+ if (feature) {
+ if (port->port_features & feature) {
+ return port;
+ }
+ } else {
+ return port;
+ }
+ }
+ last = port;
+ }
+
+ return NULL;
+}
+
+/*!
+ * Function to register port driver with display driver
+ *
+ * @param pd_driver
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_NULL_PTR, PD_ERR_VER_MISMATCH, PD_ERR_DISPLAY_TYPE,
+ * PD_ERR_NOMEM on failure
+ */
+int pi_pd_register(pd_driver_t *pd_driver)
+{
+ igd_display_port_t *port;
+ igd_param_t *init_params;
+ unsigned long prev_dab = 0, prev_i2c_speed = 0;
+ unsigned long port_type, port_feature, second_port_feature = 0;
+ unsigned long cookie_sent, cookie_rcvd;
+ unsigned long num_instances = 0;
+ unsigned long prev_instance_dab = 0, prev_instance_i2c_reg = 0;
+ unsigned long dab_index = 0;
+ int ret = PD_SUCCESS;
+
+ EMGD_TRACE_ENTER;
+
+ if (!pd_driver) {
+ EMGD_ERROR_EXIT("Null pd_driver received.");
+ return PD_ERR_NULL_PTR;
+ }
+
+ /* Check the PD SDK version (interface version between main and
+ * port drivers Rightnow this check is useful only for XFree86.
+ * XP and CE already done this checking. */
+ if (pd_driver->pd_sdk_version != PD_SDK_VERSION) {
+ EMGD_ERROR("PD SDK version mismatch between main driver"
+ "and %s. %u.%u != %u.%u", pd_driver->name,
+ (unsigned short) PD_SDK_VERSION>>8,
+ (unsigned short) PD_SDK_VERSION & 0xFF,
+ (unsigned short) pd_driver->pd_sdk_version>>8,
+ (unsigned short) pd_driver->pd_sdk_version & 0xFF);
+ return PD_ERR_VER_MISMATCH;
+ }
+
+ /* Do magic cookie hand shaking */
+#ifndef CONFIG_MICRO
+ cookie_sent = get_magic_cookie(pd_driver);
+#else
+ cookie_sent = 0;
+#endif
+ cookie_rcvd = pd_driver->validate(cookie_sent);
+ if (cookie_sent != cookie_rcvd) {
+ /* TODO: Do this check once we comeup with handshake algorithm. */
+ /*
+ EMGD_ERROR("Error, magic cookie handshaking failed.");
+ return PD_ERR_HAND_SHAKE;
+ */
+ }
+
+ init_params = pi_context->igd_context->mod_dispatch.init_params;
+
+ port_feature = 0;
+ /* Get the port features based on the display types */
+ if (pd_driver->type == PD_DISPLAY_CRT) {
+ /* Allocate GMCH onboard CRT port */
+ port_type = IGD_PORT_ANALOG;
+ } else if (pd_driver->type == PD_DISPLAY_LVDS_INT) {
+ /* Allocate GMCH onboard LVDS port */
+ port_type = IGD_PORT_LVDS;
+ } else if (pd_driver->type == PD_DISPLAY_TVOUT_INT) {
+ /* Allocate GMCH onboard TV port */
+ port_type = IGD_PORT_TV;
+ } else if (pd_driver->type &
+ (PD_DISPLAY_TVOUT | PD_DISPLAY_FP | PD_DISPLAY_CRT_EXT |
+ PD_DISPLAY_LVDS_EXT | PD_DISPLAY_HDMI_EXT| PD_DISPLAY_HDMI_INT|
+ PD_DISPLAY_DRGB)) {
+
+ /* Allocate DVO port which is the only kind of port exported to
+ * 3rd party encoders */
+ port_type = IGD_PORT_DIGITAL;
+
+ if (pd_driver->flags & PD_FLAG_GANG_MODE) {
+ igd_display_port_t *portb;
+ unsigned long user_gang = 0;
+ /* Get DVO Port B */
+ pi_context->igd_context->mod_dispatch.dsp_get_display(2,
+ NULL, &portb, 0);
+ if(portb) {
+ if (portb->attr_list && portb->attr_list->num_attrs != 0) {
+ unsigned long i;
+ for (i = 0; i < portb->attr_list->num_attrs; i++) {
+ if (portb->attr_list->attr[i].id==PD_ATTR_ID_GANG_MODE){
+ user_gang = portb->attr_list->attr[i].value;
+ }
+ }
+ }
+ }
+ /* If both user attribute and port driver flag are set to GANG MODE,
+ * then allocate a gang display port */
+ if (user_gang) {
+ port_feature = IGD_PORT_GANG;
+ second_port_feature = IGD_PORT_GANG;
+ }
+ }
+ } else if (pd_driver->type == PD_DISPLAY_RGBA) {
+ port_type = IGD_PORT_DIGITAL;
+ port_feature = IGD_RGBA_COLOR;
+ second_port_feature = IGD_RGBA_ALPHA;
+ } else {
+ EMGD_ERROR_EXIT("Invalid display type.");
+ return PD_ERR_DISPLAY_TYPE;
+ }
+
+ /* Get the port entry */
+ port = NULL;
+ while((port = pi_get_feature_port(port_feature, port))) {
+ dab_index = 0;
+
+
+ /* This port already has a port driver,
+ * don't search device on this port. */
+ if (port->pd_driver || (port->port_type != port_type)) {
+ continue;
+ }
+
+ /* allocate memory for callback */
+ port->callback = (pd_callback_t *)OS_ALLOC(sizeof(pd_callback_t));
+ if (port->callback == NULL) {
+ EMGD_ERROR_EXIT("Unable to alloc memory for callback context.");
+ return PD_ERR_NOMEM;
+ }
+ /* Fill entries in pd_callback_t */
+ port->callback->callback_context = port;
+ port->callback->read_regs = pi_read_regs;
+ port->callback->write_regs = pi_write_regs;
+ port->callback->eld = NULL; /* Insert when edid is initialize */
+
+ /* SDVO port driver needs the port number */
+ port->callback->port_num = port->port_number;
+
+ /* SDVO port driver should not reset for seamless mode */
+ port->callback->reset = (init_params->qb_seamless == 1) ? 0 : 1;
+ /* now save the pd_driver in port entry */
+ port->pd_driver = pd_driver;
+
+ /* preference is to user specified i2c_speed */
+ prev_dab = port->dab;
+ prev_i2c_speed = port->i2c_speed;
+ if (!port->i2c_speed) {
+ port->i2c_speed = pd_driver->i2c_speed?pd_driver->i2c_speed:
+ I2C_DEFAULT_SPEED;
+ }
+
+ /* Try detecting the encoder by calling port driver open() */
+ if (port->dab ||
+ ((port->dab == 0) && (pd_driver->dab_list[0] == PD_DAB_LIST_END))) {
+
+ /* Workaround for not to detect 2 encoders if only 1 encoder
+ * is present and both DVOB and DVOC are using same I2C bus */
+ if ((init_params->display_flags & IGD_DISPLAY_MULTI_DVO) &&
+ (num_instances > 0) &&
+ (prev_instance_dab == port->dab) &&
+ (prev_instance_i2c_reg == port->i2c_reg)) {
+ /* Print this msg, because user explicitly mentioned DAB/I2C
+ * bus details which are same as previous encoder's DAB/I2C bus
+ * details. */
+ EMGD_DEBUG("1+ encoders have same I2C bus and DAB");
+ ret = -1;
+ } else {
+ /* Call open() only once if either user provides a DAB
+ * or
+ * no required to open an encoder. ex: analog, rgba, lvds etc.
+ */
+ EMGD_DEBUG("Looking for \"%s\" on port 0x%lx with DAB 0x%lx",
+ pd_driver->name, port->port_reg, port->dab);
+ ret = pd_driver->open(port->callback, &(port->pd_context));
+ }
+ } else {
+
+ /* Call open() for each DAB */
+ while (pd_driver->dab_list[dab_index] != PD_DAB_LIST_END) {
+ if(pd_driver->type == PD_DISPLAY_LVDS_INT) {
+ port->ddc_dab = pd_driver->dab_list[dab_index];
+ printk ("NUHAIRI: port->ddc_dab\n" );
+ } else {
+ port->dab = pd_driver->dab_list[dab_index];
+ }
+
+ /* Workaround for not to detect 2 encoders if only 1 encoder
+ * is present and both DVOB and DVOC are using same I2C bus */
+ if ((init_params->display_flags & IGD_DISPLAY_MULTI_DVO) &&
+ (num_instances > 0) &&
+ (prev_instance_dab == port->dab) &&
+ (prev_instance_i2c_reg == port->i2c_reg)) {
+ /* Don't print the debug msg, because this is a valid case.
+ * Example,
+ * Algorithm is detecting for multiple encoders with
+ * same DAB and same I2C bus on different ports.
+ * If this case arises, simply continue
+ */
+ /* EMGD_DEBUG("1+ encoders have same I2C bus and DAB"); */
+ if (pd_driver->flags & PD_FLAG_DUAL_DVO) {
+ /* If this flag is set, that means port driver is
+ * explicityly requesting to be loaded on
+ * both DVO B & DVO C with same DAB. Example: CH7017.
+ *
+ * In this case open the port driver again. */
+ } else {
+ ret = -1;
+ port->pd_context = NULL;
+ dab_index++;
+ continue;
+ }
+ }
+
+ EMGD_DEBUG("Looking for \"%s\" on port 0x%lx with DAB 0x%lx",
+ pd_driver->name, port->port_reg, port->dab);
+ ret = pd_driver->open(port->callback, &(port->pd_context));
+ if (ret == 0) {
+ break;
+ } else {
+
+ dab_index++;
+ }
+ }
+ }
+#ifndef CONFIG_MICRO
+ if(pi_context->igd_context->mod_dispatch.check_port_supported && ret == 0){
+ ret = pi_context->igd_context->mod_dispatch.check_port_supported(port);
+ }
+#endif
+ if (ret == 0) {
+
+ /* Initialize our port entry */
+ ret = pi_pd_init(port, port_feature, second_port_feature, TRUE);
+ if (ret) {
+ port->pd_driver = NULL;
+ port->pd_context = NULL;
+ port->dab = prev_dab;
+ port->i2c_speed = prev_i2c_speed;
+ port->mult_port = NULL;
+ port->timing_table = NULL;
+ port->num_timing = 0;
+ if (port->callback) {
+ OS_FREE(port->callback);
+ port->callback = NULL;
+ }
+ } else {
+ EMGD_DEBUG("Device found on %s port for \"%s\"", port->port_name,
+ pd_driver->name);
+ num_instances++;
+ prev_instance_dab = port->dab;
+ prev_instance_i2c_reg = port->i2c_reg;
+ }
+
+ /* If Multi-DVO support is enabled then detect next encoder of
+ * same kind */
+ if (init_params->display_flags & IGD_DISPLAY_MULTI_DVO){
+ /* Continue to find next encoder */
+ continue;
+ } else {
+ /* Found one encoder and return to port driver */
+ break;
+ }
+ } else {
+ port->pd_driver = NULL;
+ port->pd_context = NULL;
+ port->dab = prev_dab;
+ port->i2c_speed = prev_i2c_speed;;
+ if (port->callback) {
+ OS_FREE(port->callback);
+ port->callback = NULL;
+ }
+ }
+ } /* end while(port == feature_port()) */
+
+ if (num_instances == 0) {
+ EMGD_DEBUG("No device found for \"%s\"", pd_driver->name);
+ return PD_ERR_NOPORT_AVAIL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return PD_SUCCESS;
+} /* end pi_pd_register() */
+
+/* Function to replace common timings in 1st list with 2nd list, 2nd list
+ * is unchanged. */
+void replace_common_dtds(igd_timing_info_t *dtds1,
+ igd_timing_info_t *dtds2)
+{
+ igd_timing_info_t *temp;
+ int index;
+
+ if (!dtds2 || !dtds1) {
+ return;
+ }
+
+ while (dtds1->width != IGD_TIMING_TABLE_END) {
+ temp = dtds2;
+ index = 0;
+
+ while (temp->width != IGD_TIMING_TABLE_END && index < NUM_TIMINGS) {
+ /* Replace modes that have common width, height and
+ refresh rate. Removed Dot clock comparison since
+ EDID(CEA modes) may differ in dot clock value.
+ causing duplicate mode.
+ All ial would do a match mode by height, width
+ and refresh rate.
+ */
+ if ((temp->width == dtds1->width) &&
+ (temp->height == dtds1->height) &&
+ (temp->refresh == dtds1->refresh) &&
+ ((temp->mode_info_flags & PD_SCAN_INTERLACE) ==
+ (dtds1->mode_info_flags & PD_SCAN_INTERLACE))) {
+ dtds1->mode_info_flags &= ~PD_MODE_SUPPORTED;
+ }
+ temp++;
+ index++;
+ }
+ dtds1++;
+ }
+}
+
+/*!
+ *
+ * @param port
+ *
+ * @return 0
+ */
+int check_port_attrs(igd_display_port_t *port)
+{
+ int ret;
+ unsigned long attr_value = 0;
+#ifndef CONFIG_MICRO
+ pd_attr_t out_list,*temp_list;
+ temp_list = &out_list;
+#endif
+ /* Attempt to see if the port driver has this attibutes so it can update
+ the port driver value. For now this is required for internal HDMI which
+ has a different i2c bus and port name from the standard SDVO port driver.
+ DP would most likely use this attribute assuming it uese the same port
+ number as well*/
+ ret = pi_pd_find_attr_and_value(port, PD_ATTR_ID_PORT_DDC_REG,
+ PD_ATTR_FLAG_GENERAL, NULL, &attr_value);
+ if(!ret){
+ EMGD_DEBUG("ddr_reg value unique = %ld.", attr_value);
+ port->ddc_reg = attr_value;
+ }
+#ifndef CONFIG_MICRO
+ ret = pi_pd_find_attr_and_value(port, PD_ATTR_ID_PORT_NAME,
+ PD_ATTR_FLAG_GENERAL, &(temp_list), &attr_value);
+ if(!ret){
+ EMGD_DEBUG("ddr_reg value unique = %ld.", attr_value);
+ pd_strcpy(port->port_name, temp_list->name);
+ }
+#endif
+ return 0;
+
+}
+
+/*!
+ * Function to initialize port driver related members in port table entry
+ *
+ * @param port
+ * @param port_feature
+ * @param second_port_feature
+ * @param drm_load_time
+ *
+ * @return PD_SUCCESS on success
+ * @return 1 on failure
+ */
+int pi_pd_init(igd_display_port_t *port,
+ unsigned long port_feature,
+ unsigned long second_port_feature,
+ int drm_load_time)
+{
+ igd_display_port_t *second_port;
+ pd_timing_t *user_timings = NULL;
+ pd_timing_t *std_timings = NULL;
+ pd_timing_t *firmware_timings = NULL;
+ pd_timing_t *final_timings = NULL;
+ pd_timing_t *pd_timing_table = NULL;
+ mode_state_t *mstate;
+ int i, ret = PD_SUCCESS;
+ unsigned long edid_flags;
+ unsigned char num_firmware_timings = 0;
+ igd_display_params_t *display_params = NULL;
+ igd_param_t *init_params;
+
+ EMGD_TRACE_ENTER;
+
+ mstate = NULL;
+
+ /* If the display device is a ganged mode device or RGBA mode, then hook
+ * up second port pointer in first port */
+ if (second_port_feature) {
+ second_port = pi_get_feature_port(second_port_feature, port);
+
+ /* If second_port is N/A, or second port was already taken by
+ * other port driver, then release main port and return error */
+ if (second_port == NULL || second_port->pd_driver) {
+ EMGD_ERROR_EXIT("Second ganged/RGBA port N/A or already allocated.");
+ return PD_ERR_NOPORT_AVAIL;
+ }
+ /* now link second port to first one */
+ port->mult_port = second_port;
+ }
+
+ /* Check port attributes to overwrite port value is any available */
+ check_port_attrs(port);
+ /* Implementation notes to get the timing list:
+ * Any port timing table consists of
+ * EDID DTDS
+ * USER DTDS
+ * STD TIMINGS
+ * based on edid_flags.
+ *
+ * If there are no flags, then it defaults to use STD TIMINGS + EDID DTDs
+ */
+
+ /* Get the display params for this port */
+ init_params = pi_context->igd_context->mod_dispatch.init_params;
+
+ for (i = 0; i < 5; i++) {
+ if (port->port_number == init_params->display_params[i].port_number) {
+ display_params = &init_params->display_params[i];
+ break;
+ }
+ }
+
+ /* Start with STD TIMINGS */
+ edid_flags = IGD_DISPLAY_USE_STD_TIMINGS;
+
+ /* If there is EDID, then default to use EDID */
+ if (!display_params || (display_params->flags & IGD_DISPLAY_READ_EDID)) {
+ /* Read firmware (EDID/DisplayID) on I2C */
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->ddc_reg, /* DDC register */
+ port->ddc_speed, /* DDC speed */
+ port->ddc_dab, /* Data Addr Byte*/
+ 0, /* Register */
+ firmware_data, /* Values */
+ 128, /* Num bytes to read */
+ 0);
+
+ /* If EDID is present then use EDID.
+ * edid_flags will be corrected later if display_params are present */
+ if (ret == 0) {
+ edid_flags |= IGD_DISPLAY_USE_EDID;
+ }
+ }
+
+ /* Check for display params */
+ if (display_params) {
+ if (edid_flags & IGD_DISPLAY_USE_EDID) {
+ /* Adjust edid_flags to use edid_avail
+ * if both edid is present and edid_avail is not 0 */
+ if (display_params->edid_avail) {
+ edid_flags = display_params->edid_avail;
+ EMGD_DEBUG("EDID_Avail: 0x%lx", edid_flags);
+ }
+ } else {
+ /* Adjust edid_flags to use edid_not_avail
+ * if edid is not present and edid_not_avail is not 0 */
+ if (display_params->edid_not_avail) {
+ edid_flags =
+ display_params->edid_not_avail & ~IGD_DISPLAY_USE_EDID;
+ EMGD_DEBUG("EDID_Not_Avail: 0x%lx", edid_flags);
+ }
+ }
+ }
+
+ /* Make a copy of crt_timing_table */
+ /* All crt timings are already enabled in mode_table.c */
+ std_timings = (igd_timing_info_t *) OS_ALLOC(crt_timing_table_size);
+ OS_MEMCPY(std_timings, crt_timing_table, crt_timing_table_size);
+
+ /* Include Standard built-in modes */
+ if (edid_flags & IGD_DISPLAY_USE_STD_TIMINGS) {
+ EMGD_DEBUG("Using STD TIMINGS ");
+ final_timings = std_timings;
+ }
+
+ /* Include user DTDs */
+ if (edid_flags & IGD_DISPLAY_USE_USERDTDS) {
+ EMGD_DEBUG("Using USER-DTDs ");
+ user_timings = get_user_timings(port->dtd_list);
+
+ if (user_timings) {
+ /* Add user DTDs at the begining of the final timings */
+ user_timings[port->dtd_list->num_dtds].extn_ptr = final_timings;
+ final_timings = user_timings;
+ }
+ }
+
+ /* Include EDID timings and filter modes */
+ if (edid_flags & IGD_DISPLAY_USE_EDID) {
+ EMGD_DEBUG("Using EDID-DTDs ");
+ ret = get_firmware_timings(port, firmware_data, final_timings);
+ if (port->firmware_type == PI_FIRMWARE_EDID) {
+ firmware_timings = port->edid->timings;
+ num_firmware_timings = port->edid->num_timings;
+ } else if (port->firmware_type == PI_FIRMWARE_DISPLAYID) {
+ firmware_timings = port->displayid->timings;
+ num_firmware_timings = port->displayid->num_timings;
+ }
+ if (ret == 0 && num_firmware_timings) {
+ /* Add EDID DTDs at the begining of the final timings */
+ firmware_timings[num_firmware_timings].extn_ptr =
+ (void *)final_timings;
+ final_timings = firmware_timings;
+ }
+ }
+
+ /* Replace any common timings */
+ replace_common_dtds(std_timings, firmware_timings);
+ replace_common_dtds(std_timings, user_timings);
+ replace_common_dtds(firmware_timings, user_timings);
+
+ /* Count the number of timings in final_timings. If the above functions
+ * result in an empty timing list, then use std_timings as default.
+ */
+ if (!get_native_dtd(final_timings, PI_SUPPORTED_TIMINGS, NULL, 0)) {
+ EMGD_DEBUG("User options resulted in 0 timings; using std timings.");
+ final_timings = std_timings;
+ enable_disable_timings(final_timings, 1);
+ }
+
+ /* Update port driver attributes */
+ update_attrs(port);
+
+ /* Now get the timing list filtered by PORT DRIVER */
+ ret = port->pd_driver->get_timing_list(port->pd_context,
+ final_timings, &pd_timing_table);
+
+ if (ret || !pd_timing_table) {
+ EMGD_ERROR_EXIT("port driver: get timing list error.");
+ return PD_ERR_NO_TIMINGS;
+ }
+
+ /* Delete temporary lists and buffers */
+ if (user_timings) {
+ OS_FREE(user_timings);
+ }
+ if (std_timings) {
+ OS_FREE(std_timings);
+ }
+
+ /* Filter modes based on chipset type */
+ pi_context->igd_context->mod_dispatch.filter_modes(pi_context->igd_context,
+ port, pd_timing_table);
+
+ /* Now save the timings in port */
+ port->timing_table = pd_timing_table;
+ port->num_timing = get_native_dtd(pd_timing_table,
+ PI_SUPPORTED_TIMINGS, &port->fp_native_dtd, PD_MODE_DTD_FP_NATIVE);
+
+ assign_dynamic_numbers(port->timing_table);
+
+#ifdef DEBUG_FIRMWARE
+ {
+ int ti;
+ EMGD_DEBUG("Supported timings for \"%s\" (%lu)",
+ port->pd_driver->name, port->num_timing);
+ ti = 0;
+ while (port->timing_table[ti].width != PD_TIMING_LIST_END) {
+ if (port->timing_table[ti].mode_info_flags & PD_MODE_SUPPORTED) {
+ EMGD_DEBUG("\t%ux%u@%u dclk=%lu mode_num=%d hsync=%luKHz "
+ "vsync=%luHz flags=0x%lx",
+ port->timing_table[ti].width,
+ port->timing_table[ti].height,
+ port->timing_table[ti].refresh,
+ port->timing_table[ti].dclk,
+ port->timing_table[ti].mode_number,
+ port->timing_table[ti].dclk/port->timing_table[ti].htotal,
+ ((port->timing_table[ti].dclk * 1000)/
+ port->timing_table[ti].htotal)/
+ port->timing_table[ti].vtotal,
+ port->timing_table[ti].mode_info_flags);
+ }
+ ti++;
+ }
+ }
+#endif
+
+
+ /*
+ * Exit early when called by emgd_driver_pre_init to poke the X driver's
+ * (i.e. "xorg.conf") DTDs and attr's into the port drivers (done above).
+ */
+ if (!drm_load_time) {
+ EMGD_TRACE_EXIT;
+ return PD_SUCCESS;
+ }
+
+
+#ifndef CONFIG_MICRO
+ /*
+ * There is only two states that need to be saved; one is the regular state
+ * and the other is for the console.
+ */
+ ret = pi_save_mode_state(port, REG_MODE_STATE_REG);
+ if (config_drm.init) {
+ ret = pi_save_mode_state(port, REG_MODE_STATE_CON);
+ }
+#endif
+
+ if(port->displayid != NULL){
+ /* Driver to init audio if cea extension available */
+ if(port->firmware_type == PI_FIRMWARE_EDID){
+ port->callback->eld = &(port->edid->cea);
+ }
+ /* Displayid unsupported for now. Uncomment this code when audio
+ information is available for Display ID
+ else if(port->firmware_type == PI_FIRMWARE_EDID){
+ port->callback->eld = &(port->displayid->cea);
+ }
+ */
+ else{
+ port->callback->eld = NULL;
+ }
+ }
+ ret = port->pd_driver->init_device(port->pd_context);
+ if (ret) {
+#ifndef CONFIG_MICRO
+ /* TODO: Restore the pd state? */
+ EMGD_ERROR_EXIT("port driver: init_device error. ret = %d", ret);
+ if (mstate) {
+ mstate->pd_state[pi_context->num_pi_drivers].port = NULL;
+ mstate->pd_state[pi_context->num_pi_drivers].state = NULL;
+ }
+#endif
+ return ret;
+ }
+
+ /* Increment the number of port drivers */
+ pi_context->num_pi_drivers++;
+
+ /* save the port driver display type & flags in port. These additions are
+ * required to support different types displays by same port driver. */
+ port->pd_type = port->pd_driver->type;
+ port->pd_flags = port->pd_driver->flags;
+
+ EMGD_TRACE_EXIT;
+ return PD_SUCCESS;
+} /* end pi_pd_init */
+
+/*!
+ * Function to read registers
+ *
+ * @param context
+ * @param list
+ * @param type
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_NULL_PTR, PD_ERR_I2C_READ, PD_ERR_UNSUCCESSFUL on failure
+ */
+int pi_read_regs(void *callback_context, pd_reg_t *list, unsigned long type)
+{
+ int ret;
+ igd_display_port_t *port = callback_context;
+ unsigned char *mmio;
+
+ /*EMGD_TRACE_EXIT;*/
+
+ if (!port) {
+ EMGD_ERROR_EXIT("Null callback context passed.");
+ return PD_ERR_NULL_PTR;
+ }
+
+ if (!port->pd_driver) {
+ EMGD_ERROR_EXIT("Null pd_driver in port entry.");
+ return PD_ERR_NULL_PTR;
+ }
+
+ mmio = EMGD_MMIO(pi_context->igd_context->device_context.virt_mmadr);
+
+ /* Based on the port type either read GMCH registers or I2C registers */
+ switch (type) {
+ case PD_REG_I2C:
+ ret = 0;
+ while (list->reg != PD_REG_LIST_END) {
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->i2c_reg,
+ port->i2c_speed,
+ port->dab,
+ (unsigned char)list->reg,
+ (unsigned char *)&list->value, 1, 0);
+ if (ret) {
+ EMGD_DEBUG("i2c_read_reg: 0x%lx failed.", list->reg);
+ break;
+ }
+ list++;
+ }
+ if (ret) {
+ return PD_ERR_I2C_READ;
+ }
+ break;
+ case PD_REG_DDC_FW:
+ ret = 0;
+ while (list->reg != PD_REG_LIST_END) {
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->ddc_reg,
+ port->ddc_speed,
+ port->ddc_dab,
+ (unsigned char)list->reg,
+ (unsigned char *)&list->value, 1,
+ IGD_I2C_WRITE_FW);
+ if (ret) {
+ EMGD_DEBUG("i2c_read_reg: 0x%lx failed.", list->reg);
+ break;
+ }
+ list++;
+ }
+ if (ret) {
+ return PD_ERR_I2C_READ;
+ }
+ break;
+ case PD_REG_DDC:
+ ret = 0;
+ while (list->reg != PD_REG_LIST_END) {
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->ddc_reg,
+ port->ddc_speed,
+ port->ddc_dab,
+ (unsigned char)list->reg,
+ (unsigned char *)&list->value, 1,
+ 0);
+ if (ret) {
+ EMGD_DEBUG("i2c_read_reg: 0x%lx failed.", list->reg);
+ break;
+ }
+ list++;
+ }
+ if (ret) {
+ return PD_ERR_I2C_READ;
+ }
+ break;
+ case PD_REG_PIO8:
+ while (list->reg != PD_REG_LIST_END) {
+ list->value = EMGD_READ_PORT8(list->reg);
+ list++;
+ }
+ break;
+ case PD_REG_PIO16:
+ while (list->reg != PD_REG_LIST_END) {
+ list->value = EMGD_READ_PORT16(list->reg);
+ list++;
+ }
+ break;
+ case PD_REG_PIO32:
+ while (list->reg != PD_REG_LIST_END) {
+ list->value = EMGD_READ_PORT32(list->reg);
+ list++;
+ }
+ break;
+ case PD_REG_MIO :
+ case PD_REG_MIO8 :
+ if ((port->port_type == IGD_PORT_ANALOG) ||
+ (port->port_type == IGD_PORT_TV) || /* For Integrated TV */
+ (port->port_type == IGD_PORT_LVDS) ||
+ (port->port_type == IGD_PORT_DIGITAL)) {
+ while (list->reg != PD_REG_LIST_END) {
+ if (type == PD_REG_MIO) {
+ if (BIT31 & list->reg) {
+#ifdef CONFIG_TNC
+ /* Atom E6xx si hack: Si folks defined LVDS (0:2:0)
+ * related register in 0:3:0 (sdvo device) as they
+ * are afraid to touch Lincroft hardmacro.
+ * This triggered LVDS port driver to touch 0:3:0
+ * registers for its operation. As this is done for
+ * LVDS operation and LVDS port driver is internal,
+ * BIT31 is defined to access 0:3:0 device. */
+ list->value = READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+ list->reg);
+#endif
+ } else {
+ list->value = EMGD_READ32(EMGD_MMIO(mmio) + list->reg);
+ }
+ } else {
+ list->value = EMGD_READ8(EMGD_MMIO(mmio) + list->reg);
+ }
+ list++;
+ }
+ }
+ break;
+#ifdef CONFIG_TNC
+ case PD_REG_LPC:
+ if (port->port_type == IGD_PORT_LVDS) {
+ while (list->reg != PD_REG_LIST_END) {
+ list->value = READ_MMIO_REG_TNC(IGD_PORT_LPC, list->reg);
+ list++;
+ }
+ }
+ break;
+#endif
+ case PD_REG_PCI:
+ /* Rightnow this is only to provide the device id */
+ while (list->reg != PD_REG_LIST_END) {
+#if 0
+ /* Assume IGD at bus=0, dev=2, func=0 */
+ EMGD_WRITE_PORT32(0xCF8,
+ (0x80000000 | (0L << 16) | (2L << 11) | (0L << 8) |
+ (list->reg & 0xFC)));
+ list->value = EMGD_READ_PORT32(0xCFC + (list->reg & 0x03));
+#endif
+ list->value = pi_context->igd_context->device_context.did;
+ list++;
+ }
+ break;
+ case PD_REG_BRIDGE_OPCODE:
+ /* right now, we only return the graphics frequency to calculate the
+ * PWM Backlight modulation frequency. This is only available for pouslbo */
+ while (list->reg != PD_REG_LIST_END) {
+ list->value = pi_context->igd_context->device_context.gfx_freq;
+ list++;
+ }
+
+ break;
+ default:
+ EMGD_ERROR_EXIT("Unknown reg type (0x%lx).", type);
+ return PD_ERR_UNSUCCESSFUL;
+ break;
+ }
+
+ /*EMGD_TRACE_EXIT;*/
+ return PD_SUCCESS;
+} /* end pi_read_regs */
+
+/*!
+ * Function to write registers
+ *
+ * @param context
+ * @param list
+ * @param type
+ *
+ * @return 0 on success
+ * @return PD_ERR_NULL_PTR, PD_ERR_I2C_WRITE, PD_ERR_UNSUCCESSFUL on failure
+ */
+extern unsigned short io_base_sdvo;
+extern unsigned short io_base;
+extern unsigned short io_base_sdvo_st;
+extern unsigned short io_base_sdvo_st_gpio;
+
+int pi_write_regs(void *callback_context, pd_reg_t *list, unsigned long type)
+{
+ igd_display_port_t *port = callback_context;
+ int ret;
+ unsigned char *mmio;
+
+ EMGD_TRACE_ENTER;
+
+ if (!port) {
+ EMGD_ERROR_EXIT("Null callback context passed.");
+ return PD_ERR_NULL_PTR;
+ }
+
+ if (!port->pd_driver) {
+ EMGD_ERROR_EXIT("Null pd_driver.");
+ return PD_ERR_NULL_PTR;
+ }
+
+ EMGD_DEBUG("Getting mmio");
+ mmio = EMGD_MMIO(pi_context->igd_context->device_context.virt_mmadr);
+ EMGD_DEBUG("mmio = 0x%lx", (unsigned long)mmio);
+
+ /* Based on the port type either write GMCH registers or I2C registers */
+ switch (type) {
+ case PD_REG_DDC_FW:
+ /*This will use shorter delay than PD_REG_DDC*/
+ ret = pi_context->i2c_dispatch->i2c_write_reg_list(
+ pi_context->igd_context,
+ port->ddc_reg,
+ port->ddc_speed,
+ port->ddc_dab,
+ list,
+ IGD_I2C_WRITE_FW);
+ if (ret) {
+ EMGD_DEBUG("i2c_write_reg: 0x%lx = 0x%lx failed.",
+ list->reg, list->value);
+ return PD_ERR_I2C_WRITE;
+ }
+ break;
+ case PD_REG_DDC:
+ ret = pi_context->i2c_dispatch->i2c_write_reg_list(
+ pi_context->igd_context,
+ port->ddc_reg,
+ port->ddc_speed,
+ port->ddc_dab,
+ list,
+ 0);
+ if (ret) {
+ EMGD_DEBUG("i2c_write_reg: 0x%lx = 0x%lx failed.",
+ list->reg, list->value);
+ return PD_ERR_I2C_WRITE;
+ }
+ break;
+ case PD_REG_I2C:
+ ret = pi_context->i2c_dispatch->i2c_write_reg_list(
+ pi_context->igd_context,
+ port->i2c_reg,
+ port->i2c_speed,
+ port->dab,
+ list,
+ 0);
+ if (ret) {
+ EMGD_DEBUG("i2c_write_reg: 0x%lx = 0x%lx failed.",
+ list->reg, list->value);
+ return PD_ERR_I2C_WRITE;
+ }
+ EMGD_DEBUG("i2c_write_reg success");
+ break;
+ case PD_REG_PIO8:
+ while (list->reg != PD_REG_LIST_END) {
+ EMGD_WRITE_PORT8(list->reg, list->value);
+ list++;
+ }
+ EMGD_DEBUG("EMGD_WRITE_PORT8 seemed successful");
+ break;
+ case PD_REG_PIO16:
+ while (list->reg != PD_REG_LIST_END) {
+ EMGD_WRITE_PORT16(list->reg, list->value);
+ list++;
+ }
+ EMGD_DEBUG("EMGD_WRITE_PORT16 seemed successful");
+ break;
+ case PD_REG_PIO32:
+ while (list->reg != PD_REG_LIST_END) {
+ EMGD_WRITE_PORT32(list->reg, list->value);
+ list++;
+ }
+ EMGD_DEBUG("EMGD_WRITE_PORT32 seemed successful");
+ break;
+ case PD_REG_MIO :
+ case PD_REG_MIO8 :
+ if ((port->port_type == IGD_PORT_ANALOG) ||
+ (port->port_type == IGD_PORT_TV) || /* For Integrated TV */
+ (port->port_type == IGD_PORT_LVDS) ||
+ (port->port_type == IGD_PORT_DIGITAL)) {
+ while (list->reg != PD_REG_LIST_END) {
+ if (type == PD_REG_MIO) {
+ if (BIT31 & list->reg) {
+#ifdef CONFIG_TNC
+ /* BIT31 indicates write to 0:3:0 SDVO device */
+ WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, list->reg,
+ list->value);
+#endif
+ } else {
+ EMGD_WRITE32(list->value, EMGD_MMIO(mmio) + list->reg);
+ }
+ } else {
+ EMGD_WRITE8(list->value, EMGD_MMIO(mmio) + list->reg);
+ }
+ list++;
+ }
+ EMGD_DEBUG("complicated write seemed successful");
+ }
+ break;
+#ifdef CONFIG_TNC
+ case PD_REG_LPC:
+ if (port->port_type == IGD_PORT_LVDS) {
+ while (list->reg != PD_REG_LIST_END) {
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, list->reg, list->value);
+ list++;
+ }
+ EMGD_DEBUG("Write to IGD_PORT_LPC seemed successful");
+ }
+ break;
+#endif
+ default:
+ EMGD_ERROR_EXIT("Unknown reg type (0x%lx).", type);
+ return PD_ERR_UNSUCCESSFUL;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* end pi_write_regs */
+
+/*!
+ * Depending on the parameters, this function does multiple things. It always
+ * counts and returns the number of [supported] timings. If desired, it also
+ * finds the timing with a desired "mode_info_flags" that has the largest value
+ * of width, height, OR refresh rate, which it sets to the "native_dtd"
+ * parameter.
+ *
+ * @param timing
+ * @param flags
+ * @param native_dtd
+ * @param nflags
+ *
+ * @return 0 on failure
+ * @return native dtd on success
+ */
+unsigned long get_native_dtd(igd_timing_info_t *timing,
+ unsigned long flags, pd_timing_t **native_dtd, unsigned long nflags)
+{
+ unsigned long entries = 0;
+
+ EMGD_TRACE_EXIT;
+
+ if (!timing) {
+ return 0;
+ }
+ if (native_dtd) {
+ *native_dtd = NULL;
+ }
+ while (timing->width != IGD_TIMING_TABLE_END) {
+ if (flags & PI_SUPPORTED_TIMINGS) {
+ if (timing->mode_info_flags & PD_MODE_SUPPORTED) {
+ entries++;
+ }
+ if ((native_dtd) &&
+ (timing->mode_info_flags & nflags)) {
+ /* Native Resolution is defined as the largest resolution the
+ * panel can display. However, some panels contain more than one
+ * DTD in its EDID. We will choose the largest resolution
+ * available from EDID */
+ if(((*native_dtd) && (nflags == PD_MODE_DTD)) &&
+ (((pd_timing_t*)(*native_dtd))->width > timing->width ||
+ ((pd_timing_t*)(*native_dtd))->height > timing->height ||
+ ((pd_timing_t*)(*native_dtd))->refresh > timing->refresh)){
+ /* do nothing */
+ } else {
+ *native_dtd = timing;
+ }
+ }
+ } else {
+ entries++;
+ }
+
+ timing++;
+ if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) {
+ timing = timing->extn_ptr;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return entries;
+}
+
+#ifndef CONFIG_MICRO
+unsigned long get_magic_cookie(pd_driver_t *pd_driver)
+{
+ /* FIXME: Implement cookie checking */
+ return 0;
+}
+#endif
+
+/*!
+ * Function to filter modes based on EDID or DisplayID
+ *
+ * @param port
+ * @param firmware_data
+ * @param timing_table
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_EDID, -IGD_ERROR_NOMEM on failure
+ */
+int get_firmware_timings(igd_display_port_t *port,
+ unsigned char *firmware_data, igd_timing_info_t *timing_table)
+{
+ edid_t *edid;
+ displayid_t *displayid;
+ int ret = -1;
+
+ EMGD_TRACE_ENTER;
+
+ if (!firmware_data) {
+ return -IGD_ERROR_EDID;
+ }
+
+ if (!port->displayid) {
+ /* EDID and DisplayID use same memory */
+ displayid = (displayid_t *) OS_ALLOC(sizeof(displayid_t));
+ if (!displayid) {
+ return -IGD_ERROR_NOMEM;
+ }
+ edid = (edid_t *) displayid;
+ } else {
+ displayid = port->displayid;
+ edid = (edid_t *) displayid;
+ }
+ OS_MEMSET(displayid, 0, sizeof(displayid_t));
+
+ /* Now parse the EDID or DisplayID */
+ /* Check the header to determine whether the data is EDID or DisplayID */
+ /* EDID header first 8 bytes =
+ * byte 0, 1, 2, 3: 00 ff ff ff = unsigned long 0xFFFFFF00
+ * byte 4, 5, 6, 7: ff ff ff 00 = unsigned long 0x00FFFFFF */
+ if (*(unsigned long *) &firmware_data[0] == 0xFFFFFF00 &&
+ *(unsigned long *) &firmware_data[4] == 0x00FFFFFF) {
+#ifdef DEBUG_FIRMWARE
+ firmware_dump(firmware_data, 256);
+#endif
+ /* This is EDID data */
+ ret = edid_parse(firmware_data, edid, timing_table, 0,
+ (unsigned char) (port->pd_driver->flags&PD_FLAG_UP_SCALING?1:0));
+ if (ret == EDID_READ_AGAIN) {
+ /* Check to see if there is an extension block */
+ if((firmware_data[0x7e] == 0x1)){
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->ddc_reg, /* DDC register */
+ port->ddc_speed, /* DDC speed */
+ port->ddc_dab, /* Data Addr Byte*/
+ 0x80, /* Register */
+ &firmware_data[128], /* Values */
+ 128,
+ 0); /* next 128 bytes include extension */
+ ret = edid_ext_parse(&firmware_data[128], edid, timing_table,0,
+ (unsigned char)(port->pd_driver->flags&
+ PD_FLAG_UP_SCALING?1:0));
+ /* Parse next 128 bytes of EDID block */
+ }else{
+ ret = 0;
+ }
+ } else if (ret) {
+ OS_FREE(edid);
+ return -IGD_ERROR_EDID;
+ }
+
+ port->firmware_type = PI_FIRMWARE_EDID;
+#ifdef DEBUG_FIRMWARE
+ edid_print(edid);
+#endif
+
+#ifndef CONFIG_NO_DISPLAYID
+ } else {
+ /* size = payload + 5 */
+ /* +5 is for the 5 mandatory bytes not included in payload */
+ unsigned short displayid_size = firmware_data[1] + 5;
+ if (displayid_size > 256) {
+ EMGD_DEBUG("Invalid DisplayID size = %u (incl 5 mand bytes) > 256",
+ displayid_size);
+ return -IGD_ERROR_EDID;
+ }
+
+ /* If the DisplayID is greater than 128 bytes */
+ if (displayid_size > 128) {
+ ret = pi_context->i2c_dispatch->i2c_read_regs(
+ pi_context->igd_context,
+ port->ddc_reg, /* DDC register */
+ port->ddc_speed, /* DDC speed */
+ port->ddc_dab, /* Data Addr Byte*/
+ 0, /* Register */
+ firmware_data, /* Values */
+ displayid_size, /* Num bytes to read */
+ 0);
+ }
+
+#ifdef DEBUG_FIRMWARE
+ firmware_dump(firmware_data, 256);
+#endif
+ /* This is DisplayID data */
+ ret = displayid_parse(firmware_data, displayid, timing_table, 0,
+ (unsigned char) (port->pd_driver->flags&PD_FLAG_UP_SCALING?1:0));
+ if (!ret) {
+ port->firmware_type = PI_FIRMWARE_DISPLAYID;
+ } else {
+ OS_FREE(displayid);
+ }
+#ifdef DEBUG_FIRMWARE
+ displayid_print(firmware_data, displayid);
+#endif
+#else
+ /* If DisplayID isn't enabled then print a debug message and return error */
+ } else {
+ EMGD_ERROR_EXIT("EDID header is wrong! Will ignore");
+ return -IGD_ERROR_EDID;
+#endif
+ }
+
+ port->edid = edid;
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* end get_firmware_timings() */
+
+/*!
+ * Update port driver attributes with incoming values from IAL
+ *
+ * @param in_list attributes in this list are used to update corresponding
+ * attributes in out_list
+ * @param fp_info flat panel attributes used to update ocrresponding
+ * attributes in out_list
+ * @param out_num_attrs size of out_list
+ * @param out_list contains a list of attributes to be updated
+ *
+ * @return 0
+ */
+int update_attrs(igd_display_port_t *port)
+{
+ int ret;
+ unsigned int i = 0;
+
+ igd_param_attr_list_t *in_list = port->attr_list;
+ igd_param_fp_info_t *fp_info = port->fp_info;
+
+ /* Initial 5 attributes are for fp_info,
+ * Note: If both igd_param_fp_info_t and fp_info attributes
+ * were specified then fp_info values takes the precedence */
+ unsigned long out_num_attrs = 5;
+ pd_attr_t *out_list;
+
+ EMGD_TRACE_ENTER;
+
+ /* if: there's something in in_list */
+ if (in_list) {
+ out_num_attrs += in_list->num_attrs;
+ }
+
+ out_list = OS_ALLOC(sizeof(pd_attr_t) * out_num_attrs);
+ if (!out_list) {
+ EMGD_DEBUG("No memory to make attr_list.");
+ return 0;
+ }
+ OS_MEMSET(out_list, 0, sizeof(pd_attr_t) * out_num_attrs);
+
+ /* Pass user specified attributes */
+ if (in_list) {
+ /* For every incoming attr, make a pd_attr_t */
+ for (i = 0; i < in_list->num_attrs; i++) {
+ /* This will work for all kinds of attributes:
+ * in_list->attr[i].value =
+ * actual value for range attributes
+ * index for list attributes
+ * value for boolean attributes.
+ * This works because
+ * pd_attr_t, pd_range_attr_t, pd_list_attr_t,
+ * pd_boolean_attr_t all have save offsets for
+ * default values. */
+ out_list[i].id = in_list->attr[i].id;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i].current_value = in_list->attr[i].value;
+ }
+ } /* if: there's something in in_list */
+
+ /* Pass flat panel attributes to the port driver, if necessary */
+ if (fp_info) {
+ /* Initialize flat panel attributes */
+ /* Update FP attributes */
+ if (fp_info->fp_pwr_method == IGD_PARAM_FP_PWR_METHOD_PD) {
+ /* The only thing remaining is the FP_PWR_Tx, so check
+ * to ensure it is for an FP_PWR_METHOD_PD */
+ out_list[i].id = PD_ATTR_ID_FP_PWR_T1;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i++].current_value = fp_info->fp_pwr_t1;
+
+ out_list[i].id = PD_ATTR_ID_FP_PWR_T2;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i++].current_value = fp_info->fp_pwr_t2;
+
+ out_list[i].id = PD_ATTR_ID_FP_PWR_T3;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i++].current_value = fp_info->fp_pwr_t3;
+
+ out_list[i].id = PD_ATTR_ID_FP_PWR_T4;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i++].current_value = fp_info->fp_pwr_t4;
+
+ out_list[i].id = PD_ATTR_ID_FP_PWR_T5;
+ out_list[i].flags = PD_ATTR_FLAG_VALUE_CHANGED;
+ out_list[i++].current_value = fp_info->fp_pwr_t5;
+ }
+ }
+
+#ifndef CONFIG_NO_DISPLAYID
+ /* Based on our architecture, any user-defined config option will override
+ * firmware options. i.e., First send the DisplayID attributes
+ * then send the config attributes to port drivers. */
+ if (port->firmware_type == PI_FIRMWARE_DISPLAYID) {
+ ret = port->pd_driver->set_attrs(port->pd_context,
+ port->displayid->num_attrs,
+ port->displayid->attr_list);
+ }
+#endif
+ ret = port->pd_driver->set_attrs(port->pd_context, i, out_list);
+ if (ret) {
+ EMGD_DEBUG("Attribute update failed. ret = %d.", ret);
+ }
+ OS_FREE(out_list);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* update_attrs */
+
+/* Add user defined timings to big timing table */
+pd_timing_t *get_user_timings(igd_param_dtd_list_t *in_list)
+{
+ pd_timing_t *t = NULL, *timing = NULL;
+ igd_display_info_t *dtd;
+ unsigned long i;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ if (!in_list || !(in_list->num_dtds) || !(in_list->dtd)) {
+ return NULL;
+ }
+
+ t = (pd_timing_t *)OS_ALLOC((in_list->num_dtds + 1)
+ * sizeof(pd_timing_t));
+ if (!t) {
+ return NULL;
+ }
+
+ OS_MEMSET(t, 0, (in_list->num_dtds + 1) * sizeof(pd_timing_t));
+ timing = t;
+ dtd = in_list->dtd;
+
+ /*
+ * OPTIMIZEME: When igd_display_info_t goes away there will be no reason
+ * to copy this data. A Rule can be imposed that anything passed to
+ * the HAL during init must remain in scope until the HAL is shut
+ * down. The HAL can then just use this directly.
+ */
+ for (i = 0; i < in_list->num_dtds; i++) {
+ OS_MEMCPY(t, dtd, sizeof(igd_display_info_t));
+ t->mode_info_flags = dtd->flags | PD_MODE_DTD_USER | PD_MODE_SUPPORTED;
+#if 0
+ /* Assume there is no border, then htotal and vtotal are the same as
+ * hblank_end and vblank_end */
+ t->htotal = t->hblank_end;
+ t->vtotal = t->vblank_end;
+ if (dtd->refresh) {
+ t->refresh = (unsigned short)dtd->refresh;
+ } else if (t->htotal && t->vtotal) {
+ t->refresh = (unsigned short)
+ ((unsigned long)((unsigned long)(t->dclk) * 1000) /
+ ((unsigned long)(t->htotal) *
+ (unsigned long)(t->vtotal)));
+ }
+#endif
+
+#ifndef CONFIG_MICRO
+ /*
+ * If the VESA flag is set, set the mode mode number to VESA.
+ * DTD may not contain mode number but the VESA flag is set
+ * This will cause program pipe VGA to be executed and fail
+ * Need to make sure that if USER wants to use VGA mode, that the
+ * mode_number is entered in the user DTD
+ */
+ if((t->mode_info_flags & PD_MODE_VESA) && (!t->mode_number)){
+ t->mode_number = VGA_MODE_NUM_MAX + 1;
+ }
+
+ /*
+ * Handle the corner case where user DTD is derived from std timing.
+ * Two std timings have border (htotal != h_blank_end).
+ * Compare the timing attribute with the std timing and use the
+ * total and refresh rate from std timing.
+ * Only happens when using Harmonic tool so the change is limited
+ * to Atom E6xx through the dispatch function
+ */
+ if(pi_context->igd_context->mod_dispatch.get_refresh_in_border){
+ /* returns 1 if a refresh was obtained */
+ ret = pi_context->igd_context->mod_dispatch.get_refresh_in_border(t);
+ }
+#endif
+ if(!ret){
+ /* Assume there is no border, then htotal and vtotal are the same as
+ * hblank_end and vblank_end */
+ t->htotal = t->hblank_end;
+ t->vtotal = t->vblank_end;
+ if (dtd->refresh) {
+ t->refresh = (unsigned short)dtd->refresh;
+ } else if (t->htotal && t->vtotal) {
+ /*
+ * Refresh is used mainly for esthetic, mainly in GUI.
+ * The compiler will truncate the decimals, not rounding
+ * UP the value (in this case, 59.7 will be 59Hz and not 60Hz
+ * Need to manually handle the rounding.
+ *
+ * We multiply the dclk by 10, therefore shifting the final
+ * decimal place by one, then check if the last digit is
+ * >4 to round up the refresh by 1 after dividing by 10.
+ */
+ unsigned short temp_refresh = (unsigned short)
+ ((unsigned long)((unsigned long)(t->dclk) * 10000) /
+ ((unsigned long)(t->htotal) *
+ (unsigned long)(t->vtotal)));
+ if((temp_refresh % 10) > 4){
+ t->refresh = (temp_refresh / 10 ) + 1;
+ } else {
+ t->refresh = (temp_refresh / 10);
+ }
+ }
+ }
+
+ /* t->pd_extn_ptr = NULL; */
+ t->extn_ptr = NULL;
+
+ t++;
+ dtd++;
+ }
+
+ /* End the table with end marker */
+ t->width = IGD_TIMING_TABLE_END;
+
+ EMGD_TRACE_EXIT;
+
+ return timing;
+}
+
+/*!
+ * Assign dynamic VBE numbers to the modes that do not already have
+ * VESA defined numbers.
+ *
+ * @param timing_table
+ *
+ * @return void
+ */
+#define FIRST_DYNAMIC_MODE_NUMBER 0x120
+void assign_dynamic_numbers(igd_timing_info_t *timing_table)
+{
+ unsigned short next_number = FIRST_DYNAMIC_MODE_NUMBER;
+ unsigned int i;
+ unsigned short vesa_mode_table[] = {
+ 640, 480, 0x101,
+ 800, 600, 0x103,
+ 1024, 768, 0x105,
+ 1280, 1024, 0x107,
+ 0xffff, 0xffff, 0xffff,
+ };
+
+ EMGD_TRACE_ENTER;
+
+ while(timing_table->width != IGD_TIMING_TABLE_END) {
+ if((timing_table->mode_info_flags & IGD_MODE_SUPPORTED) &&
+ !(timing_table->mode_info_flags & IGD_MODE_VESA)) {
+
+ for (i=0; vesa_mode_table[i] != 0xffff; i+=3) {
+ if ((timing_table->width == vesa_mode_table[i]) &&
+ (timing_table->height == vesa_mode_table[i+1])) {
+ /* This is a VESA Standard mode, so assign it to the
+ * correct VESA mode number. This can occur with
+ * modes added either through User Defined DTDs or
+ * potentially EDID. */
+ timing_table->mode_number = vesa_mode_table[i+2];
+ timing_table->mode_info_flags |= IGD_MODE_VESA;
+ break;
+ }
+ }
+ if (vesa_mode_table[i] == 0xffff) {
+ /* Assign this mode a Dynamic number, if it is not
+ * a VESA Standard mode. */
+ timing_table->mode_number = next_number;
+ /* VBE modes use lower 2 bits for depth so next mode is += 4 */
+ next_number += 4;
+ timing_table->mode_info_flags |= IGD_MODE_VESA;
+ }
+ }
+ timing_table++;
+
+ /* If reached the first table END,
+ * then check for the added modes */
+ if (timing_table->width == IGD_TIMING_TABLE_END &&
+ timing_table->extn_ptr) {
+ timing_table = timing_table->extn_ptr;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+/*!
+ * This is a utility function that can be used througout the HAL.
+ * It can be used to get a ptr to an attr structure and/or the
+ * actual current_value of that attribute.
+ * According to usage modal at time of creation of this function:
+ * - the *caller_pd_attr must be NULL if the attr was not found.
+ * - the *attr_value is only changed if the attr was found
+ *
+ * @param port
+ * @param attr_id
+ * @param flag
+ * @param caller_pd_attr
+ * @param attr_value
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int pi_pd_find_attr_and_value(igd_display_port_t *port,
+ unsigned long attr_id,
+ unsigned long flag,
+ pd_attr_t **caller_pd_attr,
+ unsigned long *attr_value)
+{
+ unsigned long pd_attr_length = 0;
+ pd_attr_t *pd_attr_list = NULL;
+ pd_attr_t *found_pd_attr = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if(!port || !(port->pd_driver)) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(flag == PD_ATTR_FLAG_GENERAL){
+ pd_attr_length = PD_QUERY_GENERAL_ATTR;
+ }
+ port->pd_driver->get_attrs(port->pd_context, &pd_attr_length,
+ &pd_attr_list);
+ if(!pd_attr_length) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ found_pd_attr = pd_get_attr(pd_attr_list, pd_attr_length, attr_id, flag);
+
+ if (!found_pd_attr) {
+ if(caller_pd_attr) {
+ *caller_pd_attr = NULL;
+ }
+ return -IGD_INVAL;
+ }
+ if(caller_pd_attr) {
+ *caller_pd_attr = found_pd_attr;
+ }
+ if(attr_value) {
+ *attr_value = found_pd_attr->current_value;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ *
+ * @param port
+ * @param id
+ * @param value
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int pi_get_port_init_attr(igd_display_port_t *port,
+ unsigned long id,
+ unsigned long *value)
+{
+ unsigned short i;
+
+ EMGD_TRACE_ENTER;
+
+ if (!port || !port->attr_list) {
+ return -IGD_ERROR_INVAL;
+ }
+
+ for (i = 0; i < (unsigned short) port->attr_list->num_attrs; i++) {
+ if (port->attr_list->attr[i].id == id) {
+ *value = port->attr_list->attr[i].value;
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+ }
+
+ EMGD_DEBUG("Attribute (0x%ld) Not Found", id);
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+}
+
+
+
+int pi_save_mode_state(igd_display_port_t *port, reg_state_id_t reg_state_id)
+{
+ int ret = PD_SUCCESS;
+ mode_state_t *mstate = NULL;
+ if(pi_context->igd_context->mod_dispatch.reg_get_mod_state) {
+ module_state_h *state = NULL;
+ unsigned long *flags = NULL;
+ pi_context->igd_context->mod_dispatch.reg_get_mod_state(
+ reg_state_id,
+ &state,
+ &flags);
+
+ if (state) {
+ mstate = (mode_state_t *)(*state);
+ }
+ }
+
+ /* If mode state is present in register context,
+ * then call save() function to save the port driver's state */
+ if (mstate) {
+ ret = port->pd_driver->pd_save(port->pd_context,
+ &(mstate->pd_state[pi_context->num_pi_drivers].state), 0);
+ if (ret) {
+ EMGD_ERROR_EXIT("port driver: reg saving error. ret = %d", ret);
+ return ret;
+ }
+ mstate->pd_state[pi_context->num_pi_drivers].port = port;
+ }
+
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c b/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
new file mode 100644
index 0000000..7021e34
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
@@ -0,0 +1,943 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_plb.c
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <plb/regs.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*......................................................................... */
+extern igd_display_port_t dvob_port_plb;
+
+/*......................................................................... */
+static int i2c_read_regs_plb(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags);
+
+static int i2c_write_reg_list_plb(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags);
+
+i2c_dispatch_t i2c_dispatch_plb = {
+ i2c_read_regs_plb,
+ i2c_write_reg_list_plb,
+};
+
+
+/*.......................................................................... */
+typedef enum {
+
+ GMBUS_SPEED_50K = 0x0100,
+ GMBUS_SPEED_100K = 0x0000,
+ GMBUS_SPEED_400K = 0x0200,
+ GMBUS_SPEED_1000K = 0x0300,
+
+} gmbus_speed_t;
+
+typedef enum {
+
+ SDVOB_ADDR = 0x70,
+ SDVOC_ADDR = 0x72,
+
+} sdvo_dev_addr_t;
+
+typedef enum {
+
+ DDC1_ADDR = 0xA0,
+ DDC2_ADDR = 0xA2,
+
+} gmbus_ddc_addr_t;
+
+
+typedef enum {
+
+ GMBUS_PINS_DEDICATED = 1, /* Dedicated Control/GMBUS Pins */
+ /* LCTRCLKA, LCTRLCLKB SSC Clock Device */
+ GMBUS_PINS_ANALOG = 2, /* Analog DDC */
+ GMBUS_PINS_INT_LVDS = 3, /* Alviso : Integrated Digital Panel */
+ GMBUS_PINS_SDVO = 5, /* SDVO Registers, DDC, PROM */
+
+} gmbus_pins_pair_t;
+
+
+typedef enum {
+
+ I2C_WRITE = 0,
+ I2C_READ = 1,
+
+} i2c_bus_dir_t;
+
+/*.......................................................................... */
+typedef enum {
+
+ SDVO_BUS_PROM = BIT(0),
+ SDVO_BUS_DDC1 = BIT(1),
+ SDVO_BUS_DDC2 = BIT(2),
+
+} sdvo_bus_switch_t;
+
+#define SDVO_OPCODE_BUS_SWITCH 0x7A
+
+#define SDVO_INDEX_PARAM_1 0x07
+#define SDVO_INDEX_OPCODE 0x08
+#define SDVO_INDEX_STATUS 0x09
+
+#define SDVO_STATUS_SUCCESS 0x01
+#define SDVO_STATUS_PENDING 0x04
+
+/*.......................................................................... */
+/*
+ * In 16-bit, the mmio is a 16-bit pointer, the watcom 1.2 compiler will have
+ * error if directly convert it to unsigned long. Normally, have to cast it to
+ * unsigned short first then cast again to unsigned long; then, it will be
+ * correct. But this type of casting may cause some error in the 32 and 64 bit
+ * code. Since mmio will be equal to zero for 16-bit code. Add the checking
+ * for MICRO definition code to correct the macro by remove mmio.
+ */
+#define READ_GMCH_REG(reg) EMGD_READ32(EMGD_MMIO(mmio) + reg)
+#define WRITE_GMCH_REG(reg, data) EMGD_WRITE32(data, EMGD_MMIO(mmio) + reg)
+
+static int gmbus_init(unsigned char *mmio, unsigned long i2c_bus,
+ unsigned long i2c_speed);
+
+static int gmbus_read_edid(unsigned char *mmio,
+ unsigned long ddc_addr,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned long num_bytes,
+ unsigned char FAR *buffer);
+
+static int gmbus_read_reg(unsigned char *mmio,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned char FAR *data);
+
+static int gmbus_write_reg(unsigned char *mmio,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned char data);
+
+static int gmbus_set_control_bus_switch(unsigned char *mmio,
+ unsigned long slave_addr,
+ gmbus_ddc_addr_t ddc_addr);
+
+static int gmbus_wait_event_one(unsigned char *mmio, unsigned long bit);
+static int gmbus_wait_event_zero(unsigned char *mmio, unsigned long bit);
+static int gmbus_error_handler(unsigned char *mmio);
+
+/*!
+ * i2c_read_regs_plb is called to read Edid or a single sDVO register
+ *
+ * @param context
+ * @param i2c_bus port->ddc_reg, port->i2c_reg
+ * @param i2c_speed 50, 100, 400, 1000 (Khz)
+ * @param dab 0x70/0x72 (sDVO Regs), 0xA0/0xA2 (sDVO/Analog DDC)
+ * @param reg I2C Reg Index
+ * @param num_bytes <= 508
+ * @param buffer Data read
+ * @param flags unused, put in to match TNC func signature
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_regs_plb(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags)
+{
+ unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ unsigned long slave_addr;
+
+ if (! gmbus_init(mmio, i2c_bus, i2c_speed)) {
+ EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_init() failed");
+ return 1;
+ }
+
+ /* If the request is to read Edid from sDVO display, find out the */
+ /* i2c addres of the sDVO device */
+ if (i2c_bus == GMBUS_DVOB_DDC) {
+ slave_addr = dvob_port_plb.dab;
+
+ } else {
+ slave_addr = 0;
+
+ }
+
+ switch (i2c_bus) {
+ case GMBUS_ANALOG_DDC :
+ case GMBUS_INT_LVDS_DDC :
+ case GMBUS_DVOB_DDC :
+ case GMBUS_DVOC_DDC :
+ if (! gmbus_read_edid(mmio, dab, slave_addr, reg, num_bytes, buffer)) {
+
+ EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_read_edid() failed");
+ return 1;
+ }
+ break;
+
+ case GMBUS_DVO_REG :
+ if (! gmbus_read_reg(mmio, dab, reg, buffer)) {
+
+ EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_read_reg() failed");
+ return 1;
+ }
+ break;
+
+ default :
+ EMGD_ERROR("Error ! i2c_read_regs_plb : Invalid i2c_bus=0x%lx",
+ i2c_bus);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*!
+ * i2c_write_reg_list_plb is called to write a list of i2c registers to sDVO
+ * device
+ *
+ * @param context
+ * @param i2c_bus NAP_GMBUS_DVOB_DDC/NAP_GMBUS_DVOC_DDC
+ * @param i2c_speed 1000 Khz
+ * @param dab 0x70/0x72
+ * @param reg_list List of i2c indexes and data, terminated with register index
+ * set to PD_REG_LIST_END
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_reg_list_plb(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags)
+{
+ unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+ unsigned long reg_num = 0, ddc_addr = 0, slave_addr = 0;
+
+ if (! gmbus_init(mmio, i2c_bus, i2c_speed)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_init() failed");
+ return 1;
+ }
+ /*If it is SDVO Make sure we issue SDVO command to enable DDC access*/
+ if ((i2c_bus == GMBUS_DVOB_DDC) || (i2c_bus == GMBUS_DVOC_DDC)) {
+ if (i2c_bus == GMBUS_DVOB_DDC) {
+ slave_addr = dvob_port_plb.dab;
+ }else if (i2c_bus == GMBUS_DVOC_DDC) {
+ /* Is DVOC available in PLB? */
+ //slave_addr = dvoc_port_plb.dab;
+ slave_addr = 0;
+ }
+ ddc_addr = 0;
+ if (! gmbus_set_control_bus_switch(mmio, slave_addr, ddc_addr)) {
+ EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_set_control_bus_switch()"
+ " failed");
+ return 1;
+ }
+ while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+ if (! gmbus_write_reg(mmio, dab, reg_list[reg_num].reg,
+ (unsigned char)reg_list[reg_num].value)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_write_reg() failed, reg_num=%lu",
+ reg_num);
+
+ return 1;
+ }
+ reg_num++;
+ }
+ /*...................................................................... */
+ /* Issue a Stop Command */
+ gmbus_wait_event_one(mmio, HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+ gmbus_wait_event_one(mmio, HW_RDY);
+ gmbus_wait_event_zero(mmio, GA);
+ gmbus_error_handler(mmio);
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+ WRITE_GMCH_REG(GMBUS5, 0);
+ WRITE_GMCH_REG(GMBUS0, 0);
+ /*...................................................................... */
+ return 0;
+ }
+ while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+ if (! gmbus_write_reg(mmio, dab, reg_list[reg_num].reg,
+ (unsigned char)reg_list[reg_num].value)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_write_reg() failed, reg_num=%lu",
+ reg_num);
+
+ return 1;
+ }
+
+ reg_num++;
+ }
+
+ return 0;
+}
+
+/*!
+ * gmbus_init initializes the GMBUS controller with specified bus and speed
+ *
+ * @param mmio
+ * @param i2c_bus sDVO B/C Reg/DDC or Analog DDC
+ * @param i2c_speed 50/100/400/1000 Khz
+ *
+ * @return TRUE(1) on success
+ * @return FALSE(0) on failure
+ */
+static int gmbus_init(unsigned char *mmio, unsigned long i2c_bus,
+ unsigned long i2c_speed)
+{
+ gmbus_pins_pair_t pin_pair;
+ gmbus_speed_t bus_speed;
+
+ switch (i2c_bus) {
+
+ case GMBUS_DVO_REG :
+ case GMBUS_DVOB_DDC :
+ case GMBUS_DVOC_DDC :
+ pin_pair = GMBUS_PINS_SDVO;
+ break;
+
+ case GMBUS_ANALOG_DDC :
+ pin_pair = GMBUS_PINS_ANALOG;
+ break;
+
+ case GMBUS_INT_LVDS_DDC :
+ pin_pair = GMBUS_PINS_INT_LVDS;
+ break;
+
+ default :
+ EMGD_ERROR("Error ! gmbus_init : Invalid i2c_bus=0x%lx", i2c_bus);
+ return 0;
+ }
+
+ switch (i2c_speed) {
+
+ case 50 : /* Slow speed */
+ bus_speed = GMBUS_SPEED_50K;
+ break;
+
+ case 400 : /* SPD */
+ bus_speed = GMBUS_SPEED_400K;
+ break;
+
+ case 1000 : /* sDVO Registers */
+ bus_speed = GMBUS_SPEED_1000K;
+ break;
+
+ case 100 : /* DDC */
+ default :
+ bus_speed = GMBUS_SPEED_100K;
+ break;
+ }
+
+ WRITE_GMCH_REG(GMBUS5, 0); /* Clear the word index reg */
+ WRITE_GMCH_REG(GMBUS0, pin_pair | bus_speed);
+
+ return 1;
+}
+
+/*!
+ * gmbus_wait_event_zero waits for specified GMBUS2 register bit to be deasserted
+ *
+ * @param mmio
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was deasserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_zero(unsigned char *mmio, unsigned long bit)
+{
+ unsigned long i;
+ unsigned long status;
+
+ for (i = 0; i < 0x1000; i++) {
+
+ status = READ_GMCH_REG(GMBUS2);
+
+ if ((status & bit) == 0) {
+
+ return 1;
+ }
+ }
+
+ EMGD_DEBUG("Error ! gmbus_wait_event_zero : Failed : bit=0x%lx, status=0x%lx, forcing reset",
+ bit, status);
+
+ /* If we are here, that means that the GBMUS is busy or in a bad
+ * state, the situation was observed
+ * that the GMBUS never becomes available (idle state) after S3.
+ * This results in the driver never being able to set the display.
+ *
+ * To fix this, we force force a reset of the GMBUS.
+ */
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+
+ return 1;
+}
+
+/*!
+ * gmbus_wait_event_one wait for specified GMBUS2 register bits to be asserted
+ *
+ * @param mmio
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was asserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_one(unsigned char *mmio, unsigned long bit)
+{
+ unsigned long i;
+ unsigned long status;
+
+ for (i = 0; i < 0x10000; i++) {
+
+ status = READ_GMCH_REG(GMBUS2);
+ if ((status & bit) != 0) {
+
+ return 1;
+ }
+ }
+
+ EMGD_DEBUG("Error ! gmbus_wait_event_one : Failed : bit=0x%lx, status=0x%lx",
+ bit, status);
+
+ return 0;
+}
+
+/*!
+ * gmbus_error_handler attempts to recover from timeout error
+ *
+ * @param mmio
+ *
+ * @return TRUE(1) error was detected and handled
+ * @return FALSE(0) there was no error
+ */
+static int gmbus_error_handler(unsigned char *mmio)
+{
+ unsigned long status = READ_GMCH_REG(GMBUS2);
+
+ /* Clear the SW_INT, wait for HWRDY and GMBus active (GA) */
+ if ((status & HW_BUS_ERR) || (status & HW_TMOUT)) {
+
+ EMGD_DEBUG("Error ! gmbus_error_handler : Resolving error=0x%lx",
+ status);
+
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+
+ gmbus_wait_event_zero(mmio, GA);
+
+ return 1; /* Handled the error */
+ }
+
+ return 0; /* There was no error */
+}
+
+/*!
+ * Assemble 32 bit GMBUS1 command
+ *
+ * @param slave_addr 0x70/0x72
+ * @param index 0 - 256
+ * @param num_bytes Bytes to transfer
+ * @param flags Bits 25-31 of GMBUS1
+ * @param i2c_dir I2C_READ / I2C_WRITE
+ *
+ * @return The assembled command
+ */
+static unsigned long gmbus_assemble_command(unsigned long slave_addr, unsigned long index,
+ unsigned long num_bytes, unsigned long flags,
+ i2c_bus_dir_t i2c_dir)
+{
+ unsigned long cmd = flags | ENIDX | ENT | (num_bytes << 16) | (index << 8) |
+ slave_addr | i2c_dir;
+
+ return cmd;
+}
+
+/*!
+ * gmbus_send_pkt transmits a block a data to specified i2c slave device
+ *
+ * @param mmio
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in sending the specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_send_pkt(unsigned char *mmio,
+ unsigned long slave_addr, unsigned long index,
+ unsigned long pkt_size, void *pkt)
+{
+ unsigned long gmbus1_cmd;
+ unsigned long bytes_sent;
+ unsigned long *data;
+
+ if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+ return 0;
+ }
+
+ data = (unsigned long *)pkt;
+
+ /*...................................................................... */
+ gmbus_error_handler(mmio);
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+ STA, I2C_WRITE);
+ if (pkt_size <= 4) {
+
+ gmbus1_cmd |= SW_RDY;
+ }
+
+ /*...................................................................... */
+ bytes_sent = 0;
+
+ do {
+
+ WRITE_GMCH_REG(GMBUS3, *data);
+
+ if (bytes_sent == 0) {
+
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+ }
+
+ if (! gmbus_wait_event_one(mmio, HW_RDY)) {
+
+ EMGD_DEBUG("Error ! gmbus_send_pkt : Failed to get HW_RDY, bytes_sent=%ld",
+ bytes_sent);
+
+ return 0;
+ }
+
+ if (gmbus_error_handler(mmio)) {
+
+ EMGD_DEBUG("Error ! gmbus_send_pkt : gmbus error, bytes_sent=%ld",
+ bytes_sent);
+
+ return 0;
+ }
+
+ data++;
+
+ if (pkt_size >= 4) {
+ bytes_sent += 4;
+
+ } else {
+ bytes_sent += pkt_size;
+ }
+
+ } while (bytes_sent < pkt_size);
+
+ /*...................................................................... */
+ if (bytes_sent != pkt_size) {
+
+ return 0;
+
+ } else {
+
+ return 1;
+ }
+}
+
+/*!
+ * gmbus_recv_pkt reads a block of data from specified i2c slave device
+ *
+ * @param mmio
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in receiving specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_recv_pkt(unsigned char *mmio,
+ unsigned long slave_addr, unsigned long index,
+ unsigned long pkt_size, void FAR *pkt)
+{
+ unsigned long gmbus1_cmd;
+ unsigned long bytes_rcvd;
+ unsigned long FAR *data;
+
+ if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+ return 0;
+ }
+
+ data = (unsigned long FAR *)pkt;
+
+ /*...................................................................... */
+ gmbus_error_handler(mmio);
+
+ /* Program the command */
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+ STA | SW_RDY, I2C_READ);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ /*...................................................................... */
+ bytes_rcvd = 0;
+ do {
+
+ unsigned long gmbus3_data;
+ unsigned long bytes_left = pkt_size - bytes_rcvd;
+
+ if (! gmbus_wait_event_one(mmio, HW_RDY)) {
+
+ EMGD_DEBUG("Error ! gmbus_recv_pkt : Failed to get HW_RDY, "
+ "bytes_rcvd=%ld", bytes_rcvd);
+ break;
+ }
+
+ if (gmbus_error_handler(mmio)) {
+
+ EMGD_DEBUG("Error ! gmbus_recv_pkt : gmbus error, bytes_rcvd=%ld",
+ bytes_rcvd);
+ break;
+ }
+
+ gmbus3_data = READ_GMCH_REG(GMBUS3);
+
+ switch (bytes_left) {
+
+ case 1 :
+ *(unsigned char *)data = (unsigned char)gmbus3_data;
+ break;
+
+ case 2 :
+ *(unsigned short *)data = (unsigned short)gmbus3_data;
+ break;
+
+ case 3 :
+ {
+ unsigned char *dest = (unsigned char *)data;
+ unsigned char *src = (unsigned char *)&(gmbus3_data);
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+
+ break;
+ }
+
+ default : /* >= 4 */
+ *data = gmbus3_data;
+ break;
+ }
+
+ if (bytes_left > 4) {
+ bytes_rcvd += 4;
+ data++;
+
+ } else {
+ bytes_rcvd += bytes_left;
+
+ }
+
+ } while (bytes_rcvd < pkt_size);
+
+ /*...................................................................... */
+ if (bytes_rcvd < pkt_size) {
+ return 0;
+
+ } else {
+ return 1;
+ }
+}
+
+/*!
+ * gmbus_set_control_bus_switch sends sDVO command to switch i2c bus to read EDID
+ * or SPD data
+ *
+ * @param mmio
+ * @param slave_addr sDVO device address (0x70/0x72)
+ * @param ddc_addr DDC1_ADDR/DDC2_ADDR
+ *
+ * @return TRUE(1) if successful in sending the opcode
+ * @return FALSE(0) on failure
+ */
+static int gmbus_set_control_bus_switch(unsigned char *mmio,
+ unsigned long slave_addr,
+ gmbus_ddc_addr_t ddc_addr)
+{
+ unsigned char data;
+ sdvo_bus_switch_t bus_switch;
+ int retry;
+
+ bus_switch = SDVO_BUS_DDC1;
+
+ /*...................................................................... */
+ /* Transmit the Arguments */
+ if (! gmbus_send_pkt(mmio, slave_addr, SDVO_INDEX_PARAM_1, 1, &bus_switch)) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt() failed");
+
+ return 0;
+ }
+
+ /*...................................................................... */
+ /* Generate I2C stop cycle */
+ gmbus_wait_event_one(mmio, HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+ gmbus_wait_event_one(mmio, HW_RDY);
+ gmbus_wait_event_zero(mmio, GA);
+
+ /*...................................................................... */
+ /* Transmit the Opcode */
+ data = SDVO_OPCODE_BUS_SWITCH;
+ if (! gmbus_send_pkt(mmio, slave_addr, SDVO_INDEX_OPCODE, 1, &data)) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt(Opcode)"
+ " failed");
+
+ return 0;
+ }
+
+ /*...................................................................... */
+ /* Read Status */
+ for (retry = 0; retry < 3; retry++) {
+ if (! gmbus_recv_pkt(mmio, slave_addr, SDVO_INDEX_STATUS, 1, &data)) {
+
+ continue;
+ }
+
+ if (data != SDVO_STATUS_PENDING) {
+
+ break;
+ }
+ }
+
+ /*...................................................................... */
+ /* Send Stop */
+ gmbus_wait_event_one(mmio, HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+ gmbus_wait_event_one(mmio, HW_RDY);
+ gmbus_wait_event_zero(mmio, GA);
+
+ /*...................................................................... */
+ if (data != SDVO_STATUS_SUCCESS) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : Opcode Bus Switch failed");
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*!
+ * gmbus_read_edid reads specified number of Edid data bytes
+ *
+ * @param mmio
+ * @param ddc_addr 0xA0/0xA2 (DDC1/DDC2)
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC), 0 Analog
+ * @param index i2c register index
+ * @param num_bytes <= 508
+ * @param buffer Edid data read from the display
+ *
+ * @return TRUE(1) if successful in reading Edid
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_edid(unsigned char *mmio,
+ unsigned long ddc_addr,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned long num_bytes,
+ unsigned char FAR *buffer)
+{
+ int status;
+
+ if ((slave_addr == SDVOB_ADDR) || (slave_addr == SDVOC_ADDR)) {
+
+ if (! gmbus_set_control_bus_switch(mmio, slave_addr, ddc_addr)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_set_control_bus_switch()"
+ " failed");
+
+ return 0;
+ }
+ } else {
+ /* Reset the bus */
+ gmbus_recv_pkt(mmio, ddc_addr, 0, 1, buffer);
+ }
+
+ status = gmbus_recv_pkt(mmio, ddc_addr, index, num_bytes, buffer);
+ if (! status) {
+
+ EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_recv_pkt() failed");
+ }
+
+ /*...................................................................... */
+ /* Issue a Stop Command */
+
+ gmbus_wait_event_one(mmio, HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+ gmbus_wait_event_one(mmio, HW_RDY);
+
+ gmbus_wait_event_zero(mmio, GA);
+
+ gmbus_error_handler(mmio);
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+ WRITE_GMCH_REG(GMBUS5, 0);
+ WRITE_GMCH_REG(GMBUS0, 0);
+
+ /*...................................................................... */
+ return status;
+}
+
+/*!
+ * gmbus_read_reg reads one i2c register
+ *
+ * @param mmio
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in reading the i2c register
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_reg(unsigned char *mmio,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned char FAR *data)
+{
+ unsigned long gmbus1_cmd;
+
+ WRITE_GMCH_REG(GMBUS5, 0x0); /* Clear Word Index register */
+
+ if (! gmbus_wait_event_zero(mmio, GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(1)");
+
+ return 0;
+ }
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+ STO | STA, I2C_READ);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ if (! gmbus_wait_event_zero(mmio, GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(2)");
+
+ return 0;
+ }
+
+ *data = (unsigned char)READ_GMCH_REG(GMBUS3);
+
+ return 1;
+}
+
+/*!
+ * gmbus_write_reg writes one i2c register
+ *
+ * @param mmio
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in updating the i2c register
+ * @return FALSE(0) if failed to update the register
+ */
+static int gmbus_write_reg(unsigned char *mmio,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned char data)
+{
+ unsigned long gmbus1_cmd;
+
+ WRITE_GMCH_REG(GMBUS5, 0x0); /* Clear Word Index register */
+
+ if (! gmbus_wait_event_zero(mmio, GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(1)");
+
+ return 0;
+ }
+
+ WRITE_GMCH_REG(GMBUS3, data);
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+ STO | STA, I2C_WRITE);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ if (! gmbus_wait_event_zero(mmio, GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(2)");
+ return 0;
+ }
+
+ return 1;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
new file mode 100644
index 0000000..427aa29
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
@@ -0,0 +1,599 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_bitbash_tnc.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Bitbash to read GPIO pins are done on LPC device 0:31:0. So do not
+ * use EMGD_READ32 and EMGD_WRITE32 macros for read/write to device 31. These
+ * macros do mmio only on device2.
+ * To properly read/write mmio on device 31, use
+ * READ_MMIO_REG_TNC(port_type, reg) and
+ * WRITE_MMIO_REG_TNC(port_type, reg, data).
+ * These macros properly set to work for all OSes including VBIOS, but
+ * generate more code compared to EMGD_READ32 and EMGD_WRITE32. So use as
+ * necessary.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+
+#include <intelpci.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+static int i2c_error_recovery_tnc(
+ unsigned long hold_time);
+
+static int i2c_write_byte_tnc(
+ unsigned char value,
+ unsigned long hold_time);
+
+static int i2c_read_byte_tnc(
+ unsigned char *value,
+ unsigned char ack,
+ unsigned long hold_time);
+
+int i2c_read_regs_gpio(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags);
+
+int i2c_write_reg_list_gpio(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags);
+
+/* The LVDS GPIO clock lines are GPIOSUS[3]
+ * The LVDS GPIO data lines are GPIOSUS[4]
+ */
+#define GPIO_CLOCK 0x08
+#define GPIO_DATA 0x10
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+#if 0
+static void enable_gpio_tnc(igd_context_t *context)
+{
+ /*
+ * NOTE: This really should be a system BIOS job.
+ * The driver would not touch these register anymore since
+ * it would cause the 13x7 panel fail to start.
+ */
+
+ /* Enabling LVDS Data and LVDS Clock */
+ unsigned long temp;
+
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGEN);
+ temp |= (GPIO_DATA | GPIO_CLOCK);
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGEN, temp);
+
+ return;
+}
+#endif
+
+/*!
+ *
+ * @param clock
+ * @param data
+ *
+ * @return void
+ */
+static void i2c_get(unsigned long *clock,
+ unsigned long *data)
+{
+ unsigned long temp;
+ /* Set Data as Input */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+ temp |= (GPIO_DATA);
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+ /* Read Data */
+ *data = (READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL) & GPIO_DATA) ? 1:0;
+ *clock = (READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL) & GPIO_CLOCK) ? 1:0;
+
+#if 0
+ EMGD_WRITE32(0, EMGD_MMIO(mmio) + i2c_bus);
+ c = EMGD_READ32(EMGD_MMIO(mmio) + i2c_bus)>>4;
+ *data = (c>>8) & 1;
+ *clock &= 1;
+#endif
+}
+
+/*!
+ *
+ * @param data
+ * @param hold_time
+ *
+ * @return void
+ */
+static void i2c_set_data(int data,
+ unsigned long hold_time)
+{
+ unsigned long temp;
+ /* The LVDS GPIO data lines are GPIOSUS[4] */
+ /* Set as Output */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+ temp &= ~GPIO_DATA;
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+ /* Read status register */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL);
+
+ if(data){
+ /* Set level to High */
+ temp |= GPIO_DATA;
+ } else {
+ /* Set level to low */
+ temp &= ~GPIO_DATA;
+ }
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL, temp);
+
+ OS_DELAY(hold_time);
+
+#if 0
+ /* Implementation using Display GPIO
+ * For alm, the default data value "could" be 0
+ */
+ /*
+ * Simplified definition for the bits
+ * 11: GPIO data Value
+ * 10: GPIO Data Mask
+ * 9: GPIO Data Direction Value
+ * 8: GPIO Data Direction Mask
+ */
+ EMGD_WRITE32(data ? 0x500 : 0x700, EMGD_MMIO(mmio) + i2c_bus);
+ EMGD_WRITE32(data ? 0x400 : 0x600, EMGD_MMIO(mmio) + i2c_bus);
+ OS_DELAY(hold_time);
+#endif
+}
+
+/*!
+ *
+ * @param clock
+ * @param hold_time
+ *
+ * @return void
+ */
+static void i2c_set_clock(int clock,
+ unsigned long hold_time)
+{
+ unsigned long temp;
+ /* The LVDS GPIO clock lines are GPIOSUS[3] */
+ /* Set as Output */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+ temp &= ~GPIO_CLOCK;
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+ /* Read Status Register */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL);
+
+ if(clock){
+ /* Set level to High */
+ temp |= GPIO_CLOCK;
+
+ } else {
+ /* Set level to low */
+ temp &= ~GPIO_CLOCK;
+ }
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL, temp);
+
+ OS_DELAY(hold_time);
+
+#if 0
+ /*
+ * Simplified definition for the bits
+ * 3: GPIO Clock Value
+ * 2: GPIO Clock Mask
+ * 1: GPIO Clock Direction Value
+ * 0: GPIO Clock Direction Mask
+ */
+
+ EMGD_WRITE32(clock ? 0x5 : 0x7, EMGD_MMIO(mmio) + i2c_bus);
+ EMGD_WRITE32(clock ? 0x4 : 0x6, EMGD_MMIO(mmio) + i2c_bus);
+ OS_DELAY(hold_time);
+#endif
+}
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_start_tnc(unsigned long hold_time)
+{
+ unsigned long sc, sd;
+
+ /* set sd high */
+ i2c_set_data(1, hold_time);
+
+ /* set clock high */
+ i2c_set_clock(1, hold_time);
+
+ /* Start condition happens when sd goes high to low when sc is high */
+ i2c_get(&sc, &sd);
+
+ if( 0 == sc ) {
+ // Data must be high
+ i2c_error_recovery_tnc(hold_time);
+ return 1;
+ }
+
+ i2c_set_data(0, hold_time);
+ i2c_set_clock(0, hold_time);
+
+ return 0;
+} /* end i2c_start */
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0
+ */
+static int i2c_stop_tnc(unsigned long hold_time)
+{
+ /* Stop condition happens when sd goes low to high when sc is high */
+ unsigned long sc,sd;
+
+ i2c_set_clock(0, hold_time);
+ i2c_set_data(0, hold_time);
+
+ i2c_set_clock(1, hold_time);
+
+ i2c_get(&sc, &sd);
+ /* Try another time */
+ if (sc == 0) {
+ i2c_set_clock(1, hold_time);
+ }
+ i2c_set_data(1, hold_time);
+
+ return 0;
+} /* end i2c_stop */
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_error_recovery_tnc(unsigned long hold_time)
+{
+ unsigned char max_retries = 9;
+ unsigned long sc, sd;
+
+ while (max_retries--) {
+ i2c_get(&sc, &sd);
+ if (sd == 1 && sc == 1) {
+ return 0;
+ } else {
+ i2c_stop_tnc(hold_time);
+ }
+ }
+ EMGD_ERROR("Cannot recover I2C error.");
+
+ return 1;
+}
+
+/*!
+ *
+ * @param value
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_byte_tnc(unsigned char value,
+ unsigned long hold_time)
+{
+ int i;
+ unsigned long sc,sd;
+
+ /* I2C_DEBUG("i2c_write_byte"); */
+ for(i=7; i>=0; i--) {
+ i2c_set_clock(0, hold_time);
+ i2c_set_data(value>>i & 1, hold_time);
+
+ i2c_set_clock(1, hold_time);
+ }
+
+ /* Get ACK */
+ i2c_set_clock(0, hold_time);
+ /* Set data low. Possible inteference in some lvds panel */
+ i2c_set_data(0, hold_time);
+ i2c_set_clock(1, hold_time);
+ OS_DELAY(hold_time);
+
+ i2c_get(&sc, &sd);
+
+ i2c_set_clock(0, hold_time);
+
+ if (sd != 0) {
+ EMGD_ERROR("No ACK for byte 0x%x", value);
+ i2c_error_recovery_tnc(hold_time);
+ return 1;
+ }
+
+ return 0;
+
+} /* end i2c_write_byte */
+
+/*!
+ *
+ * @param value
+ * @param ack
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_byte_tnc(unsigned char *value,
+ unsigned char ack,
+ unsigned long hold_time)
+{
+ int i;
+ unsigned long sc, sd, temp;
+
+ *value = 0;
+ for(i=7; i>=0; i--) {
+ i2c_set_clock(1, hold_time);
+ i2c_get(&sc, &sd);
+ OS_DELAY(hold_time);
+ if(!sc) {
+ EMGD_DEBUG("Clock low on read %d", i);
+ i2c_error_recovery_tnc(hold_time);
+ return 1;
+ }
+ *value |= (sd & 1)<<i;
+ i2c_set_clock(0, hold_time);
+ }
+
+ if (ack) {
+ i2c_set_data(0, hold_time);
+ }
+
+ /* Master does not ACK */
+ i2c_set_clock(1, hold_time);
+ i2c_set_clock(0, hold_time);
+
+ if (ack) {
+ /* Set data as input as we continue to read */
+ temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+ temp |= GPIO_DATA;
+ WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+ }
+
+ return 0;
+} /* end i2c_read_byte */
+
+/*!
+ *
+ * @param context
+ * @param i2c_bus
+ * @param i2c_speed
+ * @param dab
+ * @param reg
+ * @param buffer
+ * @param num_bytes
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int i2c_read_regs_gpio(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags
+ )
+{
+ unsigned long hold_time;
+ unsigned char temp;
+ int i;
+ if (!i2c_speed) {
+ EMGD_DEBUG("i2c Speed failed.");
+ return 1;
+ }
+
+ /*
+ * We are holding the clock LOW for "hold_time" and then HIGH for
+ * "hold_time". Therefore, we double the clock speed in this calculation.
+ */
+ if (flags & IGD_I2C_WRITE_FW){
+ hold_time = 1;
+ } else {
+ hold_time = 1000/(i2c_speed * 2);
+ }
+
+ /* enable_gpio_tnc(context); */
+
+ if (i2c_start_tnc(hold_time)) {
+ EMGD_DEBUG("i2c Start failed.");
+ return 1;
+ }
+
+ if (i2c_write_byte_tnc((unsigned char)dab & 0xFE,
+ hold_time)) {
+ EMGD_DEBUG("i2c DAB(W) failed.");
+ return 1;
+ }
+
+ if (i2c_write_byte_tnc(reg, hold_time)) {
+ EMGD_DEBUG("RAB failed.");
+ return 1;
+ }
+
+ if (i2c_start_tnc(hold_time)) {
+ EMGD_DEBUG("i2c ReStart failed");
+ return 1;
+ }
+
+ if (i2c_write_byte_tnc((unsigned char)dab | 0x01,
+ hold_time)) {
+ EMGD_ERROR("i2c DAB(R) failed");
+ return 1;
+ }
+
+
+ /* Read the requested number of bytes */
+ for(i=0; i<(int)(num_bytes-1); i++) {
+ /*
+ * Use a local temp so that the FAR pointer doesn't have to
+ * get passed down.
+ */
+ if (i2c_read_byte_tnc(&temp, 1, hold_time)) {
+ EMGD_DEBUG("Read data byte %d failed", i);
+ EMGD_DEBUG("Exit i2c_read_regs_tnc with error");
+ return 1;
+ }
+ buffer[i] = temp;
+ }
+
+ /* No ACK on the last read */
+ if(i2c_read_byte_tnc(&temp, 0, hold_time)) {
+ EMGD_DEBUG("Read Data %d Failed", i);
+ EMGD_DEBUG("Exit i2c_read_regs_tnc with error");
+ return 1;
+ }
+ buffer[i] = temp;
+
+ i2c_stop_tnc(hold_time);
+ i2c_stop_tnc(hold_time);
+
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param i2c_bus
+ * @param i2c_speed
+ * @param dab
+ * @param reg_list
+ * @param flags
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int i2c_write_reg_list_gpio(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags)
+{
+ unsigned long hold_time;
+
+ if (!i2c_speed) {
+ return 1;
+ }
+
+ /*
+ * We are holding the clock LOW for "hold_time" and then HIGH for
+ * "hold_time". Therefore, we double the clock speed in this calculation.
+ */
+ if (flags & IGD_I2C_WRITE_FW){
+ hold_time = 1;
+ } else {
+ hold_time = 1000/(i2c_speed * 2);
+ }
+
+ /* enable_gpio_tnc(context); */
+
+ while(reg_list->reg != PD_REG_LIST_END) {
+ if (i2c_start_tnc(hold_time)) {
+ EMGD_DEBUG("Start failed");
+ return 1;
+ }
+
+ if (i2c_write_byte_tnc((unsigned char)dab & 0xFE,
+ hold_time)) {
+ EMGD_DEBUG("DAB(W) failed");
+ return 1;
+ }
+
+ /* Register Address */
+ if (i2c_write_byte_tnc((unsigned char)reg_list->reg, hold_time)) {
+ EMGD_DEBUG("RAB failed");
+ return 1;
+ }
+
+ do {
+ /* New Value */
+ if (i2c_write_byte_tnc((unsigned char)reg_list->value, hold_time)) {
+ EMGD_DEBUG("Data failed");
+ return 1;
+ }
+
+ if(reg_list[1].reg != (reg_list[0].reg + 1)) {
+ reg_list++;
+ break;
+ }
+
+ EMGD_DEBUG("I2C Multi-Write Reg[%x] = 0x%x",
+ (unsigned short)reg_list->reg,
+ (unsigned short)reg_list->value);
+ reg_list++;
+ } while(flags & IGD_I2C_SERIAL_WRITE);
+
+
+ i2c_stop_tnc(hold_time);
+ i2c_stop_tnc(hold_time);
+ }
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
new file mode 100644
index 0000000..ed8cbb9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
@@ -0,0 +1,929 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_gmbus_tnc.c
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*......................................................................... */
+extern igd_display_port_t dvob_port_tnc;
+
+/*......................................................................... */
+static int i2c_read_regs_tnc(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags);
+
+static int i2c_write_reg_list_tnc(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags);
+
+i2c_dispatch_t i2c_dispatch_tnc = {
+ i2c_read_regs_tnc,
+ i2c_write_reg_list_tnc,
+};
+
+
+/*.......................................................................... */
+typedef enum {
+
+ GMBUS_SPEED_50K = 0x0100,
+ GMBUS_SPEED_100K = 0x0000,
+ GMBUS_SPEED_400K = 0x0200,
+ GMBUS_SPEED_1000K = 0x0300,
+
+} gmbus_speed_t;
+
+typedef enum {
+
+ SDVOB_ADDR = 0x70,
+
+} sdvo_dev_addr_t;
+
+typedef enum {
+
+ DDC1_ADDR = 0xA0,
+ DDC2_ADDR = 0xA2,
+
+} gmbus_ddc_addr_t;
+
+
+typedef enum {
+
+ GMBUS_PINS_DEDICATED = 1, /* Dedicated Control/GMBUS Pins */
+ GMBUS_PINS_SDVO = 5, /* SDVO Registers, DDC, PROM */
+
+} gmbus_pins_pair_t;
+
+
+typedef enum {
+
+ I2C_WRITE = 0,
+ I2C_READ = 1,
+
+} i2c_bus_dir_t;
+
+/*.......................................................................... */
+typedef enum {
+
+ SDVO_BUS_PROM = BIT(0),
+ SDVO_BUS_DDC1 = BIT(1),
+ SDVO_BUS_DDC2 = BIT(2),
+
+} sdvo_bus_switch_t;
+
+#define SDVO_OPCODE_BUS_SWITCH 0x7A
+
+#define SDVO_INDEX_PARAM_1 0x07
+#define SDVO_INDEX_OPCODE 0x08
+#define SDVO_INDEX_STATUS 0x09
+
+#define SDVO_STATUS_SUCCESS 0x01
+#define SDVO_STATUS_PENDING 0x04
+
+/*.......................................................................... */
+/*
+ * In 16-bit, the mmio is a 16-bit pointer, the watcom 1.2 compiler will have
+ * error if directly convert it to unsigned long. Normally, have to cast it to
+ * unsigned short first then cast again to unsigned long; then, it will be
+ * correct. But this type of casting may cause some error in the 32 and 64 bit
+ * code. Since mmio will be equal to zero for 16-bit code. Add the checking
+ * for MICRO definition code to correct the macro by remove mmio.
+ */
+#define READ_GMCH_REG(reg) READ_MMIO_REG_TNC(IGD_PORT_SDVO, reg)
+#define WRITE_GMCH_REG(reg, data) WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, reg, data)
+
+static int gmbus_init(unsigned long i2c_bus,
+ unsigned long i2c_speed);
+
+static int gmbus_read_edid(unsigned long ddc_addr,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned long num_bytes,
+ unsigned char FAR *buffer);
+
+static int gmbus_read_reg(unsigned long slave_addr,
+ unsigned long index,
+ unsigned char FAR *data);
+
+static int gmbus_write_reg(unsigned long slave_addr,
+ unsigned long index,
+ unsigned char data);
+
+static int gmbus_set_control_bus_switch(unsigned long slave_addr,
+ gmbus_ddc_addr_t ddc_addr);
+
+static int gmbus_wait_event_one(unsigned long bit);
+static int gmbus_wait_event_zero(unsigned long bit);
+static int gmbus_error_handler(void);
+
+/*.......................................................................... */
+extern int i2c_read_regs_gpio(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags);
+
+extern int i2c_write_reg_list_gpio(
+ igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags);
+
+
+/*!
+ * i2c_read_regs_tnc is called to read Edid or a single sDVO register
+ *
+ * @param context
+ * @param i2c_bus port->ddc_reg, port->i2c_reg
+ * @param i2c_speed 50, 100, 400, 1000 (Khz)
+ * @param dab 0x70/0x72 (sDVO Regs), 0xA0/0xA2 (sDVO/Analog DDC)
+ * @param reg I2C Reg Index
+ * @param num_bytes <= 508
+ * @param buffer Data read
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_regs_tnc(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ unsigned char reg,
+ unsigned char FAR *buffer,
+ unsigned long num_bytes,
+ unsigned long flags)
+{
+ unsigned long slave_addr = 0;
+
+ if(i2c_bus == I2C_INT_LVDS_DDC){
+ /*
+ * Atom E6xx LVDS does not have GMBUS support. To read DDC register, we bit bash.
+ * The i2c_speed is necessary to calculate the hold time. But i2c_bus is not needed.
+ */
+
+ EMGD_DEBUG("i2c_read_regs_tnc : Using GPIO to read DDC");
+ return i2c_read_regs_gpio(context, i2c_bus, i2c_speed, dab, reg, buffer, num_bytes, flags);
+
+ } else {
+
+ if (! gmbus_init(i2c_bus, i2c_speed)) {
+ EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_init() failed");
+ return 1;
+ }
+
+ /* If the request is to read Edid from sDVO display, find out the */
+ /* i2c addres of the sDVO device */
+ if (i2c_bus == GMBUS_DVOB_DDC) {
+ slave_addr = dvob_port_tnc.dab;
+ }
+
+ switch (i2c_bus) {
+ case GMBUS_DVOB_DDC :
+ if (! gmbus_read_edid(dab, slave_addr, reg, num_bytes, buffer)) {
+
+ EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_read_edid() failed");
+ return 1;
+ }
+ break;
+
+ case GMBUS_DVO_REG :
+ if (! gmbus_read_reg(dab, reg, buffer)) {
+
+ EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_read_reg() failed");
+ return 1;
+ }
+ break;
+
+ default :
+ EMGD_ERROR("Error ! i2c_read_regs_tnc : Invalid i2c_bus=0x%lx",
+ i2c_bus);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * i2c_write_reg_list_tnc is called to write a list of i2c registers to sDVO
+ * device
+ *
+ * @param context
+ * @param i2c_bus NAP_GMBUS_DVOB_DDC/NAP_GMBUS_DVOC_DDC
+ * @param i2c_speed 1000 Khz
+ * @param dab 0x70/0x72
+ * @param reg_list List of i2c indexes and data, terminated with register index
+ * set to PD_REG_LIST_END
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_reg_list_tnc(igd_context_t *context,
+ unsigned long i2c_bus,
+ unsigned long i2c_speed,
+ unsigned long dab,
+ pd_reg_t *reg_list,
+ unsigned long flags)
+{
+ unsigned long reg_num = 0, ddc_addr = 0, slave_addr = 0;
+
+ if(i2c_bus == I2C_INT_LVDS_DDC){
+ /* There are no GMBUS pins for internal LVDS on Atom E6xx.
+ * Forcing us to use bit bashing */
+ /* FIXME: determine which GPIO pin is used for bit bashing
+ * i2c_bus is not defined
+ */
+ EMGD_DEBUG("i2c_write_reg_list_tnc : Using GPIO to write DDC");
+ return i2c_write_reg_list_gpio(context, i2c_bus, i2c_speed, dab, reg_list, flags);
+
+ } else {
+
+ if (! gmbus_init(i2c_bus, i2c_speed)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_init() failed");
+ return 1;
+ }
+ /*If it is SDVO Make sure we issue SDVO command to enable DDC access*/
+ if (i2c_bus == GMBUS_DVOB_DDC) {
+ slave_addr = dvob_port_tnc.dab;
+ ddc_addr = 0;
+
+ if (! gmbus_set_control_bus_switch(slave_addr, ddc_addr)) {
+ EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_set_control_bus_switch()"
+ " failed");
+ return 1;
+ }
+ while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+ if (! gmbus_write_reg(dab, reg_list[reg_num].reg,
+ (unsigned char)reg_list[reg_num].value)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_write_reg() failed, reg_num=%lu",
+ reg_num);
+
+ return 1;
+ }
+ reg_num++;
+ }
+ /*...................................................................... */
+ /* Issue a Stop Command */
+ gmbus_wait_event_one(HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+ gmbus_wait_event_one(HW_RDY);
+ gmbus_wait_event_zero(GA);
+ gmbus_error_handler();
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+ WRITE_GMCH_REG(GMBUS5, 0);
+ WRITE_GMCH_REG(GMBUS0, 0);
+ /*...................................................................... */
+ return 0;
+ }
+ while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+ if (! gmbus_write_reg(dab, reg_list[reg_num].reg,
+ (unsigned char)reg_list[reg_num].value)) {
+
+ EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_write_reg() failed, reg_num=%lu",
+ reg_num);
+
+ return 1;
+ }
+
+ reg_num++;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * gmbus_init initializes the GMBUS controller with specified bus and speed
+ *
+ * @param i2c_bus sDVO B/C Reg/DDC or Analog DDC
+ * @param i2c_speed 50/100/400/1000 Khz
+ *
+ * @return TRUE(1) on success
+ * @return FALSE(0) on failure
+ */
+static int gmbus_init(unsigned long i2c_bus,
+ unsigned long i2c_speed)
+{
+ gmbus_pins_pair_t pin_pair;
+ gmbus_speed_t bus_speed;
+
+ switch (i2c_bus) {
+
+ case GMBUS_DVO_REG :
+ case GMBUS_DVOB_DDC :
+ pin_pair = GMBUS_PINS_SDVO;
+ break;
+
+ default :
+ EMGD_ERROR("Error ! gmbus_init : Invalid i2c_bus=0x%lx", i2c_bus);
+ return 0;
+ }
+
+ switch (i2c_speed) {
+
+ case 50 : /* Slow speed */
+ bus_speed = GMBUS_SPEED_50K;
+ break;
+
+ case 400 : /* SPD */
+ bus_speed = GMBUS_SPEED_400K;
+ break;
+
+ case 1000 : /* sDVO Registers */
+ //bus_speed = GMBUS_SPEED_1000K;
+ bus_speed = GMBUS_SPEED_400K;
+ break;
+
+ case 100 : /* DDC */
+ default :
+ bus_speed = GMBUS_SPEED_100K;
+ break;
+ }
+
+ WRITE_GMCH_REG(GMBUS5, 0); /* Clear the word index reg */
+ WRITE_GMCH_REG(GMBUS0, pin_pair | bus_speed);
+
+ return 1;
+}
+
+/*!
+ * gmbus_wait_event_zero waits for specified GMBUS2 register bit to be deasserted
+ *
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was deasserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_zero(unsigned long bit)
+{
+ unsigned long i;
+ unsigned long status;
+
+ for (i = 0; i < 0x1000; i++) {
+
+ status = READ_GMCH_REG(GMBUS2);
+
+ if ((status & bit) == 0) {
+
+ return 1;
+ }
+ }
+
+ EMGD_DEBUG("Error ! gmbus_wait_event_zero : Failed : bit=0x%lx, status=0x%lx",
+ bit, status);
+
+ return 0;
+}
+
+/*!
+ * gmbus_wait_event_one wait for specified GMBUS2 register bits to be asserted
+ *
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was asserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_one(unsigned long bit)
+{
+ unsigned long i;
+ unsigned long status;
+
+ for (i = 0; i < 0x10000; i++) {
+
+ status = READ_GMCH_REG(GMBUS2);
+ if ((status & bit) != 0) {
+
+ return 1;
+ }
+ }
+
+ EMGD_DEBUG("Error ! gmbus_wait_event_one : Failed : bit=0x%lx, status=0x%lx",
+ bit, status);
+
+ return 0;
+}
+
+/*!
+ * gmbus_error_handler attempts to recover from timeout error
+ *
+ *
+ * @return TRUE(1) error was detected and handled
+ * @return FALSE(0) there was no error
+ */
+static int gmbus_error_handler(void)
+{
+ unsigned long status = READ_GMCH_REG(GMBUS2);
+
+ /* Clear the SW_INT, wait for HWRDY and GMBus active (GA) */
+ if ((status & HW_BUS_ERR) || (status & HW_TMOUT)) {
+
+ EMGD_DEBUG("Error ! gmbus_error_handler : Resolving error=0x%lx",
+ status);
+
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+
+ gmbus_wait_event_zero(GA);
+
+ return 1; /* Handled the error */
+ }
+
+ return 0; /* There was no error */
+}
+
+/*!
+ * Assemble 32 bit GMBUS1 command
+ *
+ * @param slave_addr 0x70/0x72
+ * @param index 0 - 256
+ * @param num_bytes Bytes to transfer
+ * @param flags Bits 25-31 of GMBUS1
+ * @param i2c_dir I2C_READ / I2C_WRITE
+ *
+ * @return The assembled command
+ */
+static unsigned long gmbus_assemble_command(unsigned long slave_addr, unsigned long index,
+ unsigned long num_bytes, unsigned long flags,
+ i2c_bus_dir_t i2c_dir)
+{
+ unsigned long cmd = flags | ENIDX | ENT | (num_bytes << 16) | (index << 8) |
+ slave_addr | i2c_dir;
+
+ return cmd;
+}
+
+/*!
+ * gmbus_send_pkt transmits a block a data to specified i2c slave device
+ *
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in sending the specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_send_pkt(unsigned long slave_addr, unsigned long index,
+ unsigned long pkt_size, void *pkt)
+{
+ unsigned long gmbus1_cmd;
+ unsigned long bytes_sent;
+ unsigned long *data;
+
+ if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+ return 0;
+ }
+
+ data = (unsigned long *)pkt;
+
+ /*...................................................................... */
+ gmbus_error_handler();
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+ STA, I2C_WRITE);
+ if (pkt_size <= 4) {
+
+ gmbus1_cmd |= SW_RDY;
+ }
+
+ /*...................................................................... */
+ bytes_sent = 0;
+
+ do {
+
+ WRITE_GMCH_REG(GMBUS3, *data);
+
+ if (bytes_sent == 0) {
+
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+ }
+
+ if (! gmbus_wait_event_one(HW_RDY)) {
+
+ EMGD_DEBUG("Error ! gmbus_send_pkt : Failed to get HW_RDY, bytes_sent=%ld",
+ bytes_sent);
+
+ return 0;
+ }
+
+ if (gmbus_error_handler()) {
+
+ EMGD_DEBUG("Error ! gmbus_send_pkt : gmbus error, bytes_sent=%ld",
+ bytes_sent);
+
+ return 0;
+ }
+
+ data++;
+
+ if (pkt_size >= 4) {
+ bytes_sent += 4;
+
+ } else {
+ bytes_sent += pkt_size;
+ }
+
+ } while (bytes_sent < pkt_size);
+
+ /*...................................................................... */
+ if (bytes_sent != pkt_size) {
+
+ return 0;
+
+ } else {
+
+ return 1;
+ }
+}
+
+/*!
+ * gmbus_recv_pkt reads a block of data from specified i2c slave device
+ *
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in receiving specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_recv_pkt(unsigned long slave_addr, unsigned long index,
+ unsigned long pkt_size, void FAR *pkt)
+{
+ unsigned long gmbus1_cmd;
+ unsigned long bytes_rcvd;
+ unsigned long FAR *data;
+
+ if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+ return 0;
+ }
+
+ data = (unsigned long FAR *)pkt;
+
+ /*...................................................................... */
+ gmbus_error_handler();
+
+ /* Program the command */
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+ STA | SW_RDY, I2C_READ);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ /*...................................................................... */
+ bytes_rcvd = 0;
+ do {
+
+ unsigned long gmbus3_data;
+ unsigned long bytes_left = pkt_size - bytes_rcvd;
+
+ if (! gmbus_wait_event_one(HW_RDY)) {
+
+ EMGD_DEBUG("Error ! gmbus_recv_pkt : Failed to get HW_RDY, "
+ "bytes_rcvd=%ld", bytes_rcvd);
+ break;
+ }
+
+ if (gmbus_error_handler()) {
+
+ EMGD_DEBUG("Error ! gmbus_recv_pkt : gmbus error, bytes_rcvd=%ld",
+ bytes_rcvd);
+ break;
+ }
+
+ gmbus3_data = READ_GMCH_REG(GMBUS3);
+
+ switch (bytes_left) {
+
+ case 1 :
+ *(unsigned char *)data = (unsigned char)gmbus3_data;
+ break;
+
+ case 2 :
+ *(unsigned short *)data = (unsigned short)gmbus3_data;
+ break;
+
+ case 3 :
+ {
+ unsigned char *dest = (unsigned char *)data;
+ unsigned char *src = (unsigned char *)&(gmbus3_data);
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+
+ break;
+ }
+
+ default : /* >= 4 */
+ *data = gmbus3_data;
+ break;
+ }
+
+ if (bytes_left > 4) {
+ bytes_rcvd += 4;
+ data++;
+
+ } else {
+ bytes_rcvd += bytes_left;
+
+ }
+
+ } while (bytes_rcvd < pkt_size);
+
+ /*...................................................................... */
+ if (bytes_rcvd < pkt_size) {
+ return 0;
+
+ } else {
+ return 1;
+ }
+}
+
+/*!
+ * gmbus_set_control_bus_switch sends sDVO command to switch i2c bus to read EDID
+ * or SPD data
+ *
+ * @param slave_addr sDVO device address (0x70/0x72)
+ * @param ddc_addr DDC1_ADDR/DDC2_ADDR
+ *
+ * @return TRUE(1) if successful in sending the opcode
+ * @return FALSE(0) on failure
+ */
+static int gmbus_set_control_bus_switch(unsigned long slave_addr,
+ gmbus_ddc_addr_t ddc_addr)
+{
+ unsigned char data;
+ sdvo_bus_switch_t bus_switch;
+ int retry;
+
+ bus_switch = SDVO_BUS_DDC1;
+
+ /*...................................................................... */
+ /* Transmit the Arguments */
+ if (! gmbus_send_pkt(slave_addr, SDVO_INDEX_PARAM_1, 1, &bus_switch)) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt() failed");
+
+ return 0;
+ }
+
+ /*...................................................................... */
+ /* Generate I2C stop cycle */
+ gmbus_wait_event_one(HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+ gmbus_wait_event_one(HW_RDY);
+ gmbus_wait_event_zero(GA);
+
+ /*...................................................................... */
+ /* Transmit the Opcode */
+ data = SDVO_OPCODE_BUS_SWITCH;
+ if (! gmbus_send_pkt(slave_addr, SDVO_INDEX_OPCODE, 1, &data)) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt(Opcode)"
+ " failed");
+
+ return 0;
+ }
+
+ /*...................................................................... */
+ /* Read Status */
+ for (retry = 0; retry < 3; retry++) {
+ if (! gmbus_recv_pkt(slave_addr, SDVO_INDEX_STATUS, 1, &data)) {
+
+ continue;
+ }
+
+ if (data != SDVO_STATUS_PENDING) {
+
+ break;
+ }
+ }
+
+ /*...................................................................... */
+ /* Send Stop */
+ gmbus_wait_event_one(HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+ gmbus_wait_event_one(HW_RDY);
+ gmbus_wait_event_zero(GA);
+
+ /*...................................................................... */
+ if (data != SDVO_STATUS_SUCCESS) {
+
+ EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : Opcode Bus Switch failed");
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*!
+ * gmbus_read_edid reads specified number of Edid data bytes
+ *
+ * @param ddc_addr 0xA0/0xA2 (DDC1/DDC2)
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC), 0 Analog
+ * @param index i2c register index
+ * @param num_bytes <= 508
+ * @param buffer Edid data read from the display
+ *
+ * @return TRUE(1) if successful in reading Edid
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_edid(unsigned long ddc_addr,
+ unsigned long slave_addr,
+ unsigned long index,
+ unsigned long num_bytes,
+ unsigned char FAR *buffer)
+{
+ int status;
+
+ if (slave_addr == SDVOB_ADDR) {
+
+ if (! gmbus_set_control_bus_switch(slave_addr, ddc_addr)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_set_control_bus_switch()"
+ " failed");
+
+ return 0;
+ }
+ } else {
+ /* Reset the bus */
+ gmbus_recv_pkt(ddc_addr, 0, 1, buffer);
+ }
+
+ status = gmbus_recv_pkt(ddc_addr, index, num_bytes, buffer);
+ if (! status) {
+
+ EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_recv_pkt() failed");
+ }
+
+ /*...................................................................... */
+ /* Issue a Stop Command */
+
+ gmbus_wait_event_one(HW_WAIT);
+ WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+ gmbus_wait_event_one(HW_RDY);
+
+ gmbus_wait_event_zero(GA);
+
+ gmbus_error_handler();
+ WRITE_GMCH_REG(GMBUS1, SW_RDY);
+ WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+ WRITE_GMCH_REG(GMBUS1, 0);
+ WRITE_GMCH_REG(GMBUS5, 0);
+ WRITE_GMCH_REG(GMBUS0, 0);
+
+ /*...................................................................... */
+ return status;
+}
+
+/*!
+ * gmbus_read_reg reads one i2c register
+ *
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in reading the i2c register
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_reg(unsigned long slave_addr,
+ unsigned long index,
+ unsigned char FAR *data)
+{
+ unsigned long gmbus1_cmd;
+
+ WRITE_GMCH_REG(GMBUS5, 0x0); /* Clear Word Index register */
+
+ if (! gmbus_wait_event_zero(GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(1)");
+
+ return 0;
+ }
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+ STO | STA, I2C_READ);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ if (! gmbus_wait_event_zero(GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(2)");
+
+ return 0;
+ }
+
+ *data = (unsigned char)READ_GMCH_REG(GMBUS3);
+
+ return 1;
+}
+
+/*!
+ * gmbus_write_reg writes one i2c register
+ *
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in updating the i2c register
+ * @return FALSE(0) if failed to update the register
+ */
+static int gmbus_write_reg(unsigned long slave_addr,
+ unsigned long index,
+ unsigned char data)
+{
+ unsigned long gmbus1_cmd;
+
+ WRITE_GMCH_REG(GMBUS5, 0x0); /* Clear Word Index register */
+
+ if (! gmbus_wait_event_zero(GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(1)");
+
+ return 0;
+ }
+
+ WRITE_GMCH_REG(GMBUS3, data);
+
+ gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+ STO | STA, I2C_WRITE);
+ WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+ if (! gmbus_wait_event_zero(GA)) {
+
+ EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(2)");
+ return 0;
+ }
+
+ return 1;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h b/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
new file mode 100644
index 0000000..d6d6819
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
@@ -0,0 +1,176 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: drm_emgd_private.h
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the EMGD-specific drm_device.dev_private structure,
+ * which is used to share data with the EMGD-specific, IMG 3rd-Party Display
+ * Driver (3DD, implimented in the
+ * "egd_drm/pvr/services4/3rdparty/emgd_displayclass" directory).
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _DRM_EMGD_PRIVATE_H_
+#define _DRM_EMGD_PRIVATE_H_
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_fb_helper.h>
+#include "mode.h"
+#include "context.h"
+#include "emgd_drv.h"
+
+struct _drm_emgd_private;
+
+
+/* FIXME: This define should not be here. Find a better place to put it */
+#define PSB_GATT_RESOURCE 2
+
+/**
+ * This enum is used to record the currently-saved register state (e.g. for VT
+ * switching)--either the Linux console's state is saved (i.e. the X server is
+ * active), or the X server's state is saved (i.e. the Linux console is
+ * active).
+ */
+typedef enum _drm_emgd_saved_state {
+ CONSOLE_STATE_SAVED = 0,
+ X_SERVER_STATE_SAVED = 1,
+} drm_emgd_saved_state;
+
+
+/**
+ * This structure allows the EMGD-proper code to communicate information and
+ * function pointers to the IMG 3rd-Party Display Driver (mrstlfb).
+ */
+typedef struct _drm_emgd_private {
+ /** Non-zero if the HAL is running */
+ int hal_running;
+
+ /**
+ * Which register state is currently saved for VT switches (X or the
+ * console; note: the opposite is what's actively installed in the
+ * hardware)
+ */
+ drm_emgd_saved_state saved_registers;
+
+ /**
+ * Saved state of the console, when suspending (or hibernating) the system.
+ * emgd_driver_suspend() allocates this, and emgd_driver_resume() frees
+ * this.
+ */
+ void *suspended_state;
+
+ /**
+ * A flag which emgd_driver_pre_init() sets and emgd_alter_displays()
+ * clears. If set (i.e. to 1), this indicates that emgd_alter_displays()
+ * must power on the port drivers' hardware.
+ */
+ int must_power_on_ports;
+
+ /** Non-zero if the X server is running (i.e. PVR can't do mode changes) */
+ int xserver_running;
+
+ /**
+ * Function to re-initialize the 3DD's data structures, after calls to
+ * alter_displays()
+ */
+ int (*reinit_3dd)(struct drm_device *dev);
+
+ /**
+ * Function to invalidate the flip-chains assosciated with a display (or all
+ * displays). Called from igd_alter_displays before a possible mode_change
+ */
+ int (*invalidate_flip_chains)(int display);
+
+
+ /** The context is set during the DRM module load function. */
+ igd_context_t *context;
+
+ /* The selected DC is copied to here each time alter_displays() is called
+ * via an ioctl.
+ */
+ unsigned long dc;
+
+ /**
+ * The port number of the primary display handle is copied to here each
+ * time alter_displays() is called via an ioctl.
+ */
+ unsigned short primary_port_number;
+
+ /**
+ * The primary display handle is copied to here each time alter_displays()
+ * is called via an ioctl.
+ */
+ igd_display_h primary;
+
+ /**
+ * The port number of the secondary display handle is copied to here each
+ * time alter_displays() is called via an ioctl.
+ */
+ unsigned short secondary_port_number;
+
+ /**
+ * The secondary display handle is copied to here each time alter_displays()
+ * is called via an ioctl.
+ */
+ igd_display_h secondary;
+
+ /**
+ * Store the device information so it can be passed back to userspace
+ * callers via an ioctl.
+ */
+ igd_init_info_t *init_info;
+
+ /** TODO: May use this in future.
+ * MSVDX
+ */
+ void *msvdx_private;
+
+ /*
+ * GTT offset of initial framebuffer. The initial framebuffer is a special
+ * case in that it is allocated directly by the GMM at system startup
+ * before the PVR services are initialized. As such, it has no PVR
+ * meminfo that can be used as a handle to refer to it; functions that take
+ * a framebuffer will treat a handle of 0 as referring to the initial
+ * framebuffer and then pull the GTT offset from here.
+ */
+ //unsigned long initfb_offset;
+ igd_framebuffer_info_t initfb_info;
+
+ /* fbdev is removed from drm_framebuffer in 2.6.35 so access it here */
+ struct fb_info *fbdev;
+ emgd_crtc_t *crtcs[IGD_MAX_PIPES];
+ int num_crtc;
+ emgd_fbdev_t *emgd_fbdev;
+ bool mode_config_initialized;
+ struct drm_device *ddev;
+ bool kms_enabled;
+ int qb_seamless; /* Store the state of seamless/quickboot */
+
+ /* The fd of the drm master - used to send vblank events to userspace */
+ struct drm_file *drm_master_fd;
+} drm_emgd_priv_t;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
new file mode 100644
index 0000000..b62c2ca
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
@@ -0,0 +1,516 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_connector.c
+ * $Revision: 1.3 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Connector / kenrel mode setting functions.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+
+#include <drmP.h>
+#include <drm_crtc_helper.h>
+#include <linux/version.h>
+
+
+#include "drm_emgd_private.h"
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+static enum drm_connector_status emgd_connector_detect(
+ struct drm_connector *connector,
+ bool force);
+#else
+static enum drm_connector_status emgd_connector_detect(
+ struct drm_connector *connector);
+#endif
+
+static int emgd_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t value);
+static void emgd_connector_destroy(struct drm_connector *connector);
+static int emgd_connector_get_modes(struct drm_connector *connector);
+static int emgd_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode);
+static struct drm_encoder *emgd_connector_best_encoder(
+ struct drm_connector *connector);
+static void emgd_connector_save (struct drm_connector *connector);
+static void emgd_connector_restore (struct drm_connector *connector);
+
+
+
+const struct drm_connector_funcs emgd_connector_funcs = {
+ .save = emgd_connector_save,
+ .restore = emgd_connector_restore,
+ .dpms = drm_helper_connector_dpms,
+ .detect = emgd_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = emgd_connector_set_property,
+ .destroy = emgd_connector_destroy,
+};
+
+const struct drm_connector_helper_funcs emgd_connector_helper_funcs = {
+ .get_modes = emgd_connector_get_modes,
+ .mode_valid = emgd_connector_mode_valid,
+ .best_encoder = emgd_connector_best_encoder,
+};
+
+
+
+/**
+ * emgd_mode_to_kms
+ *
+ * Converts an EMGD mode to a DRM KMS mode
+ *
+ * @param emgd_mode (IN) emgd_mode timing information
+ * @param drm_mode (OUT) DRM mode
+ */
+static void emgd_mode_to_kms(igd_display_info_t *emgd_mode,
+ struct drm_display_mode *drm_mode)
+{
+ drm_mode->status = MODE_OK;
+ drm_mode->type = DRM_MODE_TYPE_DRIVER;
+ drm_mode->clock = emgd_mode->dclk;
+ drm_mode->hdisplay = emgd_mode->width;
+ drm_mode->hsync_start = emgd_mode->hsync_start;
+ drm_mode->hsync_end = emgd_mode->hsync_end;
+ drm_mode->htotal = emgd_mode->htotal;
+ drm_mode->vdisplay = emgd_mode->height;
+ drm_mode->vsync_start = emgd_mode->vsync_start;
+ drm_mode->vsync_end = emgd_mode->vsync_end;
+ drm_mode->vtotal = emgd_mode->vtotal;
+ drm_mode->flags = emgd_mode->flags;
+ drm_mode->vrefresh = emgd_mode->refresh;
+
+ drm_mode_set_name(drm_mode);
+}
+
+
+
+/**
+ * emgd_connector_save
+ *
+ * Saves a connector state before a power event.
+ *
+ * @param encoder (IN) Encoder
+ * @param mode (IN) power mode
+ *
+ * @return None
+ */
+static void emgd_connector_save (struct drm_connector *connector)
+{
+#if 0
+ emgd_connector_t *emgd_connector;
+ emgd_encoder_t *emgd_encoder;
+ igd_display_port_t *igd_port;
+
+
+ /* Currently there is no need to do anything in this function because
+ * CRTC save calls igd_driver_save() which eventually calls mode_save().
+ * Inside of mode_save() is where encoder state is saved. In order for
+ * this function to work properly, we need to take the pd_save() call
+ * out of mode_save(). Let's wait until Phase 2 to do this.
+ */
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+ emgd_encoder = emgd_connector->encoder;
+ igd_port = emgd_encoder->igd_port;
+
+ igd_port->pd_driver->pd_save(igd_port->pd_context,
+ &emgd_encoder->state.state, 0);
+
+ EMGD_TRACE_EXIT;
+#else
+ EMGD_TRACE_ENTER;
+ EMGD_TRACE_EXIT;
+#endif
+}
+
+
+
+/**
+ * emgd_connector_restore
+ *
+ * Restores a connector state after a power event
+ *
+ * @param encoder (IN) Encoder
+ * @param mode (IN) power mode
+ *
+ * @return None
+ */
+static void emgd_connector_restore (struct drm_connector *connector)
+{
+#if 0
+ emgd_connector_t *emgd_connector;
+ emgd_encoder_t *emgd_encoder;
+ igd_display_port_t *igd_port;
+
+
+ /* Currently there is no need to do anything in this function because
+ * CRTC save calls igd_driver_save() which eventually calls mode_save().
+ * Inside of mode_save() is where encoder state is saved. In order for
+ * this function to work properly, we need to take the pd_save() call
+ * out of mode_save(). Let's wait until Phase 2 to do this.
+ */
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+ emgd_encoder = emgd_connector->encoder;
+ igd_port = emgd_encoder->igd_port;
+
+ igd_port->pd_driver->pd_restore(igd_port->pd_context,
+ emgd_encoder->state.state, 0);
+ emgd_encoder->state.state = NULL;
+
+ EMGD_TRACE_EXIT;
+#else
+ EMGD_TRACE_ENTER;
+ EMGD_TRACE_EXIT;
+#endif
+}
+
+
+
+/**
+ * emgd_connector_detect
+ *
+ * Checks to see if a display device is attached to the connector. EMGD
+ * does not currently support hot-plug.
+ *
+ * FIXME: The prototype for this function seemed to change sometime
+ * around the 2.6.35 timeframe however, different distributions
+ * cherrypicked it earlier.
+ *
+ * Fedora 14's 2.6.35.11 kernel has the patch (needs bool force)
+ * MeeGo's 2.6.35.10 kernel doesn't.
+ *
+ * @param encoder (IN) Encoder
+ * @param mode (IN) power mode
+ *
+ * @return None
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+
+static enum drm_connector_status emgd_connector_detect(
+ struct drm_connector *connector, bool force) {
+#else
+static enum drm_connector_status emgd_connector_detect(
+ struct drm_connector *connector) {
+#endif
+ emgd_connector_t *emgd_connector;
+ enum drm_connector_status connector_status;
+ igd_display_port_t *igd_port;
+ pd_port_status_t port_status;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+ igd_port = emgd_connector->encoder->igd_port;
+
+ memset(&port_status, 0, sizeof(pd_port_status_t));
+
+ /* Get current status from the port driver */
+ igd_port->pd_driver->pd_get_port_status(igd_port->pd_context, &port_status);
+
+ switch (port_status.connected) {
+ case PD_DISP_STATUS_ATTACHED:
+ connector_status = connector_status_connected;
+ break;
+
+ case PD_DISP_STATUS_DETACHED:
+ connector_status = connector_status_disconnected;
+ break;
+
+ case PD_DISP_STATUS_UNKNOWN:
+ default:
+ /*
+ * Technically "unknown" is correct here, but that isn't actually
+ * what we want to pass back to userspace via KMS. LVDS panels
+ * always have unknown connection status, so they'll always be
+ * ignored by userspace apps that only operate on connected outputs.
+ * If the driver is configured to use a port, then we should just
+ * assume that its actually connected when we report back to
+ * userspace.
+ */
+
+ connector_status = connector_status_connected;
+ break;
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return connector_status;
+}
+
+
+
+/**
+ * emgd_connector_set_property
+ *
+ * Sets a port attribute.
+ *
+ * @param connector (IN) connector
+ * @param property (IN)
+ * @param value (IN)
+ *
+ * @return TBD
+ */
+static int emgd_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t value)
+{
+ emgd_connector_t *emgd_connector;
+ drm_emgd_priv_t *priv;
+ int ret;
+ igd_attr_t *attributes, selected_attr;
+ unsigned short port_number;
+ unsigned long num_of_attributes, i;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Set the property value to the new one. This doesn't actually change
+ * anything on the HW. */
+ ret = drm_connector_property_set_value(connector, property, value);
+ if (ret) {
+ return ret;
+ }
+
+ /* Take care of the HW changes associated with the value change */
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+ port_number = emgd_connector->encoder->igd_port->port_number;
+ priv = emgd_connector->priv;
+
+ /* Search port attributes to find the one associated with the property */
+ ret = priv->context->dispatch.get_attrs(priv->context,
+ port_number,
+ &num_of_attributes,
+ &attributes);
+
+ if (ret) {
+ return ret;
+ }
+
+
+ for (i = 0; i < num_of_attributes; i++) {
+
+ if (attributes[i].id == property->values[0]) {
+ /* Copy the content of the attribute */
+ memcpy(&selected_attr, &attributes[i], sizeof(igd_attr_t));
+
+ switch (selected_attr.type) {
+ case PD_ATTR_TYPE_RANGE:
+ case PD_ATTR_TYPE_BOOL:
+ selected_attr.current_value = (unsigned long) value;
+ ret = priv->context->dispatch.set_attrs(priv->context,
+ port_number,
+ 1, /* Setting 1 attribute */
+ &selected_attr);
+ break;
+
+ case PD_ATTR_TYPE_LIST:
+ case PD_ATTR_TYPE_LIST_ENTRY:
+ case PD_ATTR_TYPE_BUFFER:
+ default:
+ EMGD_DEBUG("Unsupported PD Attribute type");
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+/**
+ * emgd_connector_destroy
+ *
+ * Cleans up the emgd_connector object.
+ *
+ * @param connector (IN) connector to clean up
+ *
+ * @return None
+ */
+static void emgd_connector_destroy(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ emgd_connector_t *emgd_connector;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("connector=0x%lx",(unsigned long)connector);
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+
+ /* Remove the properties */
+ if (emgd_connector->properties) {
+ int i;
+
+ for(i = 0; i < emgd_connector->num_of_properties; i++) {
+ drm_property_destroy(dev, emgd_connector->properties[i]);
+ }
+
+ kfree(emgd_connector->properties);
+ emgd_connector->properties = NULL;
+ }
+
+ kfree(emgd_connector);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_connector_get_modes
+ *
+ * Get the list of supported modes for the given connector
+ *
+ * @param connector (IN) connector to query.
+ *
+ * @return None
+ */
+static int emgd_connector_get_modes(struct drm_connector *connector)
+{
+ emgd_connector_t *emgd_connector;
+ igd_display_port_t *igd_port;
+ unsigned long i;
+ struct drm_display_mode *drm_mode;
+
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+ igd_port = emgd_connector->encoder->igd_port;
+
+ EMGD_DEBUG("[EMGD] emgd_connector_get_modes for port %ld\n",
+ igd_port->port_number);
+
+ for (i = 0; i < igd_port->num_timing; i++) {
+ drm_mode = drm_mode_create(emgd_connector->priv->ddev);
+
+ emgd_mode_to_kms((igd_display_info_t *)&igd_port->timing_table[i],
+ drm_mode);
+
+ /* Add current mode to the connector */
+ drm_mode_probed_add(connector, drm_mode);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return igd_port->num_timing;
+}
+
+
+
+/**
+ * emgd_connector_mode_valid
+ *
+ * Examines the mode given and see if the connector can support it.
+ * Note: the ModeStatus enum is defined in xorg/hw/xfree86/common/xf86str.h
+ *
+ * @param connector (IN) the connector to be analyzed.
+ * @param mode (IN) mode to check
+ *
+ * @return MODE_OK if supported, other ModeStatus enum if not
+ */
+static int emgd_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ emgd_connector_t *emgd_connector;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+
+
+ /* Basic checks */
+ if ((0 >= mode->hdisplay) || (mode->hdisplay > mode->hsync_start) ||
+ (mode->hsync_start >= mode->hsync_end) ||
+ (mode->hsync_end >= mode->htotal)) {
+ return MODE_H_ILLEGAL;
+ }
+
+ if ((0 >= mode->vdisplay) || (mode->vdisplay > mode->vsync_start) ||
+ (mode->vsync_start >= mode->vsync_end) ||
+ (mode->vsync_end >= mode->vtotal)) {
+ return MODE_V_ILLEGAL;
+ }
+
+ /* We should reject modes that are already rejected by the Port driver */
+ if (!(mode->flags & IGD_MODE_SUPPORTED)) {
+ return MODE_BAD;
+ }
+
+ /* We can do some basic checks here, but it is better to call
+ * match_mode() in the display/mode module because that function does
+ * a much more thorough check */
+
+
+
+ EMGD_TRACE_EXIT;
+
+ return MODE_OK;
+}
+
+
+
+/**
+ * emgd_connector_best_encoder
+ *
+ * Returns the best encoder for the given connector. In EMGD the connector is
+ * fixed to the encoder.
+ *
+ * @param connector (IN) the connector to be analyzed.
+ *
+ * @return Encoder onto which the connector is fixed on.
+ */
+static struct drm_encoder *emgd_connector_best_encoder(
+ struct drm_connector *connector)
+{
+ emgd_connector_t *emgd_connector;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_connector = container_of(connector, emgd_connector_t, base);
+
+ EMGD_TRACE_EXIT;
+
+ return &emgd_connector->encoder->base;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
new file mode 100644
index 0000000..4576b6a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
@@ -0,0 +1,1023 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_crtc.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * CRTC / kernel mode setting functions.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+
+#include <drmP.h>
+#include <drm_crtc_helper.h>
+#include <linux/version.h>
+
+
+#include "drm_emgd_private.h"
+#include "emgd_drm.h"
+
+#include <memory.h>
+#include <mode_dispatch.h>
+#include <igd_pwr.h>
+
+/* Necessary to cursor memory from PVR buffer */
+#include "pvr_bridge_km.h"
+
+/* Maximum cursor size supported by our HAL: 64x64 in ARGB */
+#define MAX_CURSOR_SIZE (64*64*4)
+
+static void emgd_crtc_dpms(struct drm_crtc *crtc, int mode);
+static bool emgd_crtc_mode_fixup(struct drm_crtc *crtc,
+ struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
+static int emgd_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode,
+ int x, int y, struct drm_framebuffer *old_fb);
+static int emgd_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
+static void emgd_crtc_prepare(struct drm_crtc *crtc);
+static void emgd_crtc_commit(struct drm_crtc *crtc);
+
+static void emgd_crtc_save(struct drm_crtc *crtc);
+static void emgd_crtc_restore(struct drm_crtc *crtc);
+static int emgd_crtc_cursor_set(struct drm_crtc *crtc,
+ struct drm_file *file_priv, uint32_t handle,
+ uint32_t width, uint32_t height);
+static int emgd_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+static void emgd_crtc_gamma_set(struct drm_crtc *crtc,
+ unsigned short *red, unsigned short *green, unsigned short *blue,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+ uint32_t start,
+#endif
+ uint32_t size);
+static void emgd_crtc_destroy(struct drm_crtc *crtc);
+static void emgd_crtc_load_lut(struct drm_crtc *crtc);
+static int emgd_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event);
+static int emgd_crtc_set_config(struct drm_mode_set *set);
+
+
+
+const struct drm_crtc_helper_funcs emgd_crtc_helper_funcs = {
+ .dpms = emgd_crtc_dpms,
+ .mode_fixup = emgd_crtc_mode_fixup,
+ .mode_set = emgd_crtc_mode_set,
+ .mode_set_base = emgd_crtc_mode_set_base,
+ .prepare = emgd_crtc_prepare,
+ .commit = emgd_crtc_commit,
+ .load_lut = emgd_crtc_load_lut,
+};
+
+const struct drm_crtc_funcs emgd_crtc_funcs = {
+ .save = emgd_crtc_save,
+ .restore = emgd_crtc_restore,
+ .cursor_set = emgd_crtc_cursor_set,
+ .cursor_move = emgd_crtc_cursor_move,
+ .gamma_set = emgd_crtc_gamma_set,
+ .set_config = emgd_crtc_set_config,
+ .destroy = emgd_crtc_destroy,
+ .page_flip = emgd_crtc_page_flip,
+};
+
+
+
+static int emgd_crtc_set_config(struct drm_mode_set *set)
+{
+ int ret;
+ struct drm_device *dev;
+ struct drm_encoder *encoder;
+ struct drm_encoder_helper_funcs *encoder_funcs;
+
+ EMGD_TRACE_ENTER;
+
+ ret = drm_crtc_helper_set_config(set);
+
+ if (ret) {
+ EMGD_ERROR_EXIT("Failed to set config\n");
+ return ret;
+ }
+
+ /* FIXME: This is a temporary fix for the resume problem: Screen goes
+ * blank after an idling period, then doesn't come back. At this point
+ * it is unclear why KMS is not calling our DPMS functions to re-enable
+ * the display. KMS does call this function on resume, so we will
+ * enable the displays here
+ */
+ emgd_crtc_dpms(set->crtc, DRM_MODE_DPMS_ON);
+
+ dev = set->crtc->dev;
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->crtc == set->crtc) {
+ encoder_funcs = encoder->helper_private;
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+/*
+ * Sets the power management mode of the pipe.
+ */
+static void emgd_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+
+ EMGD_TRACE_ENTER;
+
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ EMGD_DEBUG("pipe=%d, mode=%d", emgd_crtc->crtc_id, mode);
+ pipe = emgd_crtc->igd_pipe;
+
+ /* The following check is a work around.KMS tries to program
+ * both the crtcs and ports (LVDS and SDVO) even if it is in
+ * single mode. It results in a SIGSEGV.
+ * By putting this check we ensure that it moves forward
+ * only if there is a valid context associated with the
+ * crtc. We check it by checking the owner of the pipe which
+ * should not be null.
+ */
+ if (pipe->owner){
+
+ switch(mode) {
+
+ case DRM_MODE_DPMS_ON:
+ EMGD_DEBUG("Checking if we have pipe timings");
+ if (!pipe->timing) {
+ /* If there is no pipe timing, we cannot enable */
+ EMGD_ERROR("No pipe timing, can't enable pipe=%d, mode=%d",
+ emgd_crtc->crtc_id, DRM_MODE_DPMS_ON );
+ } else {
+ EMGD_DEBUG("Calling program pipe");
+ mode_context->kms_dispatch->kms_program_pipe(emgd_crtc);
+ EMGD_DEBUG("Calling program plane");
+ mode_context->kms_dispatch->
+ kms_set_plane_pwr(emgd_crtc, TRUE);
+
+ crtc->enabled = true;
+ }
+ break;
+
+ case DRM_MODE_DPMS_STANDBY:
+ case DRM_MODE_DPMS_SUSPEND:
+ case DRM_MODE_DPMS_OFF:
+ if (emgd_crtc->igd_pipe->inuse && crtc->enabled) {
+ EMGD_DEBUG("Calling program plane");
+ mode_context->kms_dispatch->
+ kms_set_plane_pwr(emgd_crtc, FALSE);
+
+ EMGD_DEBUG("Calling program pipe");
+ mode_context->kms_dispatch->
+ kms_set_pipe_pwr(emgd_crtc, FALSE);
+ crtc->enabled = false;
+ }else {
+ EMGD_ERROR("pipe is already off");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ EMGD_TRACE_EXIT;
+}
+
+
+
+static bool emgd_crtc_mode_fixup(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ EMGD_TRACE_ENTER;
+
+ /* Check ajusted mode to see if it's valid. If not, populate it */
+ if (adjusted_mode->crtc_htotal == 0) {
+ drm_mode_set_crtcinfo(adjusted_mode, 0);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 1;
+}
+
+
+
+/**
+ * emgd_crtc_mode_set
+ *
+ * Sets mode for the selected CRTC. This function only sets the timings
+ * into the CRTC, but doesn't actually program the timing values into the
+ * registers. The actual programming is done in emgd_crtc_commit.
+ *
+ * @param crtc (IN) CRTC to configure
+ * @param x (IN) starting X position in the frame buffer
+ * @param y (IN) starting Y position in the frame buffer
+ * @param old_fb (IN) Not used
+ *
+ * @return 0
+ */
+static int emgd_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode,
+ int x, int y, struct drm_framebuffer *old_fb)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_timing_info_t *timing = NULL;
+
+ EMGD_TRACE_ENTER;
+
+
+ dev = crtc->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ /* Which pipe are we using */
+ EMGD_DEBUG("Getting PIPE");
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ EMGD_DEBUG("\t\tpipe=%d, ->(%dx%d@%d)", emgd_crtc->crtc_id,
+ adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay,
+ adjusted_mode->vrefresh);
+
+ pipe = emgd_crtc->igd_pipe;
+
+
+ if (old_fb) {
+ EMGD_DEBUG("Handling old framebuffer?");
+ /* What do we do with the old framebuffer? */
+ }
+
+ timing = kzalloc(sizeof(igd_timing_info_t), GFP_KERNEL);
+ if (!timing) {
+ EMGD_ERROR_EXIT("unable to allocate a igd_timing_info struct.");
+ return 1;
+ }
+
+ timing->width = adjusted_mode->crtc_hdisplay;
+ timing->height = adjusted_mode->crtc_vdisplay;
+ timing->refresh = adjusted_mode->vrefresh;
+ timing->dclk = adjusted_mode->synth_clock; /* Is this the right variable? */
+ timing->htotal = adjusted_mode->crtc_htotal;
+ timing->hblank_start = adjusted_mode->crtc_hblank_start;
+ timing->hblank_end = adjusted_mode->crtc_hblank_end;
+ timing->hsync_start = adjusted_mode->crtc_hsync_start;
+ timing->hsync_end = adjusted_mode->crtc_hsync_end;
+ timing->vtotal = adjusted_mode->crtc_vtotal;
+ timing->vblank_start = adjusted_mode->crtc_vblank_start;
+ timing->vblank_end = adjusted_mode->crtc_vblank_end;
+ timing->vsync_start = adjusted_mode->crtc_vsync_start;
+ timing->vsync_end = adjusted_mode->crtc_vsync_end;
+ timing->mode_number = adjusted_mode->clock_index;
+ timing->mode_info_flags = adjusted_mode->private_flags;
+ timing->x_offset = x;
+ timing->y_offset = y;
+ timing->mode_info_flags |= IGD_DISPLAY_ENABLE;
+
+ if (pipe->timing) {
+ OS_MEMCPY(pipe->timing, timing, sizeof(igd_timing_info_t));
+ kfree(timing);
+ } else {
+ pipe->timing = timing;
+ }
+
+ /* The code above only sets the CRTC timing, not the plane */
+ emgd_crtc_mode_set_base(crtc, x, y, old_fb);
+
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/**
+ * emgd_crtc_mode_set_base
+ *
+ * Sets the starting position in the framebuffer for the given CRTC.
+ *
+ * @param crtc (IN) CRTC to configure
+ * @param x (IN) starting X position in the frame buffer
+ * @param y (IN) starting Y position in the frame buffer
+ * @param old_fb (IN) Not used
+ *
+ * @return 0
+ */
+static int emgd_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_context_t *display = NULL;
+ emgd_framebuffer_t *emgd_fb;
+ igd_framebuffer_info_t *plane_fb_info;
+ struct drm_framebuffer *fb = NULL;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ fb = crtc->fb;
+ emgd_fb = container_of(fb, emgd_framebuffer_t, base);
+ display = emgd_crtc->igd_pipe->owner;
+
+
+ if (old_fb) {
+ /* We should not need to do anything here. */
+ }
+
+ plane_fb_info = PLANE(display)->fb_info;
+
+ plane_fb_info->width = fb->width;
+ plane_fb_info->height = fb->height;
+ plane_fb_info->screen_pitch = fb->DRMFB_PITCH;
+ plane_fb_info->flags = 0;
+ plane_fb_info->allocated = 1;
+ plane_fb_info->fb_base_offset = emgd_fb->gtt_offset;
+ plane_fb_info->visible_offset = (y * fb->DRMFB_PITCH) +
+ (x * (fb->bits_per_pixel / 8));
+
+
+ PLANE(display)->inuse = 1;
+ PLANE(display)->ref_cnt++;
+
+ mode_context->kms_dispatch->kms_program_plane(emgd_crtc, TRUE);
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+static void emgd_crtc_prepare(struct drm_crtc *crtc)
+{
+ EMGD_TRACE_ENTER;
+ emgd_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ EMGD_TRACE_EXIT;
+}
+
+static void emgd_crtc_commit(struct drm_crtc *crtc)
+{
+ EMGD_TRACE_ENTER;
+ emgd_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+static void emgd_crtc_save(struct drm_crtc *crtc)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+ unsigned long save_flags;
+
+ /* We should probably break out register save and restore
+ * so that its specific to a crtc
+ */
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+ EMGD_DEBUG("\t\tpipe=%d", emgd_crtc->crtc_id);
+
+ save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT & ~IGD_REG_SAVE_RB) |
+ IGD_REG_SAVE_TYPE_MISC;
+ context->dispatch.driver_save((igd_driver_h)context, save_flags);
+
+ EMGD_TRACE_EXIT;
+}
+
+static void emgd_crtc_restore(struct drm_crtc *crtc)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+ unsigned long restore_flags;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+ EMGD_DEBUG("\t\tpipe=%d", emgd_crtc->crtc_id);
+
+ restore_flags = IGD_REG_SAVE_TYPE_MISC;
+ context->dispatch.driver_restore((igd_driver_h)context, restore_flags);
+
+ EMGD_TRACE_EXIT;
+}
+
+static int emgd_crtc_cursor_set(struct drm_crtc *crtc,
+ struct drm_file *file_priv, uint32_t handle,
+ uint32_t width, uint32_t height)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+ igd_display_context_t *display = NULL;
+ igd_cursor_info_t *cursor_info = NULL;
+ PVRSRV_PER_PROCESS_DATA *pvr_perproc;
+ PVRSRV_KERNEL_MEM_INFO *pvr_meminfo;
+ PVRSRV_ERROR ret;
+ unsigned char *tempcurs;
+ unsigned long pid;
+ struct page **pagelist;
+ unsigned long numpages, page_offset, cursor_size = 0;
+ void *pageaddr;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ if (!emgd_crtc->igd_pipe->inuse) {
+ EMGD_ERROR("\t\tpipe %d is not available", emgd_crtc->crtc_id);
+ return 1;
+ }
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+ display = emgd_crtc->igd_pipe->owner;
+
+ if (!handle) {
+ /* If handle is 0, turn off the cursor */
+ EMGD_DEBUG("Turning off cursor");
+ mode_context->dispatch->full->program_cursor(display, FALSE);
+ } else {
+ /* Fetch PVR services 'per-process' data structure */
+ pid = OSGetCurrentProcessIDKM();
+ pvr_perproc = PVRSRVPerProcessData(pid);
+
+ /* Look up the kernel-side meminfo for the handle passed in*/
+ ret = PVRSRVLookupHandle(pvr_perproc->psHandleBase,
+ (void**)&pvr_meminfo,
+ (IMG_HANDLE)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (ret != PVRSRV_OK) {
+ EMGD_ERROR("Buffer handle is not a valid PVR surface.");
+ return -EINVAL;
+ }
+
+ /*
+ * Now fetch the page list, number of pages, and offset into the first
+ * page for this buffer.
+ */
+ ret = PVRSRVGetPageListKM(pvr_meminfo, &pagelist, &numpages,
+ &page_offset);
+ if (ret != PVRSRV_OK) {
+ EMGD_ERROR("Failed to get pagelist for PVR surface.");
+ return -EINVAL;
+ }
+
+ /* Allocate a temporary buffer to hold the cursor image */
+ tempcurs = OS_ALLOC(MAX_CURSOR_SIZE);
+ if (!tempcurs) {
+ return -ENOMEM;
+ }
+
+ /* Map the page list into kernel virtual address space */
+ pageaddr = vmap(pagelist, numpages, VM_MAP, PAGE_KERNEL_UC_MINUS);
+
+ /*
+ * Our HAL only accepts 64x64 x 4byte cursors. Only copy the first
+ * 64x64x4 of the provided buffer if the user tries to pass us
+ * something too big.
+ */
+ if (numpages * PAGE_SIZE > MAX_CURSOR_SIZE) {
+ cursor_size = MAX_CURSOR_SIZE;
+ } else {
+ cursor_size = numpages * PAGE_SIZE;
+ }
+
+ OS_MEMCPY(tempcurs, pageaddr, cursor_size);
+
+ vunmap(pageaddr);
+
+ /* Pass the cursor image to the HAL to program the cursor plane */
+ cursor_info = emgd_crtc->igd_pipe->cursor->cursor_info;
+ cursor_info->flags = IGD_CURSOR_LOAD_ARGB_IMAGE | IGD_CURSOR_ON;
+ cursor_info->width = width;
+ cursor_info->height = height;
+ context->dispatch.alter_cursor(display, cursor_info, tempcurs);
+
+ /* Free temporary cursor image */
+ OS_FREE(tempcurs);
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+static int emgd_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+ igd_display_context_t *display = NULL;
+ igd_cursor_info_t *emgd_cursor;
+
+ /* Too spammy; commenting out */
+#if 0
+ EMGD_TRACE_ENTER;
+#endif
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ if (!emgd_crtc->igd_pipe->inuse) {
+ EMGD_ERROR("\t\tpipe %d is not available", emgd_crtc->crtc_id);
+ return 1;
+ }
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+ display = emgd_crtc->igd_pipe->owner;
+
+ emgd_cursor = emgd_crtc->igd_pipe->cursor->cursor_info;
+ emgd_cursor->x_offset = x;
+ emgd_cursor->y_offset = y;
+ context->dispatch.alter_cursor_pos(display, emgd_cursor);
+
+ /* Too spammy; commenting out */
+#if 0
+ EMGD_TRACE_EXIT;
+#endif
+ return 0;
+}
+
+static void emgd_crtc_gamma_set(struct drm_crtc *crtc,
+ unsigned short *red, unsigned short *green, unsigned short *blue,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+ uint32_t start,
+#endif
+ uint32_t size)
+{
+ int end, i;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ int start = 0;
+#endif
+ emgd_crtc_t *emgd_crtc = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ end = (start + size > 256) ? 256 : start + size;
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ for (i=start; i < end; i++) {
+ emgd_crtc->lut_r[i] = red[i] >> 8;
+ emgd_crtc->lut_g[i] = green[i] >> 8;
+ emgd_crtc->lut_b[i] = blue[i] >> 8;
+ }
+
+ emgd_crtc_load_lut(crtc);
+
+ EMGD_TRACE_EXIT;
+}
+
+static void emgd_crtc_destroy(struct drm_crtc *crtc)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+ igd_display_pipe_t *igd_pipe = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ igd_pipe = emgd_crtc->igd_pipe;
+ if (!igd_pipe) {
+ EMGD_ERROR("\t\tpipe %d is not available", emgd_crtc->crtc_id);
+ return;
+ }
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+
+ EMGD_DEBUG("\t\tpipe=%d", emgd_crtc->crtc_id);
+
+ drm_crtc_cleanup(crtc);
+
+ /* Free our private crtc structure */
+ kfree(emgd_crtc);
+
+ igd_pipe->inuse = 0;
+ igd_pipe->plane = NULL;
+ igd_pipe->timing = NULL;
+ igd_pipe->owner = NULL;
+
+ EMGD_TRACE_EXIT;
+}
+
+static void emgd_crtc_load_lut(struct drm_crtc *crtc)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_context_t *context = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ if (!emgd_crtc->igd_pipe) {
+ EMGD_ERROR("\t\tpipe %d is not available", emgd_crtc->crtc_id);
+ return;
+ }
+ context = ((drm_emgd_priv_t *)crtc->dev->dev_private)->context;
+ EMGD_DEBUG("\t\tpipe=%d", emgd_crtc->crtc_id);
+ /* Call into hal function to set color map. */
+ context->mod_dispatch.reg_crtc_lut_set(context, emgd_crtc);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/*
+ * crtc_pageflip_handler()
+ *
+ * VBlank handler to be called when a pageflip is complete. This will send
+ * the vblank event to userspace.
+ *
+ * State upon entry (assuming vblank_expected is set):
+ * * newfb is non-NULL
+ * * flip_event is non-NULL
+ * * flip_work_queued is FALSE
+ * * vblank_expected is TRUE (based on assumption)
+ *
+ * State upon exit (assuming entered with vblank_expected):
+ * * newfb is NULL
+ * * flip_event is NULL
+ * * flip_work_queued is FALSE
+ * * vblank_expected is FALSE
+ */
+int crtc_pageflip_handler(struct drm_device *dev, int port_num)
+{
+ drm_emgd_priv_t *devpriv = dev->dev_private;
+ emgd_crtc_t *emgd_crtc;
+ struct drm_pending_vblank_event *e;
+ struct timeval now;
+ igd_context_t *context = NULL;
+ int crtcnum;
+ unsigned long flags;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * This handler should only be executed if KMS modesetting is
+ * enabled. However, the device dependent mode code always hooks
+ * this up. Abort early if KMS modesetting is disabled.
+ */
+ if (!devpriv->kms_enabled) {
+ return 0;
+ }
+
+ context = devpriv->context;
+
+ /* Look up which CRTC that this flip is for. */
+ /* If the DC=1, only one of the CRTCs would have a non-NULL owner (display context),
+ * so we determine the CRTC by looking at the owner field. If the DC is not 1
+ * (which means both the CRTCs have valid owner fields), we look at the port number to
+ * determine the right CRTC.
+ */
+ if (devpriv->crtcs[0]->igd_pipe->owner && devpriv->crtcs[1]->igd_pipe->owner) {
+ if (port_num == devpriv->crtcs[0]->igd_pipe->owner->port_number) {
+ crtcnum = 0;
+ } else {
+ crtcnum = 1;
+ }
+ } else {
+ if (devpriv->crtcs[0]->igd_pipe->owner) {
+ crtcnum = 0;
+ } else {
+ crtcnum = 1;
+ }
+ }
+
+
+ emgd_crtc = devpriv->crtcs[crtcnum];
+
+ /* Protect access to CRTC */
+ spin_lock_irqsave(&emgd_crtc->crtc_lock, flags);
+
+ /*
+ * Were we waiting for a vblank to do flip cleanup? If not, we
+ * should just bail out.
+ */
+ if (!emgd_crtc->vblank_expected) {
+ spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+ return 1;
+ }
+
+ /* Sanity check: shouldn't be here if we still have flip work queued */
+ if (emgd_crtc->flip_work_queued) {
+ EMGD_ERROR("Flip vblank handler while work queued!");
+ spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+ return 0;
+ }
+
+ /*
+ * Sanity check: shouldn't be possible to get to this point without a
+ * userspace event to send.
+ */
+ if (!emgd_crtc->flip_event) {
+ EMGD_ERROR("Pageflip vblank handler has no userspace event");
+ spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+ return 1;
+ }
+
+ /* Release vblank refcount */
+ drm_vblank_put(dev, crtcnum);
+ emgd_crtc->vblank_expected = 0;
+
+ /* Flip is now complete; send userspace event, if requested */
+ e = emgd_crtc->flip_event;
+ do_gettimeofday(&now);
+ e->event.sequence = 0;
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+ list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+
+ /*
+ * Cleanup; not in process of switching to new FB, no outstanding
+ * userspace event awaiting our attention.
+ */
+ emgd_crtc->newfb = NULL;
+ emgd_crtc->flip_event = NULL;
+
+ spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+
+ EMGD_TRACE_EXIT;
+ return 1;
+}
+
+
+/**
+ * emgd_flip_worker
+ *
+ * Workqueue task to schedule a flip when rendering to the new framebuffer
+ * is complete. Should check the "cancel" flag and just give up,
+ * regardless of whether rendering is complete or not if set.
+ *
+ * State upon entry:
+ * * newfb is non-NULL
+ * * no constraint on flip_event
+ * * flip_work_queued is TRUE
+ * * vblank_expected is FALSE
+ *
+ * State upon exit:
+ * * no constraint on newfb
+ * * no constraint on flip_event
+ * * no constraint on flip_work_queued
+ * * no constraint on vblank_expected
+ */
+void emgd_flip_worker(struct work_struct *w)
+{
+ drm_emgd_priv_t *dev_priv;
+ igd_context_t *igd_context;
+ PVRSRV_KERNEL_MEM_INFO *meminfo;
+ PVRSRV_SYNC_DATA *syncdata = NULL;
+ emgd_crtc_t *crtc;
+ igd_surface_t igd_surface = { 0 };
+ unsigned long flags;
+ unsigned int crtcnum;
+ int ret;
+
+ /* Which CRTC does this work task belong to? */
+ crtc = container_of(w, emgd_crtc_t, flip_work);
+
+ /* Protect updates to the CRTC structure */
+ spin_lock_irqsave(&crtc->crtc_lock, flags);
+
+ /* Sanity check: flip_work_queued must be TRUE */
+ if (!crtc->flip_work_queued) {
+ EMGD_ERROR("Flip worker running without being queued");
+ spin_unlock_irqrestore(&crtc->crtc_lock, flags);
+ return;
+ }
+
+ /* Sanity check: newfb must not be NULL */
+ if (!crtc->newfb) {
+ EMGD_ERROR("No newfb in flip worker");
+ spin_unlock_irqrestore(&crtc->crtc_lock, flags);
+ return;
+ }
+
+ /*
+ * Sanity check: we shouldn't be expecting vblank/cleanup while we're
+ * still doing flip work (prior flips that may have scheduled a vblank
+ * were cancelled already.
+ */
+ if (crtc->vblank_expected) {
+ EMGD_ERROR("Expecting vblank cleanup while flip work in progress");
+ spin_unlock_irqrestore(&crtc->crtc_lock, flags);
+ return;
+ }
+
+ /*
+ * Grab the PVR meminfo and syncinfo for the surface we're waiting for
+ * rendering completion on.
+ */
+ if (crtc->newfb->type == PVR_FRAMEBUFFER) {
+ meminfo = (PVRSRV_KERNEL_MEM_INFO *)crtc->newfb->pvr_meminfo;
+ syncdata = meminfo->psKernelSyncInfo->psSyncData;
+ }
+
+ /*
+ * Have we completed all the operations that were pending when the flip
+ * ioctl was called? If so, proceed with issuing the actual flip. If
+ * we're flipping to a GMM framebuffer (i.e., the initial system fb),
+ * then we don't need to wait for any kind of rendering).
+ *
+ * It seems like we should test for wraparound here, but I don't see
+ * anywhere in PVR's code where they handle wraparound. It's probably safe
+ * to ignore for now since even if we perform 60 ops per second against the
+ * framebuffer, it would still take over two years to overflow the 32-bit
+ * unsigned int for the operation counter.
+ */
+ if (crtc->newfb->type == GMM_FRAMEBUFFER ||
+ syncdata->ui32WriteOpsComplete >= crtc->render_complete_at)
+ {
+ dev_priv = (drm_emgd_priv_t *) crtc->base.dev->dev_private;
+ igd_context = dev_priv->context;
+ crtcnum = (crtc == dev_priv->crtcs[0]) ? 0 : 1;
+
+ /* Rendering complete; program the plane registers */
+ igd_surface.flags = IGD_SURFACE_DISPLAY;
+ igd_surface.offset = crtc->newfb->gtt_offset;
+ igd_surface.pitch = crtc->newfb->base.DRMFB_PITCH;
+ igd_surface.width = crtc->newfb->base.width;
+ igd_surface.height = crtc->newfb->base.height;
+ igd_surface.pixel_format = IGD_PF_ARGB32;
+
+ igd_context->dispatch.set_surface(
+ crtc->igd_pipe->owner,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &igd_surface,
+ NULL, /* Not used */
+ 0);
+
+ /* Flip issued. No need to requeue the work. */
+ crtc->flip_work_queued = 0;
+
+ /*
+ * If a userspace event was requested for this flip, request vblank
+ * interrupts if they aren't already on.
+ */
+ if (crtc->flip_event) {
+ /* Request vblank events (or inc the refcount if they're already on) */
+ ret = drm_vblank_get(crtc->base.dev, crtcnum);
+ if (ret) {
+ EMGD_ERROR("Failed enable vblanks");
+ return;
+ }
+ crtc->vblank_expected = 1;
+ } else {
+ /*
+ * No userspace event; the flip is complete as far as we're
+ * concerned. Clear the "in progress of switching to fb" field.
+ */
+ crtc->newfb = NULL;
+ }
+
+ } else {
+ /* Rendering not complete. Requeue the work task. */
+ schedule_work(w);
+ }
+
+ spin_unlock_irqrestore(&crtc->crtc_lock, flags);
+}
+
+
+/**
+ * emgd_crtc_page_flip
+ *
+ * Page flip ioctl handler. The ioctl simply dispatches a workqueue task
+ * which will wait until current rendering against the new framebuffer
+ * is complete, then issue the actual flip. This ioctl should return
+ * immediately, allowing pipelining of subsequent CPU execution with
+ * the outstanding rendering happening against this framebuffer.
+ *
+ * @param crtc (INOUT) The pipe to put the new framebuffer on
+ * @param fb (IN) Framebuffer to flip to
+ * @param event (IN) Event to signal when flip has been completed
+ *
+ * @return
+ *
+ * State upon entry:
+ * * No constraint on newfb
+ * * No constraint on flip_event
+ * * No constraint on flip_work_queued
+ * * No constraint on vblank_expected
+ *
+ * State upon exit:
+ * * newfb is non-NULL
+ * * no constraint on flip_event
+ * * flip_work_queued is TRUE
+ * * vblank_expected is FALSE
+ */
+static int emgd_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event)
+{
+ emgd_crtc_t *emgd_crtc;
+ emgd_framebuffer_t *emgd_fb;
+ drm_emgd_priv_t *dev_priv;
+ igd_context_t *igd_context;
+ unsigned int crtcnum;
+ unsigned long flags;
+ struct drm_pending_vblank_event *e;
+ struct timeval now;
+ PVRSRV_KERNEL_MEM_INFO *meminfo;
+ PVRSRV_SYNC_DATA *syncdata;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+ dev_priv = (drm_emgd_priv_t *) crtc->dev->dev_private;
+ igd_context = dev_priv->context;
+ emgd_fb = container_of(fb, emgd_framebuffer_t, base);
+ crtcnum = (emgd_crtc == dev_priv->crtcs[0]) ? 0 : 1;
+
+ /*
+ * Protect updates to the CRTC structure. We don't want this code to
+ * overlap with either the workqueue task or the vblank handler.
+ */
+ spin_lock_irqsave(&emgd_crtc->crtc_lock, flags);
+
+ /*
+ * Was there a pending userspace event for a previous flip request? If
+ * so, just send the completion back now. We're essentially cancelling
+ * the previous flip (it will never show up on the display), but we don't
+ * want userspace to get confused by not receiving notification. We'll
+ * also decrement our vblank request if we'd already scheduled on for
+ * cleanup.
+ */
+ if ((e = emgd_crtc->flip_event) != NULL) {
+ do_gettimeofday(&now);
+ e->event.sequence = 0;
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+ list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+ emgd_crtc->flip_event = NULL;
+
+ /*
+ * If the work task had completed and actually programmed the
+ * registers, it had also requested a vblank callback. Cancel
+ * that as well since we've already taken care of the necessary
+ * cleanup. Note that vblanks are only requested when we actually
+ * have a userspace event to send back.
+ */
+ if (emgd_crtc->vblank_expected) {
+ drm_vblank_put(crtc->dev, crtcnum);
+ emgd_crtc->vblank_expected = 0;
+ }
+ }
+
+ /* Update the CRTC's "target framebuffer" field. */
+ emgd_crtc->newfb = emgd_fb;
+ emgd_crtc->flip_event = event;
+
+ /*
+ * Set the number of rendering operations that need to complete before we
+ * can flip to this buffer. I.e., we don't need render to completely
+ * quiesce, we can flip as soon as any operations that are outstanding
+ * right now complete, even if more rendering ops get added to the pipeline
+ * after we return.
+ */
+ meminfo = (PVRSRV_KERNEL_MEM_INFO *)emgd_fb->pvr_meminfo;
+ syncdata = meminfo->psKernelSyncInfo->psSyncData;
+ emgd_crtc->render_complete_at = syncdata->ui32WriteOpsPending;
+
+ /*
+ * If work is already scheduled, nothing more to do here; the
+ * already-scheduled work will see the new values we set next time it wakes
+ * up and will act upon them. However if work is not scheduled, then
+ * we need to schedule it now.
+ */
+ if (!emgd_crtc->flip_work_queued) {
+ schedule_work(&emgd_crtc->flip_work);
+ emgd_crtc->flip_work_queued = 1;
+ }
+
+ /* Move the FB currently associated with the CRTC to the new FB */
+ crtc->fb = fb;
+
+ /* Done updating CRTC structure */
+ spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
new file mode 100755
index 0000000..58927c6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
@@ -0,0 +1,2596 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_drv.c
+ * $Revision: 1.147 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * The main part of the kernel module. This part gets everything going and
+ * connected, and then the rest can function.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.oal
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <drm/drm_pciids.h>
+#include <intelpci.h>
+#include "drm_emgd_private.h"
+#include "user_config.h"
+#include "emgd_drv.h"
+#include "emgd_drm.h"
+#include "memory.h"
+#include "io.h"
+#include "mode_dispatch.h"
+#include "igd_debug.h"
+#include "splash_screen.h"
+#include "msvdx.h"
+/*
+ * Imagination includes.
+ */
+#include <img_types.h>
+#include <pvr_drm.h>
+#include <pvr_drm_shared.h>
+#include <pvr_bridge.h>
+#include <linkage.h>
+#include <sysconfig.h>
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))
+#include <linux/module.h>
+#include <linux/export.h>
+#endif
+/* For Buffer Class of Texture Stream*/
+/* pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c */
+extern int emgd_bc_ts_init(void);
+extern int emgd_bc_ts_uninit(void);
+
+/*------------------------------------------------------------------------------
+ * Formal Declaration
+ *------------------------------------------------------------------------------
+ */
+extern void emgd_set_real_handle(igd_driver_h drm_handle);
+extern void emgd_set_real_dispatch(igd_dispatch_t *drm_dispatch);
+extern void emgd_modeset_init(struct drm_device *dev);
+extern void emgd_modeset_destroy(struct drm_device *dev);
+extern int msvdx_pre_init_plb(struct drm_device *dev);
+extern int msvdx_shutdown_plb(igd_context_t *context);
+extern int topaz_shutdown_tnc(igd_context_t *context);
+
+extern emgd_drm_config_t config_drm;
+extern int context_count;
+#ifdef SUPPORT_V2G_CAMERA
+/* V2G Camera Module Exported API */
+extern int v2g_start_camera();
+#endif
+
+/* This must be defined whether debug or release build */
+igd_debug_t emgd_debug_flag = {
+ {
+ CONFIG_DEBUG_FLAGS
+ }
+};
+igd_debug_t *emgd_debug = &emgd_debug_flag;
+
+#ifdef DEBUG_BUILD_TYPE
+
+MODULE_PARM_DESC(debug_cmd, "Debug: cmd");
+module_param_named(debug_cmd, emgd_debug_flag.hal.cmd, short, 0600);
+
+MODULE_PARM_DESC(debug_dsp, "Debug: dsp");
+module_param_named(debug_dsp, emgd_debug_flag.hal.dsp, short, 0600);
+
+MODULE_PARM_DESC(debug_mode, "Debug: mode");
+module_param_named(debug_mode, emgd_debug_flag.hal.mode, short, 0600);
+
+MODULE_PARM_DESC(debug_init, "Debug: init");
+module_param_named(debug_init, emgd_debug_flag.hal.init, short, 0600);
+
+MODULE_PARM_DESC(debug_overlay, "Debug: overlay");
+module_param_named(debug_overlay, emgd_debug_flag.hal.overlay, short, 0600);
+
+MODULE_PARM_DESC(debug_power, "Debug: power");
+module_param_named(debug_power, emgd_debug_flag.hal.power, short, 0600);
+
+MODULE_PARM_DESC(debug_2D, "Debug: 2D");
+module_param_named(debug_2D, emgd_debug_flag.hal._2d, short, 0600);
+
+MODULE_PARM_DESC(debug_blend, "Debug: blend");
+module_param_named(debug_blend, emgd_debug_flag.hal.blend, short, 0600);
+
+MODULE_PARM_DESC(debug_state, "Debug: state");
+module_param_named(debug_state, emgd_debug_flag.hal.state, short, 0600);
+
+MODULE_PARM_DESC(debug_gmm, "Debug: GMM");
+module_param_named(debug_gmm, emgd_debug_flag.hal.gmm, short, 0600);
+
+MODULE_PARM_DESC(debug_gart, "Debug: GART");
+module_param_named(debug_gart, emgd_debug_flag.hal.gart, short, 0600);
+
+MODULE_PARM_DESC(debug_oal, "Debug: OAL");
+module_param_named(debug_oal, emgd_debug_flag.hal.oal, short, 0600);
+
+MODULE_PARM_DESC(debug_intr, "Debug: intr");
+module_param_named(debug_intr, emgd_debug_flag.hal.intr, short, 0600);
+
+MODULE_PARM_DESC(debug_dpd, "Debug: dpd");
+module_param_named(debug_dpd, emgd_debug_flag.hal.dpd, short, 0600);
+
+MODULE_PARM_DESC(debug_video, "Debug: video");
+module_param_named(debug_video, emgd_debug_flag.hal.video, short, 0600);
+
+MODULE_PARM_DESC(debug_pvr3dd, "Debug: PVR3DD");
+module_param_named(debug_pvr3dd, emgd_debug_flag.hal.pvr3dd, short, 0600);
+
+MODULE_PARM_DESC(debug_trace, "Global Debug: trace");
+module_param_named(debug_trace, emgd_debug_flag.hal.trace, short, 0600);
+
+MODULE_PARM_DESC(debug_instr, "Global Debug: instr");
+module_param_named(debug_instr, emgd_debug_flag.hal.instr, short, 0600);
+
+MODULE_PARM_DESC(debug_debug, "Global Debug: Debug with no associated module ");
+module_param_named(debug_debug, emgd_debug_flag.hal.debug, short, 0600);
+
+MODULE_PARM_DESC(debug_blend_stats, "Verbose Debug: Blend stats");
+module_param_named(debug_blend_stats, emgd_debug_flag.hal.blend_stats, short, 0600);
+
+MODULE_PARM_DESC(debug_dump_overlay_regs, "Verbose Debug: Dump overlay regs");
+module_param_named(debug_dump_overlay_regs, emgd_debug_flag.hal.dump_overlay_regs, short, 0600);
+
+MODULE_PARM_DESC(debug_dump_command_queue, "Verbose Debug: dump command queue");
+module_param_named(debug_dump_command_queue, emgd_debug_flag.hal.dump_command_queue, short, 0600);
+
+MODULE_PARM_DESC(debug_dump_gmm_on_fail, "Verbose Debug: dump gmm on fail");
+module_param_named(debug_dump_gmm_on_fail, emgd_debug_flag.hal.dump_gmm_on_fail, short, 0600);
+
+MODULE_PARM_DESC(debug_dump_shaders, "Verbose Debug: dump shaders");
+module_param_named(debug_dump_shaders, emgd_debug_flag.hal.dump_shaders, short, 0600);
+
+MODULE_PARM_DESC(debug_bc_ts, "Debug: Texture Stream");
+module_param_named(debug_bc_ts, emgd_debug_flag.hal.buf_class, short, 0600);
+#endif
+
+
+static struct drm_driver driver; /* TODO: what? */
+
+/* Note: The following module paramter values are advertised to the root user,
+ * via the files in the /sys/module/emgd/parameters directory (e.g. the "init"
+ * file contains the value of the "init" module parameter), and so we keep
+ * these values up to date.
+ *
+ * Note: The initial values are all set to -1, so that we can tell if the user
+ * set them.
+ */
+int drm_emgd_portorder[IGD_MAX_PORTS] = {-1, -1, -1, -1, -1};
+int drm_emgd_numports;
+int drm_emgd_configid = -1;
+int drm_emgd_init = -1;
+int drm_emgd_dc = -1;
+int drm_emgd_width = -1;
+int drm_emgd_height = -1;
+int drm_emgd_refresh = -1;
+MODULE_PARM_DESC(portorder, "Display port order (e.g. \"4,2,0,0,0\")");
+MODULE_PARM_DESC(configid, "Which defined configuration number to use (e.g. "
+ "\"1\")");
+MODULE_PARM_DESC(init, "Whether to initialize the display at startup (1=yes, "
+ "0=no)");
+MODULE_PARM_DESC(dc, "Display configuration (i.e. 1=single, 2=clone)");
+MODULE_PARM_DESC(width, "Display resolution's width (e.g. \"1024\")");
+MODULE_PARM_DESC(height, "Display resolution's height (e.g. \"768\")");
+MODULE_PARM_DESC(refresh, "Monitor refresh rate (e.g. 60, as in 60Hz)");
+module_param_array_named(portorder, drm_emgd_portorder, int, &drm_emgd_numports,
+ 0600);
+module_param_named(configid, drm_emgd_configid, int, 0600);
+module_param_named(init, drm_emgd_init, int, 0600);
+module_param_named(dc, drm_emgd_dc, int, 0600);
+module_param_named(width, drm_emgd_width, int, 0600);
+module_param_named(height, drm_emgd_height, int, 0600);
+module_param_named(refresh, drm_emgd_refresh, int, 0600);
+
+
+/** The DC to use when the DRM module [re-]initializes the display. */
+static unsigned long *desired_dc = NULL;
+/** The DC to use when the DRM module [re-]initializes the display. */
+static unsigned short port_number = 0;
+/** The mode to use when the DRM module [re-]initializes the display. */
+static igd_display_info_t *desired_mode = NULL;
+/** Set to true when we know X is initialized. This flag should be set
+ ** earlier, but right now we're setting it in emgd_driver_preclose() */
+unsigned x_started = false;
+
+/**
+ * The primary fb_info to use when the DRM module [re-]initializes the display.
+ */
+igd_framebuffer_info_t *primary_fb_info;
+/**
+ * The secondary fb_info to use when the DRM module [re-]initializes the
+ * display.
+ */
+igd_framebuffer_info_t *secondary_fb_info;
+/**
+ * The primary display structure (filled in by alter_displays()) to use when
+ * the DRM module [re-]initializes the display.
+ */
+igd_display_h primary;
+/**
+ * The secondary display structure (filled in by alter_displays()) to use when
+ * the DRM module [re-]initializes the display.
+ */
+igd_display_h secondary;
+/**
+ * The display information to use when the DRM module [re-]initializes the
+ * display.
+ */
+igd_display_info_t pt_info;
+extern mode_context_t mode_context[1];
+
+/* Note: This macro is #define'd in "oal/os/memory.h" */
+#ifdef INSTRUMENT_KERNEL_ALLOCS
+os_allocd_mem *list_head = NULL;
+os_allocd_mem *list_tail = NULL;
+#endif
+
+
+#define emgd_PCI_IDS \
+ {0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108}, \
+ {0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109}, \
+ {0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TC_4108}, \
+ {0, 0, 0}
+
+static struct pci_device_id pciidlist[] = {
+ emgd_PCI_IDS
+};
+
+/*
+ * To use DRM_IOCTL_DEF, the first arg should be the local (zero based)
+ * IOCTL number, not the global number.
+ */
+#define EMGD_IOCTL_DEF(ioctl, _func, _flags) \
+ [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = \
+ {.cmd = ioctl, .func = _func, .flags = _flags}
+
+static struct drm_ioctl_desc emgd_ioctl[] = {
+ /*
+ * NOTE: The flag "DRM_MASTER" for the final parameter indicates an ioctl
+ * can only be used by the DRM master process. In an X environment, the
+ * X server will be the master, in a Wayland environment, the Wayland
+ * compositor will be master, and if just running standalone GBM apps,
+ * they'll gain master. For ioctl's that we want to run from an X
+ * client app or a Wayland client app, we instead use DRM_AUTH; these
+ * clients will get the DRM master to authenticate them, after which
+ * they'll be able to call the ioctl's. Random programs that haven't
+ * authenticated with the DRM master won't be able to call them.
+ *
+ * For all private EMGD ioctl's added declaration DRM_UNLOCKED,
+ * now ioctl's can run in parallel. Before it, without declaration
+ * DRM_UNLOCKED private EMGD ioctl's can run/work in serial mode only,
+ * one by one.
+ */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_CURSOR, emgd_alter_cursor,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_CURSOR_POS, emgd_alter_cursor_pos,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_DISPLAYS, emgd_alter_displays,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_OVL, emgd_alter_ovl, DRM_MASTER|DRM_UNLOCKED),
+ /* Making DRM_IOCTL_IGD_ALTER_OVL2 DRM_AUTH so that libva wayland can
+ * call alter_ovl without going through X server.
+ */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_OVL2, emgd_alter_ovl2, DRM_AUTH|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_APPCTX_ALLOC, emgd_appcontext_alloc,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_APPCTX_FREE, emgd_appcontext_free,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_SAVE_RESTORE, emgd_driver_save_restore,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ENABLE_PORT, emgd_enable_port, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_ATTRS, emgd_get_attrs, DRM_MASTER|DRM_UNLOCKED),
+ /* Making DRM_IOCTL_IGD_GET_DISPLAY DRM_AUTH so that libva wayland can
+ * obtain the display handle without going through x server.
+ */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_DISPLAY, emgd_get_display, DRM_AUTH|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_DRM_CONFIG, emgd_get_drm_config,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_EDID_BLOCK, emgd_get_EDID_block,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_EDID_INFO, emgd_get_EDID_info,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PIXELFORMATS, emgd_get_pixelformats,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PORT_INFO, emgd_get_port_info,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_ALLOC_REGION, emgd_gmm_alloc_region,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_ALLOC_SURFACE, emgd_gmm_alloc_surface,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_GET_NUM_SURFACE, emgd_gmm_get_num_surface,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_GET_SURFACE_LIST,emgd_gmm_get_surface_list,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_FREE, emgd_gmm_free,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_FLUSH_CACHE, emgd_gmm_flush_cache,
+ DRM_MASTER|DRM_UNLOCKED),
+ /*
+ * Externally handled IOCTL's. These are routed to the Imagination Tech
+ * kernel services.
+ * function prototypes in services4/srvkm/env/linux/pvr_drm.h
+ */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_1, PVRSRV_BridgeDispatchKM, DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_2, PVRDRM_Dummy_ioctl, DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_3, PVRDRM_Dummy_ioctl, DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_4, PVRDRMIsMaster, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_5, PVRDRMUnprivCmd, DRM_UNLOCKED),
+
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PAN_DISPLAY, emgd_pan_display,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_POWER_DISPLAY, emgd_power_display,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PWR_ALTER, emgd_pwr_alter, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_DC, emgd_query_dc,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_MAX_SIZE_OVL, emgd_query_max_size_ovl,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_OVL, emgd_query_ovl, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_MODE_LIST, emgd_query_mode_list,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_GOLDEN_HTOTAL, emgd_get_golden_htotal,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_CONTROL_PLANE_FORMAT, emgd_control_plane_format,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_OVERLAY_DISPLAY, emgd_set_overlay_display,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_2D_CAPS_HWHINT, emgd_query_2d_caps_hwhint,
+ DRM_MASTER|DRM_UNLOCKED),
+ /*
+ * For PDUMP
+ */
+#if defined(PDUMP)
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_6, dbgdrv_ioctl, 0),
+#else
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_6, NULL, 0),
+#endif
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_ATTRS, emgd_set_attrs, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_PALETTE_ENTRY, emgd_set_palette_entry,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_SURFACE, emgd_set_surface, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SYNC, emgd_sync, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_PRE_INIT, emgd_driver_pre_init,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_GET_PORTS, emgd_driver_get_ports,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_OVL_INIT_PARAMS, emgd_get_ovl_init_params,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PAGE_LIST, emgd_get_page_list,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_START_PVRSRV, emgd_start_pvrsrv,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_TEST_PVRSRV, emgd_test_pvrsrv,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_CHIPSET_INFO, emgd_get_chipset_info,
+ DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DIHCLONE_SET_SURFACE, emgd_dihclone_set_surface, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PREINIT_MMU, emgd_preinit_mmu, DRM_MASTER|DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_UNLOCK_PLANES, emgd_unlock_planes, DRM_MASTER|DRM_UNLOCKED),
+
+ /*
+ * For VIDEO (MSVDX/TOPAZ
+ */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_CMD_BUF, emgd_video_cmd_buf,
+ DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_INIT_VIDEO, emgd_init_video,
+ DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_DEVICE_INFO, emgd_get_device_info,
+ DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_GET_INFO, emgd_video_get_info,
+ DRM_UNLOCKED),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_FLUSH_TLB, emgd_video_flush_tlb,
+ DRM_UNLOCKED),
+
+ /* For Buffer Class of Texture Stream */
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_INIT, emgd_bc_ts_cmd_init,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_UNINIT, emgd_bc_ts_cmd_uninit,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_REQUEST_BUFFERS, emgd_bc_ts_cmd_request_buffers,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_RELEASE_BUFFERS, emgd_bc_ts_cmd_release_buffers,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_SET_BUFFER_INFO, emgd_bc_ts_set_buffer_info,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFERS_COUNT, emgd_bc_ts_get_buffers_count,
+ DRM_AUTH),
+ EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFER_INDEX, emgd_bc_ts_get_buffer_index,
+ DRM_AUTH),
+};
+
+static int emgd_max_ioctl = DRM_ARRAY_SIZE(emgd_ioctl);
+
+
+
+/*
+ * NOTE: The next part of this file are EMGD-specific DRM functions, exported to
+ * the generic DRM code via the drm_driver struct:
+ */
+
+
+extern igd_driver_h handle;
+/** This is the dispatch table for the HAL. It is cached for quick access. */
+extern igd_dispatch_t *dispatch;
+
+
+/**
+ * The driver handle for talking with the HAL, within the DRM/kernel code.
+ *
+ * This is a "real handle" as opposed to the "fake handle" in user-space.
+ * Notice that there's only one handle, as the secondary device shares this
+ * handle.
+ */
+static igd_driver_h drm_HAL_handle = NULL;
+
+/**
+ * This is the drm_HAL_handle cast to an igd_context_t. It is cached for quick
+ * access.
+ */
+static igd_context_t *drm_HAL_context = NULL;
+
+/**
+ * This is the dispatch table for the HAL. It is cached for quick access.
+ */
+static igd_dispatch_t *drm_HAL_dispatch = NULL;
+
+
+int emgd_get_display_handle(void **display_handle, int screen_number)
+{
+ emgd_drm_get_display_t drm_data;
+ struct drm_file file_priv;
+ int ret;
+ drm_emgd_priv_t *priv = NULL;
+ igd_display_pipe_t *primary_pipe = NULL;
+ igd_display_pipe_t *secondary_pipe = NULL;
+ igd_plane_t *primary_plane = NULL;
+ igd_plane_t *secondary_plane = NULL;
+ unsigned long pipe_num = 0;
+ unsigned long port_num = 0;
+
+ EMGD_TRACE_ENTER;
+
+ memset(&drm_data, 0, sizeof(emgd_drm_get_display_t));
+ memset(&file_priv, 0, sizeof(struct drm_file));
+
+ drm_HAL_context->mod_dispatch.dsp_get_planes_pipes(&primary_plane, &secondary_plane, &primary_pipe, &secondary_pipe);
+
+ priv = (drm_emgd_priv_t *)((struct drm_device *)drm_HAL_context->drm_dev)->dev_private;
+
+ if (0 == screen_number) {
+ if (NULL == priv->primary || NULL == primary_pipe) {
+ EMGD_ERROR("Primary Display & Pipe does not exist!");
+ return 1;
+ }
+ port_num = priv->primary_port_number;
+ pipe_num = primary_pipe->pipe_num;
+ } else {
+ if (NULL == priv->secondary || NULL == secondary_pipe ) {
+ EMGD_ERROR("Secondary Display does not exist!");
+ return 1;
+ }
+ port_num = priv->secondary_port_number;
+ pipe_num = secondary_pipe->pipe_num;
+ }
+
+ drm_data.port_number = port_num;
+
+ ret = emgd_get_display(drm_HAL_context->drm_dev, (void *)&drm_data, &file_priv);
+
+ /* set the requested display handle for the caller */
+ *display_handle = ret ? NULL : (void *)drm_data.display_handle;
+ if (NULL != *display_handle) {
+ PIPE(*display_handle)->pipe_num = pipe_num;
+ EMGD_DEBUG("port_num: %lu, pipe_number: %lu", port_num, pipe_num);
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+EXPORT_SYMBOL(emgd_get_display_handle);
+
+int emgd_get_screen_size(int screen_num, unsigned short *width, unsigned short *height)
+{
+ EMGD_TRACE_ENTER;
+
+ if (NULL == width || NULL == height) {
+ return 1;
+ }
+
+ *width = (unsigned short)config_drm.width;
+ *height = (unsigned short)config_drm.height;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+EXPORT_SYMBOL(emgd_get_screen_size);
+/*!
+ * get_pre_driver_info
+ *
+ * Gets the mode information before the user-mode driver changes it.
+ * This information can either come from the firmware or the DRM.
+ * Note: Prior to EMGD this information can only come from the firmware
+ * thus the field "fw_info." This should really be changed
+ * to "pre_drv_info"
+ *
+ * @param mode_context This is where fw_info is stored
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+static int get_pre_driver_info(mode_context_t *mode_context)
+{
+ int ret = 0;
+ int seamless = FALSE;
+ EMGD_TRACE_ENTER;
+
+ if(mode_context->fw_info != NULL) {
+ seamless = TRUE;
+
+ ret = mode_context->dispatch->full->get_plane_info();
+ if(ret) {
+ seamless = FALSE;
+ }
+
+ ret = mode_context->dispatch->full->get_pipe_info(primary);
+ if(ret) {
+ seamless = FALSE;
+ }
+
+ ret = mode_context->dispatch->full->get_port_info();
+ if(ret) {
+ seamless = FALSE;
+ }
+
+ }
+
+ if(seamless == FALSE) {
+ /* If one of these plane/pipe/port functions
+ * returns an error, we explicitly
+ * turn-off seamless.
+ */
+ mode_context->seamless = FALSE;
+
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/**
+ * A helper function that prints the igd_param_t struct.
+ *
+ * @param params (IN) The the igd_param_t struct to print
+ */
+void emgd_print_params(igd_param_t *params)
+{
+ int i;
+
+ EMGD_DEBUG("Values of params:");
+ EMGD_DEBUG(" page_request = %lu = 0x%lx", params->page_request,
+ params->page_request);
+ EMGD_DEBUG(" max_fb_size = %lu = 0x%lx", params->max_fb_size,
+ params->max_fb_size);
+ EMGD_DEBUG(" preserve_regs = %u", params->preserve_regs);
+ EMGD_DEBUG(" display_flags = %lu = 0x%lx", params->display_flags,
+ params->display_flags);
+ EMGD_DEBUG(" port_order:");
+ for (i = 0 ; i < IGD_MAX_PORTS; i++) {
+ EMGD_DEBUG(" port number %d = %lu", i, params->port_order[i]);
+ }
+ EMGD_DEBUG(" display_params:");
+ for (i = 0 ; i < IGD_MAX_PORTS; i++) {
+ int j;
+
+ EMGD_DEBUG(" port_number = %lu",
+ params->display_params[i].port_number);
+ EMGD_DEBUG(" present_params = %lu = 0x%lx",
+ params->display_params[i].present_params,
+ params->display_params[i].present_params);
+ EMGD_DEBUG(" flags = %lu = 0x%lx",
+ params->display_params[i].flags,
+ params->display_params[i].flags);
+ EMGD_DEBUG(" edid_avail = %u = 0x%x",
+ params->display_params[i].edid_avail,
+ params->display_params[i].edid_avail);
+ EMGD_DEBUG(" edid_not_avail = %u = 0x%x",
+ params->display_params[i].edid_not_avail,
+ params->display_params[i].edid_not_avail);
+ EMGD_DEBUG(" ddc_gpio = %lu", params->display_params[i].ddc_gpio);
+ EMGD_DEBUG(" ddc_speed = %lu", params->display_params[i].ddc_speed);
+ EMGD_DEBUG(" ddc_dab = %lu", params->display_params[i].ddc_dab);
+ EMGD_DEBUG(" i2c_gpio = %lu", params->display_params[i].i2c_gpio);
+ EMGD_DEBUG(" i2c_speed = %lu", params->display_params[i].i2c_speed);
+ EMGD_DEBUG(" i2c_dab = %lu", params->display_params[i].i2c_dab);
+ EMGD_DEBUG(" fp_info.fp_width = %lu",
+ params->display_params[i].fp_info.fp_width);
+ EMGD_DEBUG(" fp_info.fp_height = %lu",
+ params->display_params[i].fp_info.fp_height);
+ EMGD_DEBUG(" fp_info.fp_pwr_method = %lu",
+ params->display_params[i].fp_info.fp_pwr_method);
+ EMGD_DEBUG(" fp_info.fp_pwr_t1 = %lu",
+ params->display_params[i].fp_info.fp_pwr_t1);
+ EMGD_DEBUG(" fp_info.fp_pwr_t2 = %lu",
+ params->display_params[i].fp_info.fp_pwr_t2);
+ EMGD_DEBUG(" fp_info.fp_pwr_t3 = %lu",
+ params->display_params[i].fp_info.fp_pwr_t3);
+ EMGD_DEBUG(" fp_info.fp_pwr_t4 = %lu",
+ params->display_params[i].fp_info.fp_pwr_t4);
+ EMGD_DEBUG(" fp_info.fp_pwr_t5 = %lu",
+ params->display_params[i].fp_info.fp_pwr_t5);
+ EMGD_DEBUG(" dtd_list:");
+ EMGD_DEBUG(" num_dtds = %lu",
+ params->display_params[i].dtd_list.num_dtds);
+ for (j = 0 ; j < params->display_params[i].dtd_list.num_dtds; j++) {
+ EMGD_DEBUG(" *dtd[%d].width = %u", j,
+ params->display_params[i].dtd_list.dtd[j].width);
+ EMGD_DEBUG(" dtd[%d].height = %u", j,
+ params->display_params[i].dtd_list.dtd[j].height);
+ EMGD_DEBUG(" dtd[%d].refresh = %u", j,
+ params->display_params[i].dtd_list.dtd[j].refresh);
+ EMGD_DEBUG(" dtd[%d].dclk = %lu = 0x%lx", j,
+ params->display_params[i].dtd_list.dtd[j].dclk,
+ params->display_params[i].dtd_list.dtd[j].dclk);
+ EMGD_DEBUG(" dtd[%d].htotal = %u", j,
+ params->display_params[i].dtd_list.dtd[j].htotal);
+ EMGD_DEBUG(" dtd[%d].hblank_start = %u", j,
+ params->display_params[i].dtd_list.dtd[j].hblank_start);
+ EMGD_DEBUG(" dtd[%d].hblank_end = %u", j,
+ params->display_params[i].dtd_list.dtd[j].hblank_end);
+ EMGD_DEBUG(" dtd[%d].hsync_start = %u", j,
+ params->display_params[i].dtd_list.dtd[j].hsync_start);
+ EMGD_DEBUG(" dtd[%d].hsync_end = %u", j,
+ params->display_params[i].dtd_list.dtd[j].hsync_end);
+ EMGD_DEBUG(" dtd[%d].vtotal = %u", j,
+ params->display_params[i].dtd_list.dtd[j].vtotal);
+ EMGD_DEBUG(" dtd[%d].vblank_start = %u", j,
+ params->display_params[i].dtd_list.dtd[j].vblank_start);
+ EMGD_DEBUG(" dtd[%d].vblank_end = %u", j,
+ params->display_params[i].dtd_list.dtd[j].vblank_end);
+ EMGD_DEBUG(" dtd[%d].vsync_start = %u", j,
+ params->display_params[i].dtd_list.dtd[j].vsync_start);
+ EMGD_DEBUG(" dtd[%d].vsync_end = %u", j,
+ params->display_params[i].dtd_list.dtd[j].vsync_end);
+ EMGD_DEBUG(" dtd[%d].mode_number = %d", j,
+ params->display_params[i].dtd_list.dtd[j].mode_number);
+ EMGD_DEBUG(" dtd[%d].flags = %lu = 0x%lx", j,
+ params->display_params[i].dtd_list.dtd[j].flags,
+ params->display_params[i].dtd_list.dtd[j].flags);
+ EMGD_DEBUG(" dtd[%d].x_offset = %u", j,
+ params->display_params[i].dtd_list.dtd[j].x_offset);
+ EMGD_DEBUG(" dtd[%d].y_offset = %u", j,
+ params->display_params[i].dtd_list.dtd[j].y_offset);
+ /*EMGD_DEBUG(" dtd[%d].pd_private_ptr = 0x%p", j,
+ params->display_params[i].dtd_list.dtd[j].pd_private_ptr); */
+ EMGD_DEBUG(" dtd[%d].private_ptr = 0x%p", j,
+ params->display_params[i].dtd_list.dtd[j].private_ptr);
+ }
+ EMGD_DEBUG(" attr_list:");
+ EMGD_DEBUG(" num_attrs = %lu",
+ params->display_params[i].attr_list.num_attrs);
+ for (j = 0 ; j < params->display_params[i].attr_list.num_attrs; j++) {
+ EMGD_DEBUG(" attr[%d].id = %lu = 0x%lx", j,
+ params->display_params[i].attr_list.attr[j].id,
+ params->display_params[i].attr_list.attr[j].id);
+ EMGD_DEBUG(" attr[%d].value = %lu = 0x%lx", j,
+ params->display_params[i].attr_list.attr[j].value,
+ params->display_params[i].attr_list.attr[j].value);
+ }
+ }
+ EMGD_DEBUG(" display_color = %lu = 0x%lx", params->display_color,
+ params->display_color);
+ EMGD_DEBUG(" quickboot = %lu", params->quickboot);
+ EMGD_DEBUG(" qb_seamless = %d", params->qb_seamless);
+ EMGD_DEBUG(" qb_video_input = %lu", params->qb_video_input);
+ EMGD_DEBUG(" qb_splash = %d", params->qb_splash);
+ EMGD_DEBUG(" polling = %d", params->polling);
+} /* emgd_print_params() */
+
+
+/**
+ * A helper function that starts, initializes and configures the HAL. This
+ * will be called during emgd_driver_load() if the display is to be initialized
+ * at module load time. Otherwise, this is deferred till the X driver loads
+ * and calls emgd_driver_pre_init().
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h").
+ * @param params (IN) The the igd_param_t struct to give to the HAL.
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_startup_hal(struct drm_device *dev, igd_param_t *params)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ int err = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Initialize the various HAL modules: */
+ EMGD_DEBUG("Calling igd_module_init()");
+
+ err = igd_module_init(drm_HAL_handle, &drm_HAL_dispatch, params);
+ if (err != 0) {
+ return -EIO;
+ }
+
+ /* Give the dispatch table to the ioctl-handling "bridge" code: */
+ emgd_set_real_dispatch(drm_HAL_dispatch);
+
+ /* Record that the HAL is running now: */
+ priv->hal_running = 1;
+ /* Record that the console's state is saved: */
+ priv->saved_registers = CONSOLE_STATE_SAVED;
+
+ /* Since PVR services is running, we're restarting the HAL, which
+ * disabled the SGX & MSVDX interrupts. Need to re-enable those
+ * interrupts:
+ */
+ SysReEnableInterrupts();
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+} /* emgd_startup_hal() */
+
+
+
+/**
+ * A helper function that initializes the display, and potentially merges the
+ * module parameters with the pre-compiled parameters.
+ *
+ * @param merge_mod_params (IN) non-zero if the module parameters should be
+ * merged with the pre-compiled parameters.
+ *
+ */
+void emgd_init_display(int merge_mod_params, drm_emgd_priv_t *priv)
+{
+ int err = 0;
+ igd_display_info_t *mode_list = NULL;
+ igd_display_info_t *mode = NULL;
+ struct drm_framebuffer *framebuffer = NULL;
+ emgd_framebuffer_t *emgd_fb = NULL;
+ unsigned char *fb = NULL;
+ int mode_flags = IGD_QUERY_LIVE_MODES;
+ unsigned long temp_bg_color;
+ int temp_dc;
+ EMGD_TRACE_ENTER;
+
+
+ if (merge_mod_params) {
+ EMGD_DEBUG("Checking other module parameters before initializing the "
+ "display");
+
+ /*************************************
+ * Get the desired display display config:
+ *************************************/
+ if (-1 != drm_emgd_dc) {
+ /* Validate and potentially use the module parameter: */
+ EMGD_DEBUG("Value of module parameter \"dc\" = \"%d\"", drm_emgd_dc);
+ if (IGD_DC_SINGLE(drm_emgd_dc) || IGD_DC_CLONE(drm_emgd_dc) ||
+ IGD_DC_VEXT(drm_emgd_dc) || IGD_DC_EXTENDED(drm_emgd_dc)) {
+ /* Use validated value to override compile-time value: */
+ config_drm.dc = drm_emgd_dc;
+ } else if (IGD_DC_TWIN(drm_emgd_dc)) {
+ /* Use validated value to override compile-time value: */
+ EMGD_DEBUG("Module parameter \"dc\" contains unsupported value "
+ "%d.", drm_emgd_dc);
+ EMGD_DEBUG("Overriding and making it 1 (single display).");
+ drm_emgd_dc = 1;
+ config_drm.dc = drm_emgd_dc;
+ } else {
+ /* Use compile-time value: */
+ EMGD_ERROR("Module parameter \"dc\" contains invalid value "
+ "%d (must be 1, 2, 5 or 8).", drm_emgd_dc);
+ if (config_drm.dc == 4) {
+ EMGD_DEBUG("Compile-time setting for module parameter "
+ "\"dc\" contains unsupported value %d.", config_drm.dc);
+ EMGD_DEBUG("Overriding and making it 1 (single display).");
+
+ config_drm.dc = 1;
+ } else {
+ EMGD_ERROR("Will use compile-time setting %d instead "
+ "of invalid value %d.\n", config_drm.dc, drm_emgd_dc);
+ }
+ drm_emgd_dc = config_drm.dc;
+ }
+ } else {
+ /* Check and potentially use the compile-time value: */
+ if (IGD_DC_SINGLE(config_drm.dc) || IGD_DC_CLONE(config_drm.dc) ||
+ IGD_DC_VEXT(config_drm.dc) ||
+ IGD_DC_EXTENDED(config_drm.dc)) {
+ /* Report the compile-time value: */
+ EMGD_DEBUG("Using compile-time setting for the module parameter"
+ " \"dc\" = \"%d\"", config_drm.dc);
+ } else if (IGD_DC_TWIN(config_drm.dc)) {
+ EMGD_DEBUG("Compile-time setting for module parameter "
+ "\"dc\" contains unsupported value %d.", config_drm.dc);
+ EMGD_DEBUG("Overriding and making it 1 (single display).");
+ config_drm.dc = 1;
+ } else {
+ EMGD_DEBUG("Compile-time setting for module parameter "
+ "\"dc\" contains invalid value %d.", config_drm.dc);
+ EMGD_DEBUG("Must be 1, 2, 5 or 8. Making it 1 (single"
+ " display).");
+ config_drm.dc = 1;
+ }
+ drm_emgd_dc = config_drm.dc;
+ }
+
+ /*************************************
+ * Get the desired display "width":
+ *************************************/
+ if (-1 != drm_emgd_width) {
+ /* Override the compile-time value with the module parameter: */
+ EMGD_DEBUG("Using the \"width\" module parameter: \"%d\"",
+ drm_emgd_width);
+ config_drm.width = drm_emgd_width;
+ } else {
+ /* Use the compile-time value: */
+ drm_emgd_width = config_drm.width;
+ EMGD_DEBUG("Using the compile-time \"width\" value: \"%d\"",
+ drm_emgd_width);
+ }
+
+ /*************************************
+ * Get the desired display "height":
+ *************************************/
+ if (-1 != drm_emgd_height) {
+ /* Override the compile-time value with the module parameter: */
+ EMGD_DEBUG("Using the \"height\" module parameter: \"%d\"",
+ drm_emgd_height);
+ config_drm.height = drm_emgd_height;
+ } else {
+ /* Use the compile-time value: */
+ drm_emgd_height = config_drm.height;
+ EMGD_DEBUG("Using the compile-time \"height\" value: \"%d\"",
+ drm_emgd_height);
+ }
+
+ /*************************************
+ * Get the desired display "refresh":
+ *************************************/
+ if (-1 != drm_emgd_refresh) {
+ /* Override the compile-time value with the module parameter: */
+ EMGD_DEBUG("Using the \"refresh\" module parameter: \"%d\"",
+ drm_emgd_refresh);
+ config_drm.refresh = drm_emgd_refresh;
+ } else {
+ /* Use the compile-time value: */
+ drm_emgd_refresh = config_drm.refresh;
+ EMGD_DEBUG("Using the compile-time \"refresh\" value: \"%d\"",
+ drm_emgd_refresh);
+ }
+ }
+
+
+ if (config_drm.kms) {
+ priv->num_crtc = 2;
+
+
+ /*************************************
+ * Initialize kernel mode setting functionality
+ *************************************/
+ emgd_modeset_init(priv->ddev);
+
+ /* Get Display context */
+ drm_HAL_context->mod_dispatch.dsp_get_dc(NULL,
+ (igd_display_context_t **) &primary,
+ (igd_display_context_t **) &secondary);
+
+
+ /*************************************
+ * Initialize primary_fb_info
+ *************************************/
+ framebuffer = list_entry(priv->ddev->mode_config.fb_list.next,
+ struct drm_framebuffer, head);
+ if (!framebuffer) {
+ EMGD_ERROR("Can't display splash screen/video as there is no fb.");
+ } else {
+ emgd_fb = container_of(framebuffer, emgd_framebuffer_t, base);
+ primary_fb_info = &priv->initfb_info;
+ if (priv->fbdev) {
+ fb = priv->fbdev->screen_base;
+ }
+ }
+
+
+ /*
+ * Update the private data structure
+ */
+ priv->primary = primary;
+ priv->secondary = secondary;
+ priv->primary_port_number = IGD_DC_PRIMARY(priv->dc);
+ priv->secondary_port_number = IGD_DC_SECONDARY(priv->dc);
+ } else {
+
+ /**************************************************************************
+ * Special case handling: Since HAL doesn't know anything about Vertical
+ * extended mode, if we are in Vertical Extended (5), send HAL asking for
+ * (2)
+ *************************************************************************/
+ temp_dc = drm_emgd_dc;
+ if(IGD_DC_VEXT(drm_emgd_dc)) {
+ temp_dc = IGD_DISPLAY_CONFIG_CLONE;
+ }
+
+ /*************************************
+ * Query the DC list (use first one):
+ *************************************/
+ EMGD_DEBUG("Calling query_dc()");
+ err = drm_HAL_dispatch->query_dc(drm_HAL_handle, temp_dc,
+ &desired_dc, IGD_QUERY_DC_INIT);
+ EMGD_DEBUG("query_dc() returned %d", err);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize the display as requested.\n"
+ "The query_dc() function returned %d.", err);
+ return;
+ }
+ port_number = (*desired_dc & 0xf0) >> 4;
+ EMGD_DEBUG("Using DC 0x%lx with port number %d",
+ *desired_dc, port_number);
+ if(IGD_DC_VEXT(drm_emgd_dc)) {
+ drm_emgd_dc = (*desired_dc & ~IGD_DISPLAY_CONFIG_CLONE) |
+ IGD_DISPLAY_CONFIG_VEXT;
+ }
+
+ /*************************************
+ * Query the mode list:
+ *************************************/
+ EMGD_DEBUG("Calling query_mode_list()");
+ err = drm_HAL_dispatch->query_mode_list(drm_HAL_handle, *desired_dc,
+ &mode_list, mode_flags);
+ EMGD_DEBUG("query_mode_list() returned %d", err);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize the display as requested\n"
+ "The query_mode_list() function returned %d.", err);
+ return;
+ }
+
+
+ /*************************************
+ * Find the desired mode from the list:
+ *************************************/
+ EMGD_DEBUG("Comparing the mode list with the desired width, height, and"
+ " refresh rate...");
+
+ mode = mode_list;
+ while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+ EMGD_DEBUG(" ...Found a mode with width=%d, height=%d, refresh=%d;",
+ mode->width, mode->height, mode->refresh);
+ if ((mode->width == drm_emgd_width) &&
+ (mode->height == drm_emgd_height) &&
+ (mode->refresh == drm_emgd_refresh)) {
+ EMGD_DEBUG(" ... This mode is a match!");
+ desired_mode = mode;
+ break;
+ }
+ mode++;
+ }
+ if (NULL == desired_mode) {
+ EMGD_ERROR("Cannot initialize the display as requested.");
+ EMGD_ERROR("No mode matching the desired width (%d), height "
+ "(%d), and refresh rate (%d) was found.",
+ drm_emgd_width, drm_emgd_height, drm_emgd_refresh);
+ return;
+ } else {
+ /* Must set this in order to get the timings setup: */
+ desired_mode->flags |= IGD_DISPLAY_ENABLE;
+ }
+
+ /*************************************
+ * Call alter_displays():
+ *************************************/
+ primary_fb_info = kzalloc(sizeof(igd_framebuffer_info_t), GFP_KERNEL);
+ secondary_fb_info = kzalloc(sizeof(igd_framebuffer_info_t), GFP_KERNEL);
+ primary_fb_info->width = desired_mode->width;
+
+ /*************************************
+ * Special for Vertical Extended, double the height
+ *************************************/
+ if(IGD_DC_VEXT(drm_emgd_dc)) {
+ primary_fb_info->height = desired_mode->height * 2;
+ } else {
+ primary_fb_info->height = desired_mode->height;
+ }
+ primary_fb_info->pixel_format = IGD_PF_ARGB32;
+ primary_fb_info->flags = 0;
+ primary_fb_info->allocated = 0;
+ memcpy(secondary_fb_info, primary_fb_info,
+ sizeof(igd_framebuffer_info_t));
+
+ EMGD_DEBUG("Calling alter_displays()");
+ err = drm_HAL_dispatch->alter_displays(drm_HAL_handle,
+ &primary, desired_mode, primary_fb_info,
+ &secondary, desired_mode, secondary_fb_info,
+ *desired_dc, 0);
+ EMGD_DEBUG("alter_displays() returned %d", err);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize the display as requested.\n"
+ "The alter_displays() function returned %d.", err);
+ return;
+ }
+
+ /*
+ * Update the private data structure with the values we get
+ * back from alter displays.
+ */
+ priv->dc = *desired_dc;
+ priv->primary = primary;
+ priv->secondary = secondary;
+ priv->primary_port_number = IGD_DC_PRIMARY(*desired_dc);
+ priv->secondary_port_number = IGD_DC_SECONDARY(*desired_dc);
+
+ /*************************************
+ * Special for Vertical Extended, pan the second display
+ *************************************/
+ if(IGD_DC_VEXT(drm_emgd_dc)) {
+ drm_HAL_dispatch->pan_display(secondary, 0,
+ secondary_fb_info->height / 2);
+ }
+
+ /*************************************
+ * Call get_display():
+ *************************************/
+ EMGD_DEBUG("Calling get_display()");
+ err = drm_HAL_dispatch->get_display(primary, port_number,
+ primary_fb_info, &pt_info, 0);
+ EMGD_DEBUG("get_display() returned %d", err);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize the display as requested\n"
+ "The get_display() function returned %d.", err);
+ return;
+ }
+
+ /*************************************
+ * Get FB virtual address
+ *************************************/
+ EMGD_DEBUG("Calling full_clear_fb()");
+ fb = mode_context->context->dispatch.gmm_map(
+ primary_fb_info->fb_base_offset);
+ }
+
+ if (fb) {
+
+ /*************************************
+ * Set the framebuffer to the background color:
+ *************************************/
+ temp_bg_color = mode_context->display_color;
+ mode_context->display_color = config_drm.ss_data->bg_color;
+ if(mode_context->seamless == FALSE)
+ {
+ full_clear_fb(mode_context, primary_fb_info, fb);
+ }
+ mode_context->display_color = temp_bg_color;
+
+ /*************************************
+ * Display a splash screen if requested by user
+ *************************************/
+ if(config_drm.ss_data->width &&
+ config_drm.ss_data->height) {
+
+ /* Display a splash screen */
+ printk(KERN_ERR "[EMGD] Display splash screen image.\n");
+ EMGD_DEBUG("Calling disp_splash_screen()");
+ display_splash_screen(primary_fb_info, fb, config_drm.ss_data);
+ }
+
+ /*************************************
+ * Display a splash video if requested by user
+ *************************************/
+ if(config_drm.sv_data->pixel_format &&
+ config_drm.sv_data->src_width &&
+ config_drm.sv_data->src_height &&
+ config_drm.sv_data->src_pitch &&
+ config_drm.sv_data->dst_width &&
+ config_drm.sv_data->dst_height) {
+
+ /* Display a splash video */
+ EMGD_DEBUG("Calling disp_splash_video()");
+ disp_splash_video(config_drm.sv_data);
+ }
+ } else {
+ EMGD_ERROR("framebuffer base address is 0");
+ }
+ mode_context->seamless = FALSE;
+
+ if (!config_drm.kms) {
+ mode_context->context->dispatch.gmm_unmap(fb);
+ }
+ EMGD_TRACE_EXIT;
+} /* emgd_init_display() */
+
+
+
+/**
+ * Function to display a splash video to the user. The splash video data must be
+ * provided to the kernel mode driver by another entity (like a driver or FPGA
+ * HW). Splash video will be display after setting the mode (if requested by
+ * the user through config options).
+ *
+ * @param sv_data (IN) a non null pointer to splash video information like
+ * width, height etc.
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int disp_splash_video(emgd_drm_splash_video_t *sv_data)
+{
+ igd_surface_t surface;
+ igd_rect_t ovl_rect, surf_rect;
+ igd_ovl_info_t ovl_info;
+ unsigned int tmp;
+
+ surface.offset = sv_data->offset;
+ surface.pitch = sv_data->src_pitch;
+ surface.width = sv_data->src_width;
+ surface.height = sv_data->src_height;
+ surface.pixel_format = sv_data->pixel_format;
+ surface.flags = IGD_SURFACE_OVERLAY;
+
+ /* Set the surface rect as big as the video frame size */
+ surf_rect.x1 = 0;
+ surf_rect.y1 = 0;
+ surf_rect.x2 = sv_data->src_width;
+ surf_rect.y2 = sv_data->src_height;
+
+
+ /* The x,y postion of the sprite c */
+ ovl_rect.x1 = sv_data->dst_x;
+ ovl_rect.y1 = sv_data->dst_y;
+
+ /*
+ * NOTE: This for scaling if the hardware supports it.
+ * If no dest w x h values are set,set it the the
+ * src w x h
+ */
+ tmp = sv_data->dst_width ? sv_data->dst_width : sv_data->src_width;
+
+ ovl_rect.x2 = ovl_rect.x1 + tmp;
+
+ tmp = sv_data->dst_height?
+ sv_data->dst_height:
+ sv_data->src_height;
+
+ ovl_rect.y2 = ovl_rect.y1 + tmp;
+
+ /*
+ * If no values are set, set it to default
+ */
+ ovl_info.video_quality.brightness =
+ config_drm.ovl_brightness ?
+ config_drm.ovl_brightness : 0x8000;
+ ovl_info.video_quality.contrast =
+ config_drm.ovl_contrast ?
+ config_drm.ovl_contrast : 0x8000;
+ ovl_info.video_quality.saturation =
+ config_drm.ovl_saturation ?
+ config_drm.ovl_saturation : 0x8000;
+ ovl_info.video_quality.hue =
+ config_drm.ovl_hue ?
+ config_drm.ovl_hue : 0x8000;
+
+ /*
+ * If any values are set for gamma, turn on the gamma flags
+ */
+ ovl_info.gamma.red = config_drm.ovl_gamma_red;
+ ovl_info.gamma.green = config_drm.ovl_gamma_green;
+ ovl_info.gamma.blue = config_drm.ovl_gamma_blue;
+
+ if(ovl_info.gamma.red || ovl_info.gamma.green || ovl_info.gamma.blue) {
+
+ ovl_info.gamma.flags = IGD_OVL_GAMMA_ENABLE;
+ }
+
+ drm_HAL_dispatch->alter_ovl(drm_HAL_handle, NULL,
+ &surface,
+ &surf_rect,
+ &ovl_rect,
+ &ovl_info, IGD_OVL_ALTER_ON);
+
+ return 0;
+}
+
+
+
+/**
+ * This is the drm_driver.load() function. It is called when the DRM "loads"
+ * (i.e. when our driver loads, it calls drm_init(), which eventually causes
+ * this driver function to be called).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param flags (IN) The last member of the pci_device_id struct that we
+ * fill-in at the top of this file (e.g. CHIP_PSB_8108).
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_driver_load(struct drm_device *dev, unsigned long flags)
+{
+ int i, err = 0;
+ igd_param_t *params;
+ drm_emgd_priv_t *priv = NULL;
+ igd_init_info_t *init_info;
+ int num_hal_params =
+ sizeof(config_drm.hal_params) / sizeof(config_drm.hal_params[0]);
+
+
+ EMGD_TRACE_ENTER;
+
+ mutex_lock(&dev->struct_mutex);
+
+ /**************************************************************************
+ *
+ * Get the compile-time/module-parameter "params" before initializing the
+ * HAL:
+ *
+ **************************************************************************/
+
+ /*************************************
+ * Take into account the "configid" module parameter:
+ *************************************/
+ if (num_hal_params <= 0) {
+ EMGD_ERROR("The compile-time configuration (in \"user_config.c\")\n"
+ "contains no igd_param_t structures. Please fix and recompile.");
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+ if ((drm_emgd_configid == 0) ||
+ (drm_emgd_configid > num_hal_params)) {
+ EMGD_ERROR("Module parameter \"configid\" contains invalid value "
+ "%d.\nMust specify a compile-time configuration (in "
+ "\"user_config.c\"),\nnumbered between 1 and %d.\n",
+ drm_emgd_configid, num_hal_params);
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
+ }
+
+ /* Obtain the user-configurable set of parameter values: */
+ if (drm_emgd_configid < 0) {
+ params = config_drm.hal_params[0];
+ } else {
+ params = config_drm.hal_params[drm_emgd_configid-1];
+ }
+
+
+ /*************************************
+ * Take into account the "portorder" module parameter:
+ *************************************/
+ err = 0;
+ EMGD_DEBUG("Determining desired port order:");
+ if (0 == drm_emgd_numports) {
+ /* Set this to 1 so we use the compile-time value below: */
+ err = 1;
+ drm_emgd_numports = IGD_MAX_PORTS;
+ } else if (drm_emgd_numports != IGD_MAX_PORTS) {
+ EMGD_ERROR("Module parameter \"portorder\" specifies %d ports "
+ "(must specify %d in a comma-separated list).",
+ drm_emgd_numports, IGD_MAX_PORTS);
+ drm_emgd_numports = IGD_MAX_PORTS;
+ err = -EINVAL;
+ }
+ if (!err) {
+ /* Validate each port within the module parameter: */
+ for (i = 0 ; i < drm_emgd_numports ; i++) {
+ if ((drm_emgd_portorder[i] < 0) ||
+ (drm_emgd_portorder[i] > 5)) {
+ EMGD_ERROR("Item %d in module parameter \"portorder\" "
+ "contains invalid value %d (must be between 0 and 5).",
+ i, drm_emgd_portorder[i]);
+ err = -EINVAL;
+ }
+ }
+ }
+ if (!err) {
+ /* Override the compile-time value with the module parameter: */
+ for (i = 0 ; i < drm_emgd_numports ; i++) {
+ params->port_order[i] = drm_emgd_portorder[i];
+ }
+ EMGD_DEBUG("Using the \"portorder\" module parameter: \"%d, %d, %d, "
+ "%d, %d\"", drm_emgd_portorder[0], drm_emgd_portorder[1],
+ drm_emgd_portorder[2], drm_emgd_portorder[3],
+ drm_emgd_portorder[4]);
+ } else {
+ /* Use the compile-time value: */
+ for (i = 0 ; i < drm_emgd_numports ; i++) {
+ drm_emgd_portorder[i] = params->port_order[i];
+ }
+ EMGD_DEBUG("Using the compile-time \"portorder\" value: \"%d, %d, "
+ "%d, %d, %d\"", drm_emgd_portorder[0], drm_emgd_portorder[1],
+ drm_emgd_portorder[2], drm_emgd_portorder[3],
+ drm_emgd_portorder[4]);
+ err = 0;
+ }
+
+
+ emgd_print_params(params);
+
+
+ /**************************************************************************
+ *
+ * Minimally initialize and configure the driver, deferring as much as
+ * possible until the X driver starts.:
+ *
+ **************************************************************************/
+
+ /* Determine whether display initialization is desired: */
+ if (-1 != drm_emgd_init) {
+ /* Validate and potentially use the module parameter: */
+ if (!((drm_emgd_init == 1) || (drm_emgd_init == 0))) {
+ EMGD_ERROR("Module parameter \"init\" contains invalid "
+ "value %d (must be 0 or 1).", drm_emgd_init);
+ drm_emgd_init = config_drm.init;
+ EMGD_ERROR("Using the compile-time \"init\" value: \"%d\"",
+ drm_emgd_init);
+ } else {
+ /* Override the compile-time value with the module parameter: */
+ config_drm.init = drm_emgd_init;
+ EMGD_DEBUG("Using the \"init\" module parameter: \"%d\"",
+ drm_emgd_init);
+ }
+ } else {
+ /* Use the compile-time value: */
+ drm_emgd_init = config_drm.init;
+ EMGD_DEBUG("Using the compile-time \"init\" value: \"%d\"",
+ drm_emgd_init);
+ }
+
+
+ /*
+ * In order for some early ioctls (e.g. emgd_get_chipset_info()) to work,
+ * we must do the following minimal initialization.
+ */
+ EMGD_DEBUG("Calling igd_driver_init()");
+ init_info = (igd_init_info_t *)OS_ALLOC(sizeof(igd_init_info_t));
+ drm_HAL_handle = igd_driver_init(init_info);
+ if (drm_HAL_handle == NULL) {
+ OS_FREE(init_info);
+ mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+
+ /* Get the HAL context and give it to the ioctl-handling "bridge" code: */
+ drm_HAL_context = (igd_context_t *) drm_HAL_handle;
+ emgd_set_real_handle(drm_HAL_handle);
+
+ /* Save the drm dev pointer, it's needed by igd_module_init */
+ drm_HAL_context->drm_dev = dev;
+
+ /* Create the private structure used to communicate to the IMG 3rd-party
+ * display driver:
+ */
+ priv = OS_ALLOC(sizeof(drm_emgd_priv_t));
+ if (NULL == priv) {
+ OS_FREE(init_info);
+ mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+
+
+ OS_MEMSET(priv, 0, sizeof(drm_emgd_priv_t));
+ priv->hal_running = 0;
+ priv->context = drm_HAL_context;
+ priv->init_info = init_info;
+ priv->qb_seamless = params->qb_seamless;
+ dev->dev_private = priv;
+ priv->ddev = dev;
+ priv->kms_enabled = 0;
+
+
+ /* Do basic driver initialization & configuration: */
+ EMGD_DEBUG("Calling igd_driver_config()");
+ err = igd_driver_config(drm_HAL_handle);
+ if (err != 0) {
+ OS_FREE(init_info);
+ OS_FREE(priv);
+ OS_FREE(drm_HAL_handle);
+ mutex_unlock(&dev->struct_mutex);
+ return -EIO;
+ }
+
+ // PVRSRVDrmLoad() sets up an ISR routine with a pointer to drm_device to be passed every time. This variable (gpDrmDevice) is initialized in msvdx_pre_init_plb only.
+ // Due to this reason, msvdx_pre_init_plb() is moved before PVRSRVDrmLoad().
+
+ /* Init MSVDX and load firmware */
+ msvdx_pre_init_plb(dev);
+
+ /* Initialize the PVR services if not already initialized */
+ printk(KERN_INFO "Initializing PVR Services.\n");
+ PVRSRVDrmLoad(dev, 0);
+
+ /* Decide if we can defer the rest of the initialization */
+ if (config_drm.init) {
+
+ if (config_drm.kms) {
+ params->preserve_regs = 1;
+ priv->kms_enabled = 1;
+ }
+
+ /* Initialize and configure the driver now */
+ err = emgd_startup_hal(dev, params);
+ if (err != 0) {
+ OS_FREE(init_info);
+ OS_FREE(priv);
+ OS_FREE(drm_HAL_handle);
+ mutex_unlock(&dev->struct_mutex);
+ return err;
+ }
+
+ /* This will get the plane, pipe and port register values and fill up the
+ * fw_info data structure. This needs to be done at INIT time before the
+ * user-mode driver loads
+ */
+ get_pre_driver_info(mode_context);
+
+ /* Per the user's request, initialize the display: */
+ emgd_init_display(TRUE, priv);
+ }
+
+
+
+#ifdef DEBUG_BUILD_TYPE
+ /* Turn on KMS debug messages in the general DRM module if our OAL
+ * messages are on and it's a debug driver.
+ */
+ if (emgd_debug->hal.oal) {
+ drm_debug |= DRM_UT_KMS;
+ }
+#endif
+
+#ifdef SUPPORT_V2G_CAMERA
+ /* to start v2g camera module */
+ if (1 == config_drm.v2g) {
+ EMGD_DEBUG("V2G Camera Enabled.");
+ if (0 == v2g_start_camera()) {
+ EMGD_DEBUG("v2g camera started successfully!");
+ } else {
+ EMGD_ERROR("Fail to start v2g camera!");
+ }
+ }
+#endif
+ /* can not work out how to start PVRSRV */
+ /* Load Buffer Class Module*/
+ emgd_bc_ts_init();
+
+ mutex_unlock(&dev->struct_mutex);
+ EMGD_TRACE_EXIT;
+
+ return 0;
+} /* emgd_driver_load() */
+
+
+/**
+ * This is the drm_driver.unload() function. It is called when the DRM
+ * "unloads." That is, drm_put_dev() (in "drm_stub.c"), which is called by
+ * drm_exit() (in "drm_drv.c"), calls this function.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_driver_unload(struct drm_device *dev)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ unsigned long save_flags = 0;
+
+ EMGD_TRACE_ENTER;
+
+ mutex_lock(&dev->struct_mutex);
+
+ /* Unload Buffer Class Module*/
+ emgd_bc_ts_uninit();
+
+ PVRSRVDrmUnload(dev);
+
+ /* KMS cleanup */
+ if (config_drm.init && config_drm.kms) {
+ emgd_modeset_destroy(dev);
+ }
+
+ if (priv->hal_running) {
+ /* igd_driver_shutdown() will restore the then-currently-saved register
+ * state. We can't rely on any save_restore() calls before that time,
+ * because igd_driver_shutdown() does things that mess up the register
+ * state. Thus, we must allow it to do a restore. The only way to
+ * control the final state of the hardware is to potentially do a
+ * save_restore now. Thus, if the X server's state is currently saved
+ * (i.e. the console's state is currently active), we must do a
+ * save_restore now, so that this state will still exist after
+ * igd_driver_shutdown().
+ */
+ if (priv->saved_registers == CONSOLE_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the console's saved register state");
+
+ save_flags = IGD_REG_SAVE_ALL;
+ drm_HAL_dispatch->driver_save_restore(drm_HAL_handle, save_flags);
+ EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
+ priv->saved_registers = X_SERVER_STATE_SAVED;
+ }
+ igd_driver_shutdown_hal(drm_HAL_handle);
+ igd_driver_shutdown(drm_HAL_handle);
+ } else {
+ /* Do safe cleanup that would've been done by igd_driver_shutdown() */
+ igd_driver_shutdown(drm_HAL_handle);
+ }
+
+ if (!config_drm.kms) {
+ kfree(primary_fb_info);
+ kfree(secondary_fb_info);
+ }
+
+ OS_FREE(priv->init_info);
+ OS_FREE(priv);
+
+ /* Note: This macro is #define'd in "oal/os/memory.h" */
+#ifdef INSTRUMENT_KERNEL_ALLOCS
+ emgd_report_unfreed_memory();
+#endif
+
+ mutex_unlock(&dev->struct_mutex);
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+} /* emgd_driver_unload() */
+
+
+/**
+ * This is the drm_driver.open() function. It is called when a user-space
+ * process opens the DRM device file. The DRM drm_open() (in "drm_fops.c")
+ * calls drm_open_helper(), which calls this function.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param priv (IN) DRM's file private data struct (in "drmP.h")
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_driver_open(struct drm_device *dev, struct drm_file *priv)
+{
+ int ret = 0;
+ drm_emgd_priv_t *emgd_priv = dev->dev_private;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Under the latest MeeGo images, something is trying to open the DRM device
+ * while we're still inside the the load() function (possibly an updated
+ * copy of udev?). Don't let open() calls through here until
+ * initialization is finished. If userspace can overlap load() and open(),
+ * then it stands to reason that we might also wind up racing with close()
+ * and unload() as well, so let's protect all of those operations by
+ * grabbing the mutex.
+ *
+ * FIXME: Should we do the same for other operations like suspend/resume/etc?
+ */
+ mutex_lock(&dev->struct_mutex);
+
+ /* The is_master flag is set after the call to this function, so there needs
+ * to be manual check to determine the DRM master */
+ if(priv->is_master || (!priv->minor->master && !emgd_priv->drm_master_fd)) {
+ emgd_priv->drm_master_fd = priv;
+ }
+
+ ret = PVRSRVOpen(dev, priv);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* emgd_driver_open() */
+
+
+/**
+ * This is the drm_driver.lastclose() function. It is called when the last
+ * user-space process closes/releases the DRM device file. At end of DRM
+ * drm_release() (in "drm_fops.c"), it calls drm_lastclose() (in "drm_drv.c"),
+ * which calls this function.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ */
+void emgd_driver_lastclose(struct drm_device *dev)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_init_info_t *init_info = priv->init_info;
+ int err = 0;
+ unsigned long restore_flags = 0;
+
+ EMGD_TRACE_ENTER;
+
+ mutex_lock(&dev->struct_mutex);
+
+
+ if (priv->hal_running) {
+ if (config_drm.init) {
+ if( x_started ) {
+
+ restore_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT)
+ | IGD_REG_SAVE_TYPE_REG;
+
+ if (!config_drm.kms) {
+ restore_flags &= ~IGD_REG_SAVE_RB;
+ }
+
+
+ if (priv->saved_registers == CONSOLE_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the console's saved "
+ "register state");
+ drm_HAL_dispatch->driver_save_restore(drm_HAL_handle,
+ restore_flags);
+ EMGD_DEBUG("State of saved registers is "
+ "X_SERVER_STATE_SAVED");
+ priv->saved_registers = X_SERVER_STATE_SAVED;
+ }
+
+ if (priv->saved_registers == X_SERVER_STATE_SAVED &&
+ !config_drm.kms && !priv->qb_seamless) {
+ emgd_init_display(FALSE, priv);
+ }
+
+ if (priv->saved_registers == CONSOLE_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the console's saved register "
+ "state");
+ drm_HAL_dispatch->driver_save_restore(drm_HAL_handle,
+ restore_flags);
+ EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
+ priv->saved_registers = X_SERVER_STATE_SAVED;
+ }
+
+ /* Since an alter_displays() was done, re-init the 3DD: */
+ if (priv->reinit_3dd) {
+ priv->reinit_3dd(dev);
+ }
+
+ x_started = false;
+ }
+ } else {
+ /* The X server has quit/crashed. If the console's state is
+ * currently saved (likely) restore that state, so that the console
+ * can be seen and work.
+ */
+ context_count = 0;
+ priv->dc = 0; /* Don't let the 3DD re-init too early: */
+ if (priv->saved_registers == CONSOLE_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the console's saved register "
+ "state");
+ restore_flags = IGD_REG_SAVE_ALL;
+
+ drm_HAL_dispatch->driver_save_restore(drm_HAL_handle,
+ restore_flags);
+ EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
+ priv->saved_registers = X_SERVER_STATE_SAVED;
+ }
+
+ /******************************************************************
+ * Shutdown and minimally-restart the HAL, so that if/when the X
+ * server starts again, the HAL will be started again. This will
+ * allow the necessary port drivers to be loaded, all configuration
+ * parameters to be used, the EDID to be read again (e.g. because
+ * the user may have switched monitors), etc.
+ *
+ * However, keeep the DRM driver state around, so that the driver
+ * can continue to work (i.e. re-enter the state when the DRM
+ * driver was first loaded).
+ *
+ * Also, keep the PVR services up and going, since it wasn't
+ * designed to be shutdown and restarted (without doing an
+ * rmmod/insmod).
+ ******************************************************************/
+ EMGD_DEBUG("Shutting down the HAL");
+
+ /* igd_driver_shutdown() will restore the then-currently-saved
+ * register state. We can't rely on any save_restore() calls
+ * before that time, because igd_driver_shutdown() does things that
+ * mess up the register state. Thus, we must allow it to do a
+ * restore. The only way to control the final state of the
+ * hardware is to potentially do a save_restore now. Thus, if the
+ * X server's state is currently saved (i.e. the console's state is
+ * currently active), we must do a save_restore now, so that this
+ * state will still exist after igd_driver_shutdown().
+ */
+ if (priv->saved_registers == X_SERVER_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the console's saved register "
+ "state");
+ restore_flags = IGD_REG_SAVE_ALL;
+ drm_HAL_dispatch->driver_save_restore(drm_HAL_handle,
+ restore_flags);
+ EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
+ priv->saved_registers = CONSOLE_STATE_SAVED;
+ }
+ msvdx_shutdown_plb(drm_HAL_handle);
+ topaz_shutdown_tnc(drm_HAL_handle);
+
+ igd_driver_shutdown_hal(drm_HAL_handle);
+ igd_driver_shutdown(drm_HAL_handle);
+
+ EMGD_DEBUG("Minimally restarting the HAL--like load-time");
+ /*
+ * In order for some early ioctls (e.g. emgd_get_chipset_info()) to
+ * work, we must do the following minimal initialization.
+ */
+ EMGD_DEBUG("Calling igd_driver_init()");
+ if(init_info == NULL){
+ init_info = (igd_init_info_t *)OS_ALLOC(sizeof(igd_init_info_t));
+ }
+ drm_HAL_handle = igd_driver_init(init_info);
+ if (drm_HAL_handle == NULL) {
+ /* This shouldn't happen, but if it does, alert the user, as
+ * the only thing to do is to rmmod/insmod emgd.ko, or to
+ * reboot:
+ */
+ OS_FREE(init_info);
+ printk(KERN_ALERT "[EMGD] Failed to restart the EMGD graphics "
+ "HAL\n");
+ mutex_unlock(&dev->struct_mutex);
+ return;
+ }
+
+ /* Get the HAL context and give it to the ioctl-handling "bridge"
+ * code:
+ */
+ drm_HAL_context = (igd_context_t *) drm_HAL_handle;
+ emgd_set_real_handle(drm_HAL_handle);
+
+ /* Save the drm dev pointer, it's needed by igd_module_init */
+ drm_HAL_context->drm_dev = dev;
+
+ /* Reset part of the private structure used to communicate to the
+ * IMG 3rd-party display driver:
+ */
+ priv->saved_registers = 0;
+ priv->suspended_state = NULL;
+ priv->must_power_on_ports = 0;
+ priv->xserver_running = 0;
+ priv->primary_port_number = 0;
+ priv->primary = NULL;
+ priv->secondary_port_number = 0;
+ priv->secondary = NULL;
+ priv->msvdx_private = NULL;
+ priv->hal_running = 0;
+ priv->context = drm_HAL_context;
+ priv->init_info = init_info;
+
+
+ /* Do basic driver initialization & configuration: */
+ EMGD_DEBUG("Calling igd_driver_config()");
+ err = igd_driver_config(drm_HAL_handle);
+ if (err != 0) {
+ /* This shouldn't happen, but if it does, alert the user, as
+ * the only thing to do is to rmmod/insmod emgd.ko, or to
+ * reboot:
+ */
+ OS_FREE(init_info);
+ printk(KERN_ALERT "[EMGD] Failed to restart the EMGD graphics "
+ "HAL.\n");
+ mutex_unlock(&dev->struct_mutex);
+ return;
+ }
+
+ /* To ensure the devinfo->interrupt_h is NULL, call the
+ * following:
+ */
+ if (priv->reinit_3dd) {
+ priv->reinit_3dd(dev);
+ }
+ }
+ }
+
+ mutex_unlock(&dev->struct_mutex );
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_driver_lastclose() */
+
+
+/**
+ * This is the drm_driver.preclose() function. It is called when a user-space
+ * process closes/releases the DRM device file. At the very start of DRM
+ * drm_release() (in "drm_fops.c"), it calls this function, before it does any
+ * real work (other than get the lock).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param priv (IN) DRM's file private data struct (in "drmP.h")
+ */
+void emgd_driver_preclose(struct drm_device *dev, struct drm_file *priv)
+{
+ drm_emgd_priv_t *emgd_priv = dev->dev_private;
+
+ /* Notes on what to implement in this function. What this
+ * function does is largely influenced by when/why this can be called:
+ *
+ * - We can determine whether the connection was for the X driver vs. for a
+ * 3D application, because the X driver should be the master.
+ *
+ * - If there's any state management we need to take care of (e.g. if the
+ * X server crashes while there are still 3D app's running), this is
+ * probably a good place to do it.
+ *
+ * - Normal 3D app shutdown is probably best done here too (simply
+ * because we can tell it's a 3D connection, and do our work before the
+ * general drm_release() code does its work.
+ *
+ * - We don't yet know what the IMG 3D code is going to need.
+ *
+ * We don't yet know what we need to do for the IMG code. Thus, I'm
+ * inclined to leave this function a stub for now.
+ */
+
+ EMGD_TRACE_ENTER;
+ mutex_lock(&dev->struct_mutex);
+ if ((emgd_priv->hal_running) && priv->is_master && drm_HAL_dispatch) {
+ /* The X server can't call gmm_cache_flush() nor igd_driver_shutdown()
+ * after DRICloseScreen() closes the connection with the DRM. However,
+ * we can tell on this side of the connection (because the X server is
+ * the master) that it is closing down. There is no need to truly shut
+ * down the HAL, but we can flush the GMM cache and reset the display
+ * hardware to a known state/mode:
+ */
+ drm_HAL_dispatch->gmm_flush_cache();
+
+ /* TODO - WRITE CODE THAT PUTS THE DISPLAY HW IN A KNOWN STATE/MODE */
+ }
+
+ if (emgd_priv->drm_master_fd == priv)
+ emgd_priv->drm_master_fd = NULL;
+
+ mutex_unlock(&dev->struct_mutex);
+ EMGD_TRACE_EXIT;
+
+ /* TODO -- ADD ANYTHING WE DISCOVER WE NEED AFTER THE IMG TRAINING */
+
+} /* emgd_driver_preclose() */
+
+
+/**
+ * This is the drm_driver.postclose() function. It is called when a user-space
+ * process closes/releases the DRM device file. At the end of DRM
+ * drm_release() (in "drm_fops.c"), but before drm_lastclose is optionally
+ * called, it calls this function.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param priv (IN) DRM's file private data struct (in "drmP.h")
+ */
+void emgd_driver_postclose(struct drm_device *dev, struct drm_file *priv)
+{
+ int ret = 0;
+ drm_emgd_priv_t *dev_priv = dev->dev_private;
+ igd_context_t *context = dev_priv->context;
+
+ EMGD_TRACE_ENTER;
+ mutex_lock(&dev->struct_mutex);
+
+ /* Calling the msvdx_postclose_check before PVRSRVRelease */
+ if (priv) {
+ msvdx_postclose_check(context, (void *) priv);
+ }
+
+ ret = PVRSRVRelease(dev, priv);
+
+ mutex_unlock(&dev->struct_mutex);
+ EMGD_TRACE_EXIT;
+} /* emgd_driver_postclose() */
+
+
+/**
+ * This is the drm_driver.suspend() function. It appears to support what the
+ * Linux "pm.h" file calls "the legacy suspend framework." The DRM
+ * drm_class_suspend() (in "drm_sysfs.c", which implements the Linux
+ * class.suspend() function defined in "device.h") calls this function if
+ * conditions are met, such as drm_minor->type is DRM_MINOR_LEGACY and the
+ * driver doesn't have the DRIVER_MODESET (i.e. KMS--Kernel Mode Setting)
+ * feature set.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param state (IN) What power state to put the device in (in "pm.h")
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_driver_suspend(struct drm_device *dev, pm_message_t state)
+{
+ int ret;
+ unsigned int pwr_state;
+ drm_emgd_priv_t *priv = dev->dev_private;
+
+ EMGD_TRACE_ENTER;
+
+
+ mutex_lock(&dev->struct_mutex);
+
+ /* When the system is suspended, the X server does a VT switch, which saves
+ * the register state of the X server, and restores the console's register
+ * state. This code saves the console's register state, so that after the
+ * system resumes, VT switches to the console can occur.
+ */
+ if (priv->hal_running) {
+ EMGD_DEBUG("Saving the console's register state");
+ priv->suspended_state =
+ drm_HAL_context->mod_dispatch.reg_alloc(drm_HAL_context,
+ IGD_REG_SAVE_ALL);
+ if (priv->suspended_state) {
+ /*
+ //Flag CDVO is not needed
+ if (state.event == PM_EVENT_SUSPEND){
+ if (drm_HAL_context->mod_dispatch.flag_cdvo!= NULL){
+ drm_HAL_context->mod_dispatch.flag_cdvo(drm_HAL_context);
+ }
+ }
+ */
+ drm_HAL_context->mod_dispatch.reg_save(drm_HAL_context,
+ priv->suspended_state);
+ }
+ }
+
+ /* Map the pm_message_t event states to HAL states: */
+ switch (state.event) {
+ case PM_EVENT_PRETHAW:
+ case PM_EVENT_FREEZE:
+ pwr_state = IGD_POWERSTATE_D1;
+ break;
+ case PM_EVENT_HIBERNATE:
+ pwr_state = IGD_POWERSTATE_D3;
+ break;
+ case PM_EVENT_SUSPEND:
+ default:
+ pwr_state = IGD_POWERSTATE_D2;
+ break;
+ } /* switch (state) */
+
+ EMGD_DEBUG("Calling pwr_alter()");
+ ret = drm_HAL_dispatch->pwr_alter(drm_HAL_handle, pwr_state);
+ EMGD_DEBUG("pwr_alter() returned %d", ret);
+
+ if (0 == ret) {
+ EMGD_DEBUG("Calling PVRSRVDriverSuspend()");
+ ret = PVRSRVDriverSuspend(dev, state);
+ EMGD_DEBUG("PVRSRVDriverSuspend() returned %d", ret);
+ }
+
+ EMGD_DEBUG("Returning %d", ret);
+ mutex_unlock(&dev->struct_mutex);
+ EMGD_TRACE_EXIT;
+ return ret;
+
+} /* emgd_driver_suspend() */
+
+
+/**
+ * This is the drm_driver.resume() function. It appears to support what the
+ * Linux "pm.h" file calls "the legacy suspend framework." The DRM
+ * drm_class_resume() (in "drm_sysfs.c", which implements the Linux
+ * class.suspend() function defined in "device.h") calls this function if
+ * conditions are met, such as drm_minor->type is DRM_MINOR_LEGACY and the
+ * driver doesn't have the DRIVER_MODESET feature set.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+int emgd_driver_resume(struct drm_device *dev)
+{
+ int ret;
+ drm_emgd_priv_t *priv = dev->dev_private;
+
+ EMGD_TRACE_ENTER;
+
+ mutex_lock(&dev->struct_mutex);
+
+ EMGD_DEBUG("Calling pwr_alter()");
+ ret = drm_HAL_dispatch->pwr_alter(drm_HAL_handle, IGD_POWERSTATE_D0);
+ EMGD_DEBUG("pwr_alter() returned %d", ret);
+
+ if (0 == ret) {
+ EMGD_DEBUG("Calling PVRSRVDriverResume()");
+ ret = PVRSRVDriverResume(dev);
+ EMGD_DEBUG("PVRSRVDriverResume() returned %d", ret);
+ }
+
+ /* Restore the register state of the console, so that after the X server is
+ * back up, VT switches to the console can occur.
+ */
+ if (priv->hal_running) {
+ EMGD_DEBUG("Restoring the console's register state");
+ if (priv->suspended_state) {
+ drm_HAL_context->mod_dispatch.reg_restore(drm_HAL_context,
+ priv->suspended_state);
+ drm_HAL_context->mod_dispatch.reg_free(drm_HAL_context,
+ priv->suspended_state);
+ priv->suspended_state = NULL;
+ }
+ }
+
+ EMGD_DEBUG("Returning %d", ret);
+ mutex_unlock(&dev->struct_mutex);
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* emgd_driver_resume() */
+
+
+/**
+ * This is the drm_driver.device_is_agp() function. It is called as a part of
+ * drm_init() (before the drm_driver.load() function), and is "typically used
+ * to determine if a card is really attached to AGP or not" (see the Doxygen
+ * comment for this function in "drmP.h"). It is actually called by the
+ * inline'd DRM procedure, drm_device_is_agp() (in "drmP.h").
+ *
+ * The Intel open source driver states that all Intel graphics devices are
+ * treated as AGP. However, the EMGD driver provides its own management of the
+ * GTT tables, and so doesn't need AGP GART driver support. Thus, this
+ * function always returns 0.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return 0 the graphics "card" is absolutely not AGP.
+ * @return 1 the graphics "card" is AGP.
+ * @return 2 the graphics "card" may or may not be AGP.
+ */
+int emgd_driver_device_is_agp(struct drm_device *dev)
+{
+ EMGD_DEBUG("[EMGD] Returning 0 from emgd_driver_device_is_agp()\n");
+ return 0;
+} /* emgd_driver_device_is_agp() */
+
+
+
+/**
+ * This is the drm_driver.get_vblank_counter() function. It is called to get
+ * the raw hardware vblank counter. There are 4 places within "drm_irq.c" that
+ * call this function.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param crtc_select (IN) Exactly how this is derived is unclear, but
+ * for now we are assuming that it is the order
+ * in which the CRTCs were creatd. So 0 for
+ * the first CRTC, 1 for the second, and so on.
+ *
+ * @return raw vblank counter value
+ */
+u32 emgd_driver_get_vblank_counter(struct drm_device *dev, int crtc_select)
+{
+ struct drm_crtc *crtc;
+ emgd_crtc_t *cur_emgd_crtc, *selected_emgd_crtc = NULL;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Only supported for KMS-enabled driver */
+ if (!config_drm.kms) {
+ /* Since we have previously returned 0 for our non-KMS driver,
+ * this is left in to prevent any unforeseen problems. */
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+
+ /* Find the CRTC associated with the */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ cur_emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if ((1 << crtc_select) == cur_emgd_crtc->crtc_id) {
+ selected_emgd_crtc = cur_emgd_crtc;
+ break;
+ }
+ }
+
+ if (NULL == selected_emgd_crtc) {
+ EMGD_ERROR_EXIT("Invalid CRTC selected.");
+ return -EINVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return mode_context->kms_dispatch->kms_get_vblank_counter(
+ selected_emgd_crtc);
+} /* emgd_driver_get_vblank_counter() */
+
+
+
+/**
+ * This is the drm_driver.enable_vblank() function. It is called by
+ * drm_vblank_get() (in "drm_irq.c") to enable vblank interrupt events.
+ * This function is only available for KMS
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param crtc_select (IN) Exactly how this is derived is unclear, but
+ * for now we are assuming that it is the order
+ * in which the CRTCs were creatd. So 0 for
+ * the first CRTC, 1 for the second, and so on.
+ *
+ * @return 0 on Success
+ * @return <0 if the given crtc's vblank interrupt cannot be enabled
+ */
+int emgd_driver_enable_vblank(struct drm_device *dev, int crtc_select)
+{
+ struct drm_crtc *crtc;
+ unsigned char *mmio;
+ emgd_crtc_t *cur_emgd_crtc, *selected_emgd_crtc = NULL;
+ unsigned long request_for;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Only supported for KMS-enabled driver */
+ if (!config_drm.kms) {
+ /* We should return an error here since this is not
+ * supported. However, since we have previously returned 0
+ * for our non-KMS driver, this is left in to prevent any
+ * unforeseen problems. */
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+
+
+ /* Find the CRTC associated with the */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ cur_emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if ((1 << crtc_select) == cur_emgd_crtc->crtc_id) {
+ selected_emgd_crtc = cur_emgd_crtc;
+ break;
+ }
+ }
+
+ if (NULL == selected_emgd_crtc) {
+ EMGD_ERROR_EXIT("Invalid CRTC selected.");
+ return -EINVAL;
+ }
+
+
+ switch (selected_emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) {
+ case IGD_PORT_SHARE_LVDS:
+ request_for = VBLANK_INT4_PORT4;
+ break;
+
+ case IGD_PORT_SHARE_DIGITAL:
+ request_for = VBLANK_INT4_PORT2;
+ break;
+
+ default:
+ EMGD_DEBUG("Unsupported port type");
+ request_for = 0;
+ ret = -EINVAL;
+ break;
+ }
+
+ if (0 == ret) {
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ ret = mode_context->dispatch->full->request_vblanks(request_for, mmio);
+
+ if (ret) {
+ EMGD_DEBUG("Failed to enable vblank");
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+} /* emgd_driver_enable_vblank() */
+
+
+
+/**
+ * This is the drm_driver.disable_vblank() function. It is called by
+ * vblank_disable_fn() (in "drm_irq.c") to disable vblank interrupt events.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param crtc_select (IN) Exactly how this is derived is unclear, but
+ * for now we are assuming that it is the order
+ * in which the CRTCs were creatd. So 0 for
+ * the first CRTC, 1 for the second, and so on.
+ */
+void emgd_driver_disable_vblank(struct drm_device *dev, int crtc_select)
+{
+ struct drm_crtc *crtc;
+ unsigned char *mmio;
+ emgd_crtc_t *cur_emgd_crtc, *selected_emgd_crtc = NULL;
+ unsigned long request_for;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Only supported for KMS-enabled driver */
+ if (!config_drm.kms) {
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+
+ /* Find the CRTC associated with the */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ cur_emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if ((1 << crtc_select) == cur_emgd_crtc->crtc_id) {
+ selected_emgd_crtc = cur_emgd_crtc;
+ break;
+ }
+ }
+
+ if (NULL == selected_emgd_crtc) {
+ EMGD_ERROR_EXIT("Invalid CRTC selected.");
+ return;
+ }
+
+
+ switch (selected_emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) {
+ case IGD_PORT_SHARE_LVDS:
+ request_for = VBLANK_INT4_PORT4;
+ break;
+
+ case IGD_PORT_SHARE_DIGITAL:
+ request_for = VBLANK_INT4_PORT2;
+ break;
+
+ default:
+ EMGD_DEBUG("Unsupported port type");
+ request_for = 0;
+ ret = -EINVAL;
+ break;
+ }
+
+ if (0 == ret) {
+ mmio = EMGD_MMIO(mode_context->context->device_context.virt_mmadr);
+ ret = mode_context->dispatch->full->end_request(request_for, mmio);
+
+ if (ret) {
+ EMGD_DEBUG("Failed to disable vblank");
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+} /* emgd_driver_disable_vblank() */
+
+
+
+/**
+ * This is the drm_driver.irq_preinstall() function. It is called by
+ * drm_irq_install() (in "drm_irq.c") before it installs this driver's IRQ
+ * handler (i.e. emgd_driver_irq_handler()).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ */
+void emgd_driver_irq_preinstall(struct drm_device *dev)
+{
+ /* Notes on what to implement in this function:
+ *
+ * - Ditto the notes in emgd_driver_enable_vblank().
+ *
+ * - In addition, I'll note that I see a HAL interface that roughly
+ * corresponds to this functionality--the interrupt_install() and
+ * interrupt_uninstall() entry points in igd_dispatch_t (in "igd.h" and
+ * better defined in "igd_interrupt.h"). However:
+ *
+ * - There are no "plb" versions of this code, only "alm", "nap" & "wht".
+ *
+ * - These install a passed-in interrupt handler. As far as I can see
+ * in the ssigd tree, these routines are never called, and no
+ * interrupt handlers exist.
+ *
+ * - Koheo doesn't contain the hal/core/interrupt code. I'm not sure
+ * what that does, but grep'ing through the source shows a number of
+ * lines about irq's.
+ *
+ * - The open source Intel driver has some code that implements this. It's
+ * not small, so I haven't really studied it yet. Can/should we go with
+ * a similar approach, or keep like the current HAL approach and
+ * structure some new entrypoints that allow future hardware to be
+ * different?
+ */
+
+ /* TODO -- REPLACE THIS STUB WITH A REAL IMPLEMENTATION */
+ printk(KERN_INFO "[EMGD] Inside of STUBBED %s()", __FUNCTION__);
+
+} /* emgd_driver_irq_preinstall() */
+
+
+/**
+ * This is the drm_driver.irq_postinstall() function. It is called by
+ * drm_irq_install() (in "drm_irq.c") after it installs this driver's IRQ
+ * handler (i.e. emgd_driver_irq_handler()).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return 0 on Success
+ * @return <0 if the given crtc's vblank interrupt cannot be enabled
+ */
+int emgd_driver_irq_postinstall(struct drm_device *dev)
+{
+ return 0;
+} /* emgd_driver_irq_postinstall() */
+
+
+/**
+ * This is the drm_driver.irq_uninstall() function. It is called by
+ * drm_irq_install() (in "drm_irq.c") as a part of uninstalling this driver's
+ * IRQ handler (i.e. emgd_driver_irq_handler()).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ */
+void emgd_driver_irq_uninstall(struct drm_device *dev)
+{
+ /* TODO -- REPLACE THIS STUB WITH A REAL IMPLEMENTATION THE IMG TRAINING */
+ printk(KERN_INFO "[EMGD] Inside of STUBBED %s()", __FUNCTION__);
+
+} /* emgd_driver_irq_uninstall() */
+
+
+/**
+ * This is the drm_driver.irq_handler() function, and is a Linux IRQ interrupt
+ * handler (see the irq_handler_t in the Linux header "interrupt.h"). It is
+ * installed by drm_irq_install() (in "drm_irq.c") by calling request_irq()
+ * (implemented in "interrupt.h") with this function as the 2nd parameter. The
+ * return type is an enum (see the Linux header "irqreturn.h").
+ *
+ * Our HAL will have already installed an IRQ handler, so we do nothing here.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return IRQ_NONE if the interrupt was not from this device
+ * @return IRQ_HANDLED if the interrupt was handled by this device
+ * @return IRQ_WAKE_THREAD if this handler requests to wake the handler thread
+ */
+irqreturn_t emgd_driver_irq_handler(int irq, void *arg)
+{
+ /* TODO -- REPLACE THIS STUB WITH A REAL IMPLEMENTATION THE IMG TRAINING */
+ printk(KERN_INFO "[EMGD] Inside of STUBBED %s()", __FUNCTION__);
+
+ return IRQ_NONE;
+} /* emgd_driver_irq_handler() */
+
+
+static int __devinit emgd_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ if (PCI_FUNC(pdev->devfn)) {
+ return -ENODEV;
+ }
+
+ /*
+ * Name changed at some point in time. 2.6.35 uses drm_get_dev
+ * and 2.6.38 uses drm_get_pci_dev Need to figure what kernel
+ * version this changed.
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+ return drm_get_pci_dev(pdev, ent, &driver);
+#else
+ return drm_get_dev(pdev, ent, &driver);
+#endif
+}
+
+static void emgd_pci_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_put_dev(dev);
+}
+
+static int emgd_pm_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int emgd_pm_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int emgd_pm_freeze(struct device *dev)
+{
+ return 0;
+}
+
+static int emgd_pm_thaw(struct device *dev)
+{
+ return 0;
+}
+
+static int emgd_pm_poweroff(struct device *dev)
+{
+ return 0;
+}
+
+static int emgd_pm_restore(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops emgd_pm_ops = {
+ .suspend = emgd_pm_suspend,
+ .resume = emgd_pm_resume,
+ .freeze = emgd_pm_freeze,
+ .thaw = emgd_pm_thaw,
+ .poweroff = emgd_pm_poweroff,
+ .restore = emgd_pm_restore,
+};
+
+/*
+ * NOTE: The remainder of this file is standard kernel module initialization
+ * code:
+ */
+
+
+/*
+ * Older kernels kept the PCI driver information directly in the
+ * DRM driver structure. Newer kernels (2.6.38-rc3 and beyond)
+ * move it outside of the DRM driver structure and pass it to
+ * drm_pci_init instead in order to help pave the way for
+ * USB graphics devices.
+ */
+#define EMGD_PCI_DRIVER { \
+ .name = DRIVER_NAME, \
+ .id_table = pciidlist, \
+ .probe = emgd_pci_probe, \
+ .remove = emgd_pci_remove, \
+ .driver.pm = &emgd_pm_ops, \
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+static struct pci_driver emgd_pci_driver = EMGD_PCI_DRIVER;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#define IOCTL unlocked_ioctl
+#else
+#define IOCTL ioctl
+#endif
+
+#define EMGD_FOPS { \
+ .owner = THIS_MODULE, \
+ .open = drm_open, \
+ .release = drm_release, \
+ .IOCTL = drm_ioctl, \
+ .mmap = emgd_mmap, \
+ .poll = drm_poll, \
+ .fasync = drm_fasync, \
+ .read = drm_read, \
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+static const struct file_operations emgd_driver_fops = EMGD_FOPS;
+#endif
+/**
+ * DRM Sub driver entry points
+ */
+static struct drm_driver driver = {
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .load = emgd_driver_load,
+ .unload = emgd_driver_unload,
+ .open = emgd_driver_open,
+ .lastclose = emgd_driver_lastclose,
+ .preclose = emgd_driver_preclose,
+ .postclose = emgd_driver_postclose,
+ .suspend = emgd_driver_suspend,
+ .resume = emgd_driver_resume,
+ .device_is_agp = emgd_driver_device_is_agp,
+ .get_vblank_counter = emgd_driver_get_vblank_counter,
+ .enable_vblank = emgd_driver_enable_vblank,
+ .disable_vblank = emgd_driver_disable_vblank,
+ .irq_preinstall = emgd_driver_irq_preinstall,
+ .irq_postinstall = emgd_driver_irq_postinstall,
+ .irq_uninstall = emgd_driver_irq_uninstall,
+ .irq_handler = emgd_driver_irq_handler,
+ .reclaim_buffers = drm_core_reclaim_buffers,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+#endif
+ .ioctls = emgd_ioctl,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+ .fops = &emgd_driver_fops,
+#else
+ .fops = EMGD_FOPS,
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+ .pci_driver = EMGD_PCI_DRIVER,
+#endif
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+/**
+ * Standard procedure to initialize this kernel module when it is loaded.
+ */
+static int __init emgd_init(void) {
+ int ret;
+ struct pci_dev *our_device;
+
+ printk(KERN_INFO "[EMGD] Initializing Driver.\n");
+ driver.num_ioctls = emgd_max_ioctl;
+
+ /* If init == 1 then we should always set KMS to 0 for US15 */
+
+ if(config_drm.init || drm_emgd_init == 1){
+
+ /* Detecting device */
+
+ /*
+ * 0x8086 is the intel vendor id and 0x8108 is the
+ * US15 device id.
+ * pci_get_device returns NULL if it is not a PLB.
+ */
+
+ our_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_VGA_PLB, NULL);
+
+ if(our_device){
+ EMGD_ERROR("US15 detected. Setting KMS to 0 "
+ "config_drm.kms = %d ", config_drm.kms);
+ config_drm.kms = 0;
+ }
+ }
+
+ if (config_drm.kms && (config_drm.init || drm_emgd_init == 1)) {
+ driver.driver_features |= DRIVER_MODESET;
+ }
+
+ PVRDPFInit();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+ ret = drm_pci_init(&driver, &emgd_pci_driver);
+#else
+ ret = drm_init(&driver);
+#endif
+ printk(KERN_INFO "[EMGD] Driver Initialized.\n");
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+/**
+ * Standard procedure to clean-up this kernel module before it exits & unloads.
+ */
+static void __exit emgd_exit(void) {
+ EMGD_TRACE_ENTER;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+ drm_pci_exit(&driver, &emgd_pci_driver);
+#else
+ drm_exit(&driver);
+#endif
+ EMGD_TRACE_EXIT;
+}
+
+
+module_init(emgd_init);
+module_exit(emgd_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
new file mode 100644
index 0000000..15c88b2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
@@ -0,0 +1,211 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_drv.h
+ * $Revision: 1.76 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _EMGD_DRV_H_
+#define _EMGD_DRV_H_
+
+#include <linux/io-mapping.h>
+#include <emgd_shared.h>
+#include <igd_version.h>
+#include "user_config.h"
+
+#define DRIVER_AUTHOR "Intel Corporation."
+#define DRIVER_NAME EMGD_MODULE_NAME
+#define DRIVER_DESC "Intel Embedded Media and Grahics Driver"
+#define DRIVER_DATE PVR_BUILD_DATE
+#define DRIVER_MAJOR IGD_MAJOR_NUM
+#define DRIVER_MINOR IGD_MINOR_NUM
+#define DRIVER_PATCHLEVEL IGD_BUILD_NUM
+
+#define INTELFB_CONN_LIMIT 4
+
+/*
+ * * Special "handle" that indicates the framebuffer being referred to is the
+ * * EMGD initial framebuffer (which does not have a PVR meminfo handle that
+ * * can be passed.
+ * */
+#define EMGD_INITIAL_FRAMEBUFFER 0
+
+
+/* Function prototypes */
+extern int emgd_driver_load(struct drm_device *dev, unsigned long flags);
+extern int emgd_driver_unload(struct drm_device *dev);
+extern int emgd_driver_open(struct drm_device *dev,
+ struct drm_file *file_priv);
+extern void emgd_driver_lastclose(struct drm_device *dev);
+extern void emgd_driver_preclose(struct drm_device *dev,
+ struct drm_file *file_priv);
+extern void emgd_driver_postclose(struct drm_device *dev,
+ struct drm_file *file_priv);
+extern int emgd_driver_device_is_agp(struct drm_device * dev);
+extern long egd(struct file *filp, unsigned int cmd, unsigned long arg);
+
+extern int emgd_startup_hal(struct drm_device *dev, igd_param_t *params);
+int disp_splash_screen(emgd_drm_splash_screen_t *ss_data);
+int disp_splash_video(emgd_drm_splash_video_t *sv_data);
+extern irqreturn_t emgd_driver_irq_handler(DRM_IRQ_ARGS);
+extern void emgd_driver_irq_preinstall(struct drm_device * dev);
+extern int emgd_driver_irq_postinstall(struct drm_device *dev);
+extern void emgd_driver_irq_uninstall(struct drm_device * dev);
+extern int emgd_driver_enable_vblank(struct drm_device *dev, int crtc);
+extern void emgd_driver_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 emgd_driver_get_vblank_counter(struct drm_device *dev, int crtc);
+
+extern int emgd_driver_suspend(struct drm_device *dev, pm_message_t state);
+extern int emgd_driver_resume(struct drm_device *dev);
+extern int emgd_mmap(struct file *filp, struct vm_area_struct *vma);
+
+
+/* Module parameters: */
+extern int drm_emgd_configid;
+
+
+
+typedef struct drm_device drm_device_t;
+
+
+/*
+ * IOCTL handler function prototypes:
+ */
+int emgd_alter_cursor(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_alter_cursor_pos(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_alter_displays(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_display_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_alter_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_appcontext_alloc(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_appcontext_free(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_driver_save_restore(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_enable_port(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_attrs(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+extern int emgd_alter_ovl2(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+extern int emgd_get_ovl_init_params(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_drm_config(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_EDID_block(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_EDID_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_pixelformats(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_port_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_alloc_region(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_alloc_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_get_num_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_get_surface_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_free(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_gmm_flush_cache(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_pan_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_power_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_pwr_alter(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_query_dc(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_query_max_size_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_query_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_query_mode_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_set_attrs(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_set_palette_entry(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_set_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_dihclone_set_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_sync(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_driver_pre_init(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_driver_get_ports(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_start_pvrsrv(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_test_pvrsrv(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_chipset_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_video_cmd_buf(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_device_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_page_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_init_video(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_video_get_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_video_flush_tlb(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_preinit_mmu(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_get_golden_htotal(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_control_plane_format(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_set_overlay_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_query_2d_caps_hwhint(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+int emgd_unlock_planes(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+/* For Buffer Class of Texture Stream */
+int emgd_bc_ts_cmd_init(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_cmd_uninit(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_cmd_request_buffers(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_cmd_release_buffers(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_set_buffer_info(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_get_buffers_count(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+int emgd_bc_ts_get_buffer_index(struct drm_device *dev, void *arg, struct drm_file *file_priv);
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
new file mode 100644
index 0000000..478863d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
@@ -0,0 +1,478 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_encoder.c
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Encoder / kenrel mode setting functions.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+#include <drmP.h>
+#include <drm_crtc_helper.h>
+#include <linux/version.h>
+
+#include <mode_dispatch.h>
+#include "drm_emgd_private.h"
+
+#include <igd_pwr.h>
+
+
+
+/*------------------------------------------------------------------------------
+ * External Functions
+ *------------------------------------------------------------------------------
+ */
+extern int calculate_eld(igd_display_port_t *port,
+ igd_timing_info_t *timing_info);
+
+
+
+static void emgd_encoder_destroy(struct drm_encoder *encoder);
+static void emgd_encoder_dpms(struct drm_encoder *encoder, int mode);
+static bool emgd_encoder_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+static void emgd_encoder_prepare(struct drm_encoder *encoder);
+static void emgd_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+static void emgd_encoder_commit(struct drm_encoder *encoder);
+
+
+const struct drm_encoder_funcs emgd_encoder_funcs = {
+ .destroy = emgd_encoder_destroy,
+};
+
+const struct drm_encoder_helper_funcs emgd_encoder_helper_funcs = {
+ .dpms = emgd_encoder_dpms,
+ .mode_fixup = emgd_encoder_mode_fixup,
+ .prepare = emgd_encoder_prepare,
+ .mode_set = emgd_encoder_mode_set,
+ .commit = emgd_encoder_commit,
+};
+
+
+/**
+ * emgd_encoder_dpms
+ *
+ * This function will put the encoder to either an ON or OFF state. Anything
+ * that is not DRM_MODE_DPMS_ON is treated as an off-state.
+ *
+ * @param encoder (IN) Encoder
+ * @param mode (IN) power mode
+ *
+ * @return None
+ */
+static void emgd_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ emgd_crtc_t *emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+ emgd_encoder_t *emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ igd_display_port_t *igd_port = emgd_encoder->igd_port;
+
+ EMGD_TRACE_ENTER;
+
+ /* The following check is a work around for KMS tries to
+ * program both the crtcs and ports (LVDS and SDVO)
+ * even if it is in single mode. It results in a SIGSEGV.
+ * By putting this check we ensure that it moves forward
+ * only if there is a valid context associated with the
+ * port.
+ */
+ if(emgd_crtc->igd_pipe->owner) {
+
+ EMGD_DEBUG("Setting port %lx power to %d",
+ igd_port->port_number, mode);
+
+ switch(mode) {
+
+ case DRM_MODE_DPMS_ON:
+ mode_context->kms_dispatch->kms_program_port(emgd_encoder,
+ IGD_DISPLAY_ENABLE);
+ mode_context->kms_dispatch->kms_post_program_port(emgd_encoder,
+ TRUE);
+ break;
+
+ case DRM_MODE_DPMS_STANDBY:
+ case DRM_MODE_DPMS_SUSPEND:
+ case DRM_MODE_DPMS_OFF:
+ mode_context->kms_dispatch->kms_program_port(emgd_encoder,
+ IGD_DISPLAY_DISABLE);
+ break;
+
+ default:
+ EMGD_ERROR_EXIT("Unsupported DPMS mode");
+ return;
+ }
+ }else {
+ EMGD_DEBUG("Owner is null for this pipe");
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_mode_fixup
+ *
+ * Called before a mode set, takes the input "mode", matches it to the closest
+ * supported mode, then put the supported mode into "adjusted_mode" to let the
+ * caller know.
+ *
+ * Note: We cannot handle centered and scaled mode with this. To handle this
+ * we need to program the pipe and the port to different sets of timings.
+ * The CRTC Helper does not allow this. It wants to send adjusted_mode
+ * to both the CRTC and the Encoder. We can maybe get around this by
+ * modifying the "mode" parameter, but that is not the right approach.
+ *
+ * @param encoder (IN) Encoder being prepared
+ * @param mode (IN) Requested mode
+ * @param adjusted_mode (IN) Encoder supported mode
+ *
+ * @return true, false (details TBD)
+ */
+static bool emgd_encoder_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = NULL;
+ igd_context_t *context = NULL;
+ igd_display_port_t *port = NULL;
+ igd_framebuffer_info_t *fb_info = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ igd_timing_info_t *timing = NULL;
+ igd_display_info_t *pt_info = NULL;
+ emgd_crtc_t *emgd_crtc = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ unsigned long existing_height = 0;
+ unsigned long existing_width = 0;
+ unsigned long existing_refresh = 0;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* Check ajusted mode to see if it's valid. If not, populate it */
+ if (adjusted_mode->crtc_htotal == 0) {
+ EMGD_DEBUG("No valid mode in adjusted mode, setting valid mode");
+ drm_mode_set_crtcinfo(adjusted_mode, 0);
+ }
+
+ dev = encoder->dev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ port = emgd_encoder->igd_port;
+ if (!port->pt_info) {
+ port->pt_info = kzalloc(sizeof(igd_display_info_t), GFP_KERNEL);
+ if (!port->pt_info) {
+ EMGD_DEBUG("Cannot allocate igd_display_into_t");
+ return false;
+ }
+ }
+ existing_height = port->pt_info->height;
+ existing_width = port->pt_info->width;
+ existing_refresh = port->pt_info->refresh;
+ pt_info = port->pt_info;
+
+ fb_info = kzalloc(sizeof(igd_framebuffer_info_t), GFP_KERNEL);
+ if (!fb_info) {
+ EMGD_DEBUG("Cannot allocate framebuffer info");
+ return false;
+ }
+
+ /* Get the dimension of the framebuffer linked to the CRTC. If it is
+ * smaller than the resolution, kms_match_mode will either center it
+ * or let the encoder hardware scale it */
+ fb_info->width = encoder->crtc->fb->width;
+ fb_info->height = encoder->crtc->fb->height;
+ EMGD_DEBUG("Setting fb_info to: %dx%d", fb_info->width, fb_info->height);
+
+ pt_info->width = mode->crtc_hdisplay;
+ pt_info->height = mode->crtc_vdisplay;
+ pt_info->refresh = mode->vrefresh;
+ pt_info->dclk = mode->synth_clock;
+ pt_info->htotal = mode->crtc_htotal;
+ pt_info->hblank_start = mode->crtc_hblank_start;
+ pt_info->hblank_end = mode->crtc_hblank_end;
+ pt_info->hsync_start = mode->crtc_hsync_start;
+ pt_info->hsync_end = mode->crtc_hsync_end;
+ pt_info->vtotal = mode->crtc_vtotal;
+ pt_info->vblank_start = mode->crtc_vblank_start;
+ pt_info->vblank_end = mode->crtc_vblank_end;
+ pt_info->vsync_start = mode->crtc_vsync_start;
+ pt_info->vsync_end = mode->crtc_vsync_end;
+ pt_info->mode_number = mode->clock_index;
+ pt_info->flags = 0;
+ EMGD_DEBUG("Setting pt_info to: %dx%d", pt_info->width, pt_info->height);
+
+ ret = mode_context->kms_dispatch->kms_match_mode((void *)emgd_encoder,
+ (void *)fb_info, &timing);
+
+ if (!ret) {
+ adjusted_mode->crtc_hdisplay = timing->width;
+ adjusted_mode->crtc_vdisplay = timing->height;
+ adjusted_mode->vrefresh = timing->refresh;
+ adjusted_mode->synth_clock = timing->dclk;
+ adjusted_mode->crtc_htotal = timing->htotal;
+ adjusted_mode->crtc_hblank_start = timing->hblank_start;
+ adjusted_mode->crtc_hblank_end = timing->hblank_end;
+ adjusted_mode->crtc_hsync_start = timing->hsync_start;
+ adjusted_mode->crtc_hsync_end = timing->hsync_end;
+ adjusted_mode->crtc_vtotal = timing->vtotal;
+ adjusted_mode->crtc_vblank_start = timing->vblank_start;
+ adjusted_mode->crtc_vblank_end = timing->vblank_end;
+ adjusted_mode->crtc_vsync_start = timing->vsync_start;
+ adjusted_mode->crtc_vsync_end = timing->vsync_end;
+ adjusted_mode->clock_index = timing->mode_number;
+ adjusted_mode->private_flags = timing->mode_info_flags;
+
+ EMGD_DEBUG("(%dx%d@%d)->(%dx%d@%d)",
+ mode->crtc_hdisplay, mode->crtc_vdisplay, mode->vrefresh,
+ adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay,
+ adjusted_mode->vrefresh);
+
+ /* Check our new mode against what currently there
+ * to see if we can do a seamless mode-set
+ */
+ if (emgd_encoder->flags & ENCODER_FLAG_FIRST_ALTER) {
+ if (mode_context->fw_info) {
+
+ emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+
+ existing_width = mode_context->fw_info->
+ timing_arr[pipe->pipe_num].width;
+ existing_height = mode_context->fw_info->
+ timing_arr[pipe->pipe_num].height;
+ existing_refresh = mode_context->fw_info->
+ timing_arr[pipe->pipe_num].refresh;
+
+ }
+ }
+
+ if (adjusted_mode->crtc_hdisplay == existing_width &&
+ adjusted_mode->crtc_vdisplay == existing_height) {
+
+ if (abs(adjusted_mode->vrefresh - existing_refresh) <= 1) {
+ emgd_encoder->flags |= ENCODER_FLAG_SEAMLESS;
+ }
+ }
+ }
+
+ kfree(fb_info);
+
+ EMGD_TRACE_EXIT;
+ return (!ret);
+}
+
+
+
+/**
+ * emgd_encoder_prepare
+ *
+ * Based on the available documentation at the moment, this function gets
+ * called right before a mode change. Its job is to turn off the display.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return None
+ */
+static void emgd_encoder_prepare(struct drm_encoder *encoder)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs;
+ emgd_encoder_t *emgd_encoder;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+ if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+ encoder_funcs = encoder->helper_private;
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+ }
+
+ emgd_encoder->flags &= ~ENCODER_FLAG_FIRST_ALTER;
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_commit
+ *
+ * This function commits the mode change sequence by actually programming
+ * the registers.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return None
+ */
+static void emgd_encoder_commit(struct drm_encoder *encoder)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs;
+ emgd_encoder_t *emgd_encoder = NULL;
+ emgd_crtc_t *emgd_crtc;
+ igd_display_port_t *port;
+ igd_display_pipe_t *pipe;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+
+ if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+
+ port = emgd_encoder->igd_port;
+ emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+
+/* mode_context->kms_dispatch->kms_program_port(emgd_encoder,
+ IGD_DISPLAY_ENABLE);*/
+/*
+ port->pd_driver->set_mode(port->pd_context, pipe->timing,
+ 1<<pipe->pipe_num);*/
+
+
+ encoder_funcs = encoder->helper_private;
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+
+ }
+ /* Reset our seamless variable */
+ emgd_encoder->flags &= ~ENCODER_FLAG_SEAMLESS;
+
+ /* TODO: Add call to check_display */
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_mode_set
+ *
+ * This function saves the requested timings into the Port Timing Info
+ * structure. At emgd_encoder_commit() time we should be using these
+ * timings to program the port, but currently we are using timings from
+ * the pipe. This is fine for now, but at one point we should investigate
+ * the centering case in which the port timings may not match the pipe timings.
+ *
+ * @param encoder (IN) Encoder being prepared
+ * @param mode (IN)
+ * @param adjusted_mode (IN)
+ *
+ * @return None
+ */
+static void emgd_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ emgd_encoder_t *emgd_encoder = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ igd_display_port_t *port = NULL;
+ pd_timing_t *timing = NULL;
+
+ EMGD_TRACE_ENTER;
+
+
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+ if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+ port = emgd_encoder->igd_port;
+ emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+ pipe = emgd_crtc->igd_pipe;
+
+ if (pipe) {
+ timing = (pd_timing_t *)pipe->timing;
+
+ if (NULL == port->pt_info) {
+ port->pt_info = kzalloc(sizeof(igd_display_info_t), GFP_KERNEL);
+
+ if (!port->pt_info) {
+ EMGD_ERROR_EXIT("Unable to allocate pt_info.");
+ return;
+ }
+ }
+
+ port->pt_info->width = adjusted_mode->crtc_hdisplay;
+ port->pt_info->height = adjusted_mode->crtc_vdisplay;
+ port->pt_info->refresh = adjusted_mode->vrefresh;
+ port->pt_info->dclk = adjusted_mode->synth_clock;
+ port->pt_info->htotal = adjusted_mode->crtc_htotal;
+ port->pt_info->hblank_start = adjusted_mode->crtc_hblank_start;
+ port->pt_info->hblank_end = adjusted_mode->crtc_hblank_end;
+ port->pt_info->hsync_start = adjusted_mode->crtc_hsync_start;
+ port->pt_info->hsync_end = adjusted_mode->crtc_hsync_end;
+ port->pt_info->vtotal = adjusted_mode->crtc_vtotal;
+ port->pt_info->vblank_start = adjusted_mode->crtc_vblank_start;
+ port->pt_info->vblank_end = adjusted_mode->crtc_vblank_end;
+ port->pt_info->vsync_start = adjusted_mode->crtc_vsync_start;
+ port->pt_info->vsync_end = adjusted_mode->crtc_vsync_end;
+ port->pt_info->mode_number = adjusted_mode->clock_index;
+ port->pt_info->flags = adjusted_mode->private_flags;
+
+ port->pt_info->x_offset = timing->x_offset;
+ port->pt_info->y_offset = timing->y_offset;
+ port->pt_info->flags |= IGD_DISPLAY_ENABLE;
+
+
+ EMGD_DEBUG("Calculate ELD");
+ if (calculate_eld(port, timing)) {
+ EMGD_DEBUG("Fail to calculate ELD");
+ }
+
+ } else {
+ EMGD_ERROR("Trying to set the mode without a pipe attached.");
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_destroy
+ *
+ * Frees the resources allocated for this encoder during "create_encoder()"
+ *
+ * @param encoder (IN) Encoder to be freed
+ *
+ * @return None
+ */
+static void emgd_encoder_destroy(struct drm_encoder *encoder)
+{
+ emgd_encoder_t *emgd_encoder;
+
+ EMGD_TRACE_ENTER;
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+ drm_encoder_cleanup(encoder);
+
+ kfree(emgd_encoder);
+
+ EMGD_TRACE_EXIT;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
new file mode 100644
index 0000000..8683477
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
@@ -0,0 +1,1450 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_fb.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Framebuffer / kernel mode setting functions.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+#include <linux/export.h>
+#else
+#include <linux/module.h>
+#endif
+#include <drmP.h>
+#include <drm.h>
+#include <drm_crtc.h>
+#include <drm_crtc_helper.h>
+#include <drm_fb_helper.h>
+#include <linux/version.h>
+#include <linux/vga_switcheroo.h>
+
+#include "drm_emgd_private.h"
+#include "emgd_drv.h"
+#include "emgd_drm.h"
+#include "memory.h"
+#include "io.h"
+#include "mode_dispatch.h"
+
+/* Necessary to import page list for a PVR-allocated surface */
+#include "pvr_bridge_km.h"
+
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+#define RETURN_PROBE_TYPE int
+#define RETURN_PROBE return 0
+#define PROBE_FUNC fb_changed
+#else
+#define RETURN_PROBE_TYPE void
+#define RETURN_PROBE
+#define PROBE_FUNC output_poll_changed
+#endif
+
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *------------------------------------------------------------------------------
+ */
+extern igd_framebuffer_info_t primary_fb_info;
+extern mode_context_t mode_context[1];
+static struct drm_mode_set panic_mode;
+extern int drm_emgd_init;
+extern emgd_drm_config_t config_drm;
+
+/* CRTC Dispatch Tables */
+extern const struct drm_crtc_funcs emgd_crtc_funcs;
+extern const struct drm_crtc_helper_funcs emgd_crtc_helper_funcs;
+
+/* Encoder Dispatch Tables */
+extern const struct drm_encoder_funcs emgd_encoder_funcs;
+extern const struct drm_encoder_helper_funcs emgd_encoder_helper_funcs;
+
+/* Connector Dispatch Tables */
+extern const struct drm_connector_funcs emgd_connector_funcs;
+extern const struct drm_connector_helper_funcs emgd_connector_helper_funcs;
+
+/* FBCON Dispatch Table */
+extern const struct fb_ops emgd_fb_ops;
+
+
+
+/*------------------------------------------------------------------------------
+ * Formal Declaration
+ *------------------------------------------------------------------------------
+ */
+extern int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev);
+
+static int emgd_fbdev_init(drm_emgd_priv_t *priv);
+static void emgd_fbdev_destroy(drm_emgd_priv_t *priv);
+
+
+
+/*------------------------------------------------------------------------------
+ * FB Functions
+ *------------------------------------------------------------------------------
+ */
+int emgd_framebuffer_init(struct drm_device *dev,
+ emgd_framebuffer_t *emgd_fb,
+ struct DRM_MODE_FB_CMD_TYPE *mode_cmd,
+ unsigned long offset);
+static struct drm_framebuffer *emgd_user_framebuffer_create(
+ struct drm_device *dev,
+ struct drm_file *filp,
+ struct DRM_MODE_FB_CMD_TYPE *r);
+RETURN_PROBE_TYPE emgd_fb_probe(struct drm_device *dev);
+static int emgd_fb_panic(struct notifier_block *n,
+ unsigned long res,
+ void *panic_str);
+static void emgd_user_framebuffer_destroy (struct drm_framebuffer *fb);
+static int emgd_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv, unsigned int *handle);
+static void emgd_fb_restore(void);
+
+
+static const struct drm_mode_config_funcs emgd_mode_funcs = {
+ .fb_create = emgd_user_framebuffer_create,
+ .PROBE_FUNC = emgd_fb_probe,
+ /*.output_poll_changed: we don't support hotplug */
+};
+
+
+static struct notifier_block paniced = {
+ .notifier_call = emgd_fb_panic,
+};
+
+
+static const struct drm_framebuffer_funcs emgd_fb_funcs = {
+ .destroy = emgd_user_framebuffer_destroy,
+ .create_handle = emgd_user_framebuffer_create_handle,
+};
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
+int convert_bpp_depth_to_drm_pixel_formal(unsigned int bpp, unsigned int depth)
+{
+ switch(bpp){
+ case 8:
+ if(depth == 8)
+ return DRM_FORMAT_RGB332;
+
+ case 16:
+ if(depth == 15)
+ return DRM_FORMAT_XRGB1555;
+ else
+ return DRM_FORMAT_RGB565;
+
+ case 24:
+ return DRM_FORMAT_RGB888;
+
+ case 32:
+ if(depth == 24)
+ return DRM_FORMAT_XRGB8888;
+ else if (depth == 30)
+ return DRM_FORMAT_XRGB2101010;
+ else
+ return DRM_FORMAT_ARGB8888;
+
+ default:
+ EMGD_ERROR("bad bpp %d, assuming x8r8g8b8 pixel format", bpp);
+ return DRM_FORMAT_XRGB8888;
+ }
+}
+#endif
+
+/*
+ * Called if something fails while trying to set up framebuffer based
+ * console.
+ */
+static int emgd_fb_panic(struct notifier_block *n,
+ unsigned long res,
+ void *panic_str)
+{
+ EMGD_DEBUG("Panic occurred, switch back to text console.");
+
+ emgd_fb_restore();
+
+ return 0;
+}
+
+
+/*
+ * emgd_fb_restore
+ *
+ * Restore the kernel's fbcon mode.
+ */
+void emgd_fb_restore(void)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * FIXME: Need to have the real crtc saved so it can be restored.
+ */
+ if ((ret = drm_crtc_helper_set_config(&panic_mode)) != 0) {
+ EMGD_ERROR("Failed to restore crtc configuration: %d", ret);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/* Workqueue task function; needed during CRTC init */
+void emgd_flip_worker(struct work_struct *w);
+
+/*
+ * create_crtcs
+ *
+ * Creates crtcs. This function loops through the valid pipes, creating
+ * one crtc for each pipe. This function assumes that dsp_alloc() has
+ * been run.
+ *
+ * TODO: Move this to emgd_crtc.c?
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return None
+ */
+void create_crtcs(struct drm_device *dev)
+{
+ emgd_crtc_t *emgd_crtc = NULL;
+ drm_emgd_priv_t *dev_priv = NULL;
+ igd_context_t *context = NULL;
+ igd_display_pipe_t *pipe = NULL;
+ int i, index = 0;
+ unsigned short *r, *g, *b;
+
+ EMGD_TRACE_ENTER;
+
+ dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
+ context = dev_priv->context;
+
+ while ((pipe = context->mod_dispatch.dsp_get_next_pipe(context, pipe, 0))) {
+
+ /* FIXME: Why are we allocating the extra space for the
+ * connectors here? */
+ emgd_crtc = kzalloc(sizeof(emgd_crtc_t) +
+ (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
+ GFP_KERNEL);
+
+ if (emgd_crtc == NULL) {
+ EMGD_ERROR("create_crtcs: Failed to allocate CRTC structure.");
+ return;
+ }
+
+ spin_lock_init(&emgd_crtc->crtc_lock);
+
+ emgd_crtc->crtc_id = 1 << index;
+ emgd_crtc->igd_pipe = pipe;
+ dev_priv->crtcs[index] = emgd_crtc;
+ EMGD_DEBUG("Creating CRTC with ID: 0x%x, igd_pipe=0x%lx",
+ emgd_crtc->crtc_id, (unsigned long)pipe);
+
+
+ /* Hook up crtc functions */
+ drm_crtc_init(dev, &emgd_crtc->base, &emgd_crtc_funcs);
+ EMGD_DEBUG(" Created CRTC [%d]", emgd_crtc->base.base.id);
+
+ /* gamma */
+ drm_mode_crtc_set_gamma_size(&emgd_crtc->base, 256);
+
+ /* Set initial gamma values */
+ r = emgd_crtc->base.gamma_store;
+ g = emgd_crtc->base.gamma_store + 256;
+ b = emgd_crtc->base.gamma_store + 512;
+ for (i = 0; i < 256; i++) {
+ emgd_crtc->lut_r[i] = i;
+ emgd_crtc->lut_g[i] = i;
+ emgd_crtc->lut_b[i] = i;
+ emgd_crtc->lut_a[i] = 0;
+ r[i] = (i << 8);
+ g[i] = (i << 8);
+ b[i] = (i << 8);
+ }
+
+ /* Initialize workqueue task to wait for render completion on flips */
+ INIT_WORK(&emgd_crtc->flip_work, emgd_flip_worker);
+ emgd_crtc->flip_work_queued = 0;
+
+ /* Target FB that we're in the process of changing to */
+ emgd_crtc->newfb = NULL;
+
+ /* Target "ops complete" watermark to allow flip to proceed */
+ emgd_crtc->render_complete_at = 0;
+
+ /*
+ * Are we expected to perform flip cleanup (sending userspace event
+ * and such) on next vblank event?
+ */
+ emgd_crtc->vblank_expected = 0;
+
+ /* Userspace 'flip done' event */
+ emgd_crtc->flip_event = NULL;
+
+ /* TODO: Create connector list */
+ emgd_crtc->mode_set.crtc = &emgd_crtc->base;
+ emgd_crtc->mode_set.connectors =
+ (struct drm_connector **)(emgd_crtc + 1);
+ emgd_crtc->mode_set.num_connectors = 0;
+
+ /* Hook up crtc helper functions */
+ drm_crtc_helper_add(&emgd_crtc->base, &emgd_crtc_helper_funcs);
+ index++;
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * create_encoder
+ *
+ * Creates an encoder for the igd_port in the parameter.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param igd_port (IN) pointer to IGD display port. (pd_driver must be valid)
+ *
+ * @return None
+ */
+static void create_encoder(struct drm_device *dev, igd_display_port_t *igd_port)
+{
+ emgd_encoder_t *emgd_encoder;
+ emgd_crtc_t *emgd_crtc;
+ struct drm_crtc *crtc;
+ unsigned long drm_encoder_type;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Find the corresponding DRM encoder type */
+ switch(igd_port->port_type) {
+ case IGD_PORT_LVDS:
+ drm_encoder_type = DRM_MODE_ENCODER_LVDS;
+ break;
+
+ case IGD_PORT_DIGITAL:
+ drm_encoder_type = DRM_MODE_ENCODER_TMDS;
+ break;
+
+ case IGD_PORT_ANALOG:
+ case IGD_PORT_RGBA:
+ case IGD_PORT_TV:
+ case IGD_PORT_SDVO_ST:
+ case IGD_PORT_SDVO_ST_GPIO:
+ default:
+ EMGD_ERROR("Invalid Port Type");
+ return;
+ }
+
+
+ emgd_encoder = kzalloc(sizeof(emgd_encoder_t), GFP_KERNEL);
+ if (!emgd_encoder) {
+ EMGD_ERROR("Out of memory!");
+ return;
+ }
+
+
+ /* What we call "TWIN" is what KMS calls "CLONE". None of the
+ * platforms we currently support allow TWIN, so just set
+ * the bits equal to the port type since a port can always
+ * "TWIN" with itself */
+ emgd_encoder->clone_mask = igd_port->port_type;
+ /*
+ * crtc's are identified by a 1 that is shifted over:
+ * 11
+ * ||_ pipe 0
+ * |__ pipe 1
+ * The order of the pipes is based on how they are initialized
+ * in the drm.
+ */
+ emgd_encoder->crtc_mask = KMS_PIPE_ID(igd_port->port_features);
+ emgd_encoder->igd_port = igd_port;
+ emgd_encoder->state.port = igd_port;
+ emgd_encoder->flags |= ENCODER_FLAG_FIRST_DPMS | ENCODER_FLAG_FIRST_ALTER;
+
+
+ /* Since we do not support TWIN and pipe assignment is fixed, the
+ * current configuration is the only possible configuration */
+ emgd_encoder->base.possible_crtcs = emgd_encoder->crtc_mask;
+ emgd_encoder->base.possible_clones = emgd_encoder->clone_mask;
+
+ /* Initialize the CRTC associated with this encoder. We should
+ * probably use the crtc_mask here to do the matching, but we
+ * have the same info in our internal structures. */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if ((emgd_crtc->igd_pipe->pipe_features & IGD_PORT_MASK) ==
+ emgd_encoder->igd_port->port_type) {
+ emgd_encoder->base.crtc = crtc;
+ break;
+ }
+ }
+
+
+ EMGD_DEBUG("Creating encoder=0x%lx on pipe=0x%lx, of port=0x%lx, "
+ "port_type=0x%lx",
+ (unsigned long)&(emgd_encoder->base), emgd_encoder->crtc_mask,
+ igd_port->port_number, igd_port->port_type);
+
+ drm_encoder_init(dev, &emgd_encoder->base, &emgd_encoder_funcs,
+ drm_encoder_type);
+ drm_encoder_helper_add(&emgd_encoder->base, &emgd_encoder_helper_funcs);
+}
+
+
+
+/**
+ * create_connector_properties
+ *
+ * Creates properties associated with the input connector. Connector properties
+ * are what EMGD calls "port attributes." The only difference is EMGD's port
+ * attributes are per-encoder, not per-connector. For this implementation, we
+ * are assuming one connector per encoder. With this assumption, we can draw
+ * a direct connection between "port attributes" and "connector properties."
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param emgd_connector (IN) Selected connector
+ *
+ * @return None
+ */
+static void create_connector_properties(struct drm_device *dev,
+ emgd_connector_t *emgd_connector)
+{
+ igd_display_port_t *igd_port = emgd_connector->encoder->igd_port;
+ drm_emgd_priv_t *priv = emgd_connector->priv;
+ unsigned long num_of_attributes = 0, num_of_properties = 0;
+ unsigned long i, current_value;
+ pd_attr_t *attributes;
+
+ struct drm_connector *drm_connector = &emgd_connector->base;
+ struct drm_property *new_prop;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Get port attributes from the port driver */
+ priv->context->dispatch.get_attrs(priv->context,
+ igd_port->port_number,
+ &num_of_attributes,
+ &attributes);
+
+
+ /* If the connector has no attributes, then return */
+ if (0 >= num_of_attributes) {
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ emgd_connector->properties =
+ (struct drm_property **) kzalloc(sizeof(struct drm_property *) *
+ num_of_attributes, GFP_KERNEL);
+
+ if (NULL == emgd_connector->properties) {
+ EMGD_ERROR_EXIT("Failed to allocate emgd_connector->properties");
+ }
+
+
+ /* Convert port attributes to connector properties and attach them */
+ for(i = 0; i < num_of_attributes; i++) {
+
+ /* Invisible attributes are not settable so don't even report
+ * it was a property */
+ if (attributes[i].flags & PD_ATTR_FLAG_USER_INVISIBLE) {
+ continue;
+ }
+
+ /* Instead of using DRM_MODE_PROP_xxxx types, it may be possible
+ * to use the PD_ATTR_TYPE_xxxx types, since the 2nd parameter
+ * to drm_property_create is a flag */
+ switch (attributes[i].type) {
+ case PD_ATTR_TYPE_RANGE:
+ {
+ igd_range_attr_t *attr = (igd_range_attr_t *) &attributes[i];
+
+
+ new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+ attr->name, 3);
+
+ if (NULL == new_prop) {
+ EMGD_ERROR("Failed to allocate new property");
+ continue;
+ }
+
+ new_prop->values[0] = attr->id;
+ new_prop->values[1] = attr->min;
+ new_prop->values[2] = attr->max;
+ current_value = attr->current_value;
+
+ break;
+ }
+
+ case PD_ATTR_TYPE_BOOL:
+ {
+ igd_bool_attr_t *attr = (igd_bool_attr_t *) &attributes[i];
+
+
+ new_prop = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+ attr->name, 2);
+
+ if (NULL == new_prop) {
+ EMGD_ERROR("Failed to allocate new property");
+ continue;
+ }
+
+ new_prop->values[0] = false;
+ new_prop->values[1] = true;
+ current_value = attr->current_value;
+
+ break;
+ }
+
+ case PD_ATTR_TYPE_LIST:
+ case PD_ATTR_TYPE_LIST_ENTRY:
+ case PD_ATTR_TYPE_BUFFER:
+ default:
+ EMGD_ERROR("Unsupported PD Attribute type");
+ continue;
+ }
+
+ drm_connector_attach_property(drm_connector, new_prop, current_value);
+ emgd_connector->properties[num_of_properties++] = new_prop;
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * create_connectors
+ *
+ * Creates connectors associated with the encoder.
+ *
+ * This function currently supports one connector per encoder. Further
+ * development required in the future to support encoders that have more
+ * than one connector.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param emgd_encoder (IN) Encoder to be examined.
+ *
+ * @return None
+ */
+static void create_connectors(struct drm_device *dev,
+ emgd_encoder_t *emgd_encoder)
+{
+ igd_display_port_t *port = emgd_encoder->igd_port;
+ pd_driver_t *pd = port->pd_driver;
+ unsigned long connector_type = DRM_MODE_CONNECTOR_LVDS;
+ emgd_connector_t *emgd_connector;
+
+
+ EMGD_TRACE_ENTER;
+
+ switch (pd->type) {
+ case PD_DISPLAY_LVDS_EXT:
+ case PD_DISPLAY_LVDS_INT:
+ connector_type = DRM_MODE_CONNECTOR_LVDS;
+ break;
+
+ case PD_DISPLAY_FP:
+ connector_type = DRM_MODE_CONNECTOR_DVID;
+ break;
+
+ case PD_DISPLAY_CRT_EXT:
+ case PD_DISPLAY_CRT:
+ connector_type = DRM_MODE_CONNECTOR_VGA;
+ break;
+
+ case PD_DISPLAY_HDMI_INT:
+ connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ break;
+
+ case PD_DISPLAY_HDMI_EXT:
+ connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ break;
+
+ case PD_DISPLAY_DP_INT:
+ connector_type = DRM_MODE_CONNECTOR_DisplayPort;
+ break;
+
+ case PD_DISPLAY_TVOUT:
+ case PD_DISPLAY_TVFP:
+ case PD_DISPLAY_RGBA:
+ case PD_DISPLAY_TVOUT_INT:
+ case PD_DISPLAY_DRGB:
+ EMGD_ERROR("Unsupported connector type");
+ return;
+
+ default:
+ EMGD_ERROR("Unknown connector type");
+ return;
+ }
+
+
+ /* Allocate a new connector */
+ emgd_connector = kzalloc(sizeof(emgd_connector_t), GFP_KERNEL);
+ if (!emgd_connector) {
+ EMGD_ERROR("Out of memory!");
+ return;
+ }
+
+ drm_connector_init(dev, &emgd_connector->base, &emgd_connector_funcs,
+ connector_type);
+
+ drm_mode_connector_attach_encoder(&emgd_connector->base,
+ &emgd_encoder->base);
+
+ drm_connector_helper_add(&emgd_connector->base,
+ &emgd_connector_helper_funcs);
+
+ EMGD_DEBUG("Creating connector=0x%lx, encoder=0x%lx, type=0x%lx",
+ (unsigned long)&(emgd_connector->base),
+ (unsigned long)&(emgd_encoder->base), connector_type);
+
+ emgd_connector->encoder = emgd_encoder;
+ emgd_connector->priv = dev->dev_private;
+ emgd_connector->base.display_info.subpixel_order = SubPixelHorizontalRGB;
+ emgd_connector->base.interlace_allowed = false;
+ emgd_connector->base.doublescan_allowed = false;
+ emgd_connector->base.encoder = &emgd_encoder->base;
+
+ /* Create and attach connector properties */
+ create_connector_properties(dev, emgd_connector);
+
+
+#if 0
+ drm_connector_attach_property(&connector->base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_FULLSCREEN);
+ drm_connector_attach_property(&connector->base,
+ dev->mode_config.edid_property, 0);
+ drm_connector_attach_property(&connector->base,
+ dev->mode_config.dpms_property, 0);
+#endif
+
+
+ drm_sysfs_connector_add(&emgd_connector->base);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_setup_outputs
+ *
+ * This function enumerates all the available outputs (physical connectors) by
+ * first initializing all the encoders in the system, and then querying
+ * the encoders for the connectors.
+ *
+ * Because we are adapting from EMGD, the real work behind detecting encoders
+ * has already been done by the time we get to this function. Therefore,
+ * all we need to do is using existing EMGD HAL dispatch functions to complete
+ * the task.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return
+ */
+void emgd_setup_outputs(struct drm_device *dev)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *igd_context = priv->context;
+ inter_module_dispatch_t *module_dispatch = &igd_context->mod_dispatch;
+ igd_display_port_t *port = NULL;
+ struct drm_encoder *encoder;
+
+ EMGD_TRACE_ENTER;
+
+ /* Loop through all available ports. What KMS calls "encoder" is a
+ * subset of what EMGD calls "port."
+ */
+ while ((port = module_dispatch->dsp_get_next_port(igd_context, port, 0))) {
+
+ /* If there is a port driver, then there's an encoder */
+ if (port->pd_driver) {
+ create_encoder(dev, port);
+ }
+ }
+
+
+ /* For each encoder, create the connectors on the encoder */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ emgd_encoder_t *emgd_encoder;
+
+ emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+ create_connectors(dev, emgd_encoder);
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_modeset_init
+ *
+ * This is the main initialization entry point. Called during driver load
+ * and does basic setup.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param full_kms (IN) If we are running with KMS enabled, then set this
+ * to true to do the full KMS initialization. If not,
+ * then set this to false.
+ *
+ * @return None
+ */
+void emgd_modeset_init(struct drm_device *dev)
+{
+ drm_emgd_priv_t *devpriv = (drm_emgd_priv_t *)dev->dev_private;
+ int ret;
+ struct drm_encoder *encoder;
+
+ EMGD_TRACE_ENTER;
+ drm_mode_config_init(dev); /* drm helper function */
+
+ dev->mode_config.min_width = 0;
+ dev->mode_config.max_width = 4096;
+ dev->mode_config.min_height = 0;
+ dev->mode_config.max_height = 2048;
+ dev->mode_config.funcs = (void *)&emgd_mode_funcs;
+
+
+ /* OTC uses dev->agp->base for fb_base */
+ dev->mode_config.fb_base = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+
+ /* Initialize VBLANK handling */
+ dev->irq_enabled = true;
+ dev->max_vblank_count = 0xffffff; /* 24-bit frame counter */
+
+ ret = drm_vblank_init(dev, devpriv->num_crtc);
+ if (ret) {
+ EMGD_ERROR("Call to drm_vblank_init() failed. drmWaitVBlank() "
+ "will not work.");
+ dev->irq_enabled = false;
+ }
+
+
+ /* Create the crtc's */
+ create_crtcs(dev);
+
+ drm_mode_create_scaling_mode_property(dev);
+ emgd_setup_outputs(dev);
+
+ /* The encoders need to be turned off to prevent the locking of some
+ of the registers - before doing a modeset */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ struct drm_encoder_helper_funcs *e_funcs = encoder->helper_private;
+ (*e_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+ }
+
+ drm_helper_disable_unused_functions(dev);
+
+ /* Initialize the framebuffer device */
+ emgd_fbdev_init(devpriv);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_modeset_destroy
+ *
+ * Clean up resources allocated in emgd_modeset_init. Called during driver
+ * unload
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return None
+ */
+void emgd_modeset_destroy(struct drm_device *dev)
+{
+ drm_emgd_priv_t *priv = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ priv = dev->dev_private;
+ emgd_fbdev_destroy(priv);
+ kfree(priv->emgd_fbdev);
+ priv->emgd_fbdev = NULL;
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/*
+ * emgd_fb_probe
+ *
+ * Registers panic mode for the DRM to switch to.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ *
+ * @return TBD
+ */
+RETURN_PROBE_TYPE emgd_fb_probe(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+ /* Set Panic Mode to 1024x768 because it is an acceptably generic mode */
+ //memset(&panic_mode, 0, sizeof(struct drm_mode_set));
+
+ /* In later kernels this function changes to "output_poll_changed", as
+ * such, it is unclear if we need to implement it at all since we do not
+ * support hot-plug
+ */
+
+
+ /* Register a notifier to switch back to kernel console on panic */
+ atomic_notifier_chain_register(&panic_notifier_list, &paniced);
+
+ EMGD_TRACE_EXIT;
+ RETURN_PROBE;
+}
+EXPORT_SYMBOL(emgd_fb_probe);
+
+
+/**
+ * emgd_user_framebuffer_create
+ *
+ * Creates an instance for the framebuffer.
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param filp (IN)
+ * @param mode_cmd (IN) Input from the DRM_IOCTL_MODE_ADDFB
+ *
+ * @return pointer to allocated FB instance
+ */
+static struct drm_framebuffer *emgd_user_framebuffer_create(
+ struct drm_device *dev,
+ struct drm_file *filp,
+ struct DRM_MODE_FB_CMD_TYPE *mode_cmd)
+{
+ emgd_framebuffer_t *emgd_fb;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
+ if (!emgd_fb) {
+ EMGD_ERROR("Failed to allocate an emgd_framebuffer_t");
+ return NULL;
+ }
+
+ /* Create a framebuffer instance */
+ ret = emgd_framebuffer_init(dev, emgd_fb, mode_cmd,
+ (unsigned long)mode_cmd->DRMMODE_HANDLE);
+ if (ret) {
+ EMGD_ERROR("Failed to create framebuffer instance.");
+ /* TODO: Free the allocation at mode_cmd->handle */
+ kfree(emgd_fb);
+ emgd_fb = NULL;
+ return NULL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return &emgd_fb->base;
+}
+
+
+/**
+ * emgd_framebuffer_init
+ *
+ * Creates an instance for the framebuffer.
+ *
+ * Maps an existing surface, which has been allocated via the PVR services,
+ * into the GTT to make it displayable and returns a 'drm_framebuffer'
+ * struct that can be used to refer to this surface in future KMS
+ * operations. This function is called as a result of drmModeAddFB()
+ * being called in userspace; the handle passed to drmModeAddFB() should
+ * be the kernel meminfo handle (i.e., meminfo->hKernelMemInfo in userspace).
+ *
+ * @param dev (IN) DRM per-device (e.g. one GMA) struct (in "drmP.h")
+ * @param emgd_fb (IN)
+ * @param mode_cmd (IN) Input from the DRM_IOCTL_MODE_ADDFB
+ * @param handle (IN) Handle of allocation. The handle will be the
+ * PVR meminfo handle. The initial framebuffer,
+ * which is allocated directly by the GMM before
+ * the PVR services starts up is a special case;
+ * a handle of 0 will refer to the initial framebuffer.
+ *
+ * @return int return value
+ */
+int emgd_framebuffer_init(struct drm_device *dev,
+ emgd_framebuffer_t *emgd_fb,
+ struct DRM_MODE_FB_CMD_TYPE *mode_cmd,
+ unsigned long handle)
+{
+ drm_emgd_priv_t *dev_priv = NULL;
+ igd_context_t *context = NULL;
+ PVRSRV_PER_PROCESS_DATA *pvr_perproc;
+ PVRSRV_KERNEL_MEM_INFO *pvr_meminfo;
+ struct page **pagelist;
+ unsigned long numpages, gtt_offset, page_offset;
+ int ret, pid;
+
+ EMGD_TRACE_ENTER;
+
+ dev_priv = ((drm_emgd_priv_t *)dev->dev_private);
+ context = dev_priv->context;
+
+ if (handle == EMGD_INITIAL_FRAMEBUFFER) {
+ /*
+ * Special case: initial EMGD framebuffer is allocated via GTT instead
+ * of through the PVR services. It has no PVR meminfo handle.
+ */
+ ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
+ if (ret) {
+ EMGD_ERROR("Failed to create framebuffer instance.");
+ return -ENOMEM;
+ }
+
+ drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
+
+ /*
+ * Initial framebuffer offset is stored in the device
+ * private structure.
+ */
+ emgd_fb->type = GMM_FRAMEBUFFER;
+ emgd_fb->gtt_offset = dev_priv->initfb_info.fb_base_offset;
+ emgd_fb->handle = handle;
+
+ } else {
+ /* Fetch PVR services 'per-process' data structure */
+ pid = OSGetCurrentProcessIDKM();
+ pvr_perproc = PVRSRVPerProcessData(pid);
+
+ /* Look up the kernel-side meminfo for the handle passed in*/
+ ret = PVRSRVLookupHandle(pvr_perproc->psHandleBase,
+ (void**)&pvr_meminfo,
+ (IMG_HANDLE)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (ret != PVRSRV_OK) {
+ EMGD_ERROR("Buffer handle is not a valid PVR surface.");
+ return -EINVAL;
+ }
+
+ /*
+ * Now fetch the page list, number of pages, and offset into the first
+ * page for this buffer.
+ */
+ ret = PVRSRVGetPageListKM(pvr_meminfo, &pagelist, &numpages,
+ &page_offset);
+ if (ret != PVRSRV_OK) {
+ EMGD_ERROR("Failed to get pagelist for PVR surface.");
+ return -EINVAL;
+ }
+
+ /* Map this page list into the GTT */
+ ret = context->dispatch.gmm_import_pages((void**)pagelist, >t_offset,
+ numpages);
+ if (ret < 0) {
+ EMGD_ERROR("Failed to map pagelist into GTT.");
+ return -ENOMEM;
+ }
+
+ /* Create a framebuffer instance */
+ ret = drm_framebuffer_init(dev, &emgd_fb->base, &emgd_fb_funcs);
+ if (ret) {
+ EMGD_ERROR("Failed to create framebuffer instance.");
+ return -ENOMEM;
+ }
+
+ /* Fill the EMGD framebuffer structure */
+ drm_helper_mode_fill_fb_struct(&emgd_fb->base, mode_cmd);
+
+ emgd_fb->type = PVR_FRAMEBUFFER;
+ emgd_fb->pvr_meminfo = pvr_meminfo;
+ emgd_fb->pagelist = pagelist;
+ emgd_fb->gtt_offset = gtt_offset + page_offset;
+ emgd_fb->handle = handle;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*
+ * emgd_user_framebuffer_destroy
+ *
+ * clean up and remove a framebuffer instance.
+ *
+ */
+static void emgd_user_framebuffer_destroy (struct drm_framebuffer *fb)
+{
+ drm_emgd_priv_t *dev_priv = NULL;
+ emgd_framebuffer_t *emgd_fb = NULL;
+ igd_context_t *context = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ dev_priv = ((drm_emgd_priv_t *)fb->dev->dev_private);
+ context = dev_priv->context;
+ emgd_fb = container_of(fb, emgd_framebuffer_t, base);
+
+ /* Unmap pages from GTT */
+ if (emgd_fb->type == PVR_FRAMEBUFFER) {
+ /* PVR-allocated pages imported into GTT: just unmap */
+ EMGD_DEBUG("Unmapping imported PVR framebuffer pages at %lu.", emgd_fb->gtt_offset);
+ context->dispatch.gmm_release_import(emgd_fb->gtt_offset);
+ } else {
+ /* GMM-allocated pages (initial framebuffer): unmap and free pages */
+ EMGD_DEBUG("Unmapping and freeing GMM framebuffer pages at %lu.", emgd_fb->gtt_offset);
+ context->dispatch.gmm_free(emgd_fb->gtt_offset);
+ }
+
+ drm_framebuffer_cleanup(fb);
+ kfree(emgd_fb);
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/*
+ * emgd_user_framebuffer_create_handle
+ *
+ * Returns 'a' handle associated with the drm_framebuffer given in the
+ * parameter. In our case, we return 'the' handle because our handles
+ * are already cross-process compatible, and PVR is keeping track of
+ * the reference count so buffers don't get destroyed unless it is not
+ * used.
+ *
+ * @param fb (IN) DRM framebuffer to look up
+ * @param file_priv (IN) Not used
+ * @param handle (OUT)
+ *
+ * @return 0 on success
+ * @return -EINVAL on failure
+ */
+static int emgd_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ emgd_framebuffer_t *emgd_fb;
+ int ret = -EINVAL;
+
+ EMGD_TRACE_ENTER;
+
+ /* To avoid compiler warning. */
+ (void)file_priv;
+
+ emgd_fb = container_of(fb, emgd_framebuffer_t, base);
+
+ if (NULL != emgd_fb) {
+ *handle = emgd_fb->handle;
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+/**
+ * emgd_fbdev_init
+ *
+ * Allocates and initializes a framebuffer device. Through
+ * drm_fb_helper_initial_config(), this function will set a sane mode and
+ * allocate a framebuffer surface to go with the framebuffer device.
+ *
+ * @param priv (IN) EMGD private DRM data structure
+ *
+ * @return 0 on success
+ */
+
+static int emgd_fbdev_init(drm_emgd_priv_t *priv)
+{
+ emgd_fbdev_t *emgd_fbdev;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_fbdev = kzalloc(sizeof(emgd_fbdev_t), GFP_KERNEL);
+ if (!emgd_fbdev) {
+ return -ENOMEM;
+ }
+
+ emgd_fbdev->priv = priv;
+ priv->emgd_fbdev = emgd_fbdev;
+
+ emgd_fbcon_initial_config(emgd_fbdev);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/**
+ * emgd_fbdev_destroy
+ *
+ * Cleans up resources allocated during emgd_fbdev_init.
+ * Since emgd_fbdev_init() calls drm_fb_helper_initial_config() which leads
+ * to a call to emgd_fb_find_or_create_single(), we are also cleaning up
+ * resources allocated in that function as well. It is unclear if this
+ * clean up is necessary because KMS APIs maybe smart enough to call
+ * the corresponding destory function.
+ *
+ * @param priv (IN) EMGD private DRM data structure
+ *
+ * @return None
+ */
+static void emgd_fbdev_destroy(drm_emgd_priv_t *priv)
+{
+ emgd_fbdev_t *emgd_fbdev = NULL;
+ struct drm_framebuffer *fb = NULL;
+ struct fb_info *info = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_fbdev = priv->emgd_fbdev;
+ fb = &emgd_fbdev->emgd_fb->base;
+
+ if (priv->fbdev) {
+ info = priv->fbdev;
+
+ unregister_framebuffer(info);
+
+ if (info->cmap.len) {
+ fb_dealloc_cmap(&info->cmap);
+ }
+
+ priv->context->dispatch.gmm_unmap(info->screen_base);
+ framebuffer_release(info);
+ }
+
+ drm_framebuffer_cleanup(fb); /* Is this the right place to call this? */
+ priv->context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+
+ kfree(emgd_fbdev->emgd_fb);
+ emgd_fbdev->emgd_fb = NULL;
+
+ EMGD_TRACE_EXIT;
+}
+
+
+
+#if 0
+/*------------------------------------------------------------------------------
+ * drm_fb_helper related functions. These will be removed once we have our
+ * own version of drm_fb_helper (in emgd_fbcon.c)
+ *------------------------------------------------------------------------------
+ */
+static int emgd_fb_find_or_create_single(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes);
+static void emgd_fb_gamma_set(struct drm_crtc *crtc,
+ u16 red, u16 green, u16 blue, int regno);
+static void emgd_fb_gamma_get(struct drm_crtc *crtc,
+ u16 *red, u16 *green, u16 *blue, int regno);
+
+
+
+/* FIXME: This should be removed. */
+static struct drm_fb_helper_funcs emgd_fb_helper_funcs = {
+ .gamma_set = emgd_fb_gamma_set,
+ .gamma_get = emgd_fb_gamma_get,
+ .fb_probe = emgd_fb_find_or_create_single,
+};
+
+
+
+/**
+ * emgd_fb_create
+ *
+ * This function creates a frame buffer using the surface information contained
+ * in surface_info. The working assumption is this function will only be
+ * called once at initialization time. So the buffer allocated here is
+ * for the console.
+ *
+ * @param emgd_fbdev (IN) Framebuffer devices to attach the new FB to
+ * @param surface_info (IN) Information about the surface to be allocated
+ */
+static int emgd_fb_create(emgd_fbdev_t *emgd_fbdev,
+ struct drm_fb_helper_surface_size *surface_info)
+{
+ drm_emgd_priv_t *priv = emgd_fbdev->priv;
+ struct drm_device *dev = priv->ddev;
+ struct fb_info *info = NULL;
+ struct drm_mode_fb_cmd mode_cmd;
+ struct drm_framebuffer *fb = NULL;
+ igd_context_t *context = NULL;
+ int ret;
+ unsigned long size;
+ unsigned long offset = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ context = priv->context;
+
+ priv->initfb_info.width = surface_info->surface_width;
+ priv->initfb_info.height = surface_info->surface_height;
+ priv->initfb_info.screen_pitch = 0;
+ priv->initfb_info.pixel_format = IGD_PF_ARGB32;
+
+ ret = context->dispatch.gmm_alloc_surface(
+ &priv->initfb_info.fb_base_offset,
+ priv->initfb_info.pixel_format,
+ &priv->initfb_info.width,
+ &priv->initfb_info.height,
+ &priv->initfb_info.screen_pitch,
+ &size,
+ IGD_GMM_ALLOC_TYPE_RESERVATION,
+ &priv->initfb_info.flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Allocation of buffer failed: %d", ret);
+ return -ENOMEM;
+ }
+
+ priv->initfb_info.allocated = 1;
+ priv->initfb_info.visible_offset = 0;
+
+ mode_cmd.handle = EMGD_INITIAL_FRAMEBUFFER;
+ mode_cmd.pitch = priv->initfb_info.screen_pitch;
+ mode_cmd.width = surface_info->surface_width;
+ mode_cmd.height = surface_info->surface_height;
+ mode_cmd.bpp = surface_info->surface_bpp;
+ mode_cmd.depth = surface_info->surface_depth;
+
+ /* Allocate fb_info */
+ info = kzalloc(sizeof(struct fb_info), GFP_KERNEL);
+ if (info == NULL) {
+ EMGD_ERROR_EXIT("Allocation of fb_info failed");
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+ return -ENOMEM;
+ }
+ info->par = emgd_fbdev;
+
+ /* Allocate emgd_framebuffer_t */
+ emgd_fbdev->emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
+ if (!emgd_fbdev->emgd_fb) {
+ EMGD_ERROR_EXIT("Allocation of emgd_framebuffer_t failed");
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+ kfree(info);
+ info = NULL;
+ return -ENOMEM;
+ }
+
+ /* Initialize the framebuffer */
+ ret = emgd_framebuffer_init(dev, emgd_fbdev->emgd_fb, &mode_cmd,
+ EMGD_INITIAL_FRAMEBUFFER);
+ if (ret) {
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+ kfree(info);
+ info = NULL;
+ kfree(emgd_fbdev->emgd_fb);
+ emgd_fbdev->emgd_fb = NULL;
+ return ret;
+ }
+
+
+
+ info->flags = FBINFO_DEFAULT /* | FBINFO_CAN_FORCE_OUTPUT */;
+ info->fbops = (struct fb_ops*) &emgd_fb_ops;
+ strcpy(info->fix.id, "emgdfb"); /* fix.id is 16 bytes long */
+ fb = &emgd_fbdev->emgd_fb->base;
+ emgd_fbdev->helper.fb = fb;
+ emgd_fbdev->helper.fbdev = info;
+ priv->fbdev = info;
+
+ EMGD_DEBUG("EMGD: Call fb_alloc_cmap()");
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ EMGD_ERROR("%s: Can't allocate color map", info->fix.id);
+ //mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+
+ /*
+ * Does this need to be filled in and if so, with what? Right now
+ * I'm trying to reuse the framebuffer that was already configured by
+ * the EMGD code.
+ *
+ * setup aperture base/size for vesafb takeover
+ */
+ info->apertures = alloc_apertures(1);
+ if (!info->apertures) {
+ EMGD_ERROR("%s: Can't allocate apertures", info->fix.id);
+ //mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+
+ info->apertures->ranges[0].base =
+ (unsigned long)priv->context->device_context.virt_gttadr;
+ info->apertures->ranges[0].size =
+ priv->context->device_context.gatt_pages << PAGE_SHIFT;
+
+ //mutex_unlock(&dev->struct_mutex);
+ /*
+ * FIXME: What is fix.smem_start vs screen_base?
+ *
+ * smem_start is the start of frame buffer mem (physical address), does
+ * that mean GTT or that it expects a physical contigous block in real
+ * memory?
+ *
+ * screen_base is a virtual address
+ *
+ */
+ /* Set up framebuffer surface */
+ EMGD_DEBUG("EMGD: Call pci_resource_start()");
+ info->fix.smem_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE) +
+ priv->initfb_info.fb_base_offset;
+ info->fix.smem_len = size;
+
+ /* Get kernel virtual memory address of framebuffer */
+ EMGD_DEBUG("EMGD: Call gmm_map()");
+ info->screen_base =
+ priv->context->dispatch.gmm_map(priv->initfb_info.fb_base_offset);
+ if (!info->screen_base) {
+ EMGD_ERROR("%s: Can't map framebuffer surface", info->fix.id);
+ return -ENOSPC;
+ }
+ info->screen_size = size;
+
+ info->pixmap.size = 64 * 1024;
+ info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 1;
+
+ EMGD_DEBUG("Frame buffer %dx%d @ 0x%08lx",
+ fb->width, fb->height, offset);
+
+ EMGD_DEBUG("EMGD: Call vga_switcheroo_client_fb_set()");
+ vga_switcheroo_client_fb_set(dev->pdev, info);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/*
+ * emgd_fb_gamma_set
+ *
+ * Set the gamma values for a framebuffer for a particular
+ * index.
+ *
+ * @param crtc (IN) the drm pipe
+ * @param red (IN) red gamma value
+ * @param green (IN) green gamma value
+ * @param blue (IN) blue gamma value
+ * @param regno (IN) index value which we are setting
+ *
+ * @return None
+ */
+static void emgd_fb_gamma_set(struct drm_crtc *crtc,
+ u16 red, u16 green, u16 blue,
+ int regno)
+{
+ emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ EMGD_TRACE_ENTER;
+ emgd_crtc->lut_r[regno] = red >> 8;
+ emgd_crtc->lut_g[regno] = green >> 8;
+ emgd_crtc->lut_b[regno] = blue >> 8;
+ EMGD_TRACE_EXIT;
+}
+
+
+/*
+ * emgd_fb_gamma_get
+ *
+ * Set the gamma values for a framebuffer for a particular
+ * index.
+ *
+ * @param crtc (IN) the drm pipe
+ * @param red (OUT) red gamma value
+ * @param green (OUT) green gamma value
+ * @param blue (OUT) blue gamma value
+ * @param regno (IN) index value which we are getting
+ *
+ * @return None
+ */
+static void emgd_fb_gamma_get(struct drm_crtc *crtc,
+ u16 *red, u16 *green, u16 *blue,
+ int regno)
+{
+ emgd_crtc_t *emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ EMGD_TRACE_ENTER;
+ *red = (emgd_crtc->lut_r[regno] << 8);
+ *blue = (emgd_crtc->lut_b[regno] << 8);
+ *green = (emgd_crtc->lut_g[regno] << 8);
+ EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_fb_find_or_create_single
+ *
+ * If there is no frame buffer associated with "helper", then allocate a new
+ * one. Otherwise, reuse the existing one.
+ *
+ * @param helper (IN) TBD
+ * @param surface_info (IN) Surface info
+ *
+ * @return None
+ */
+static int emgd_fb_find_or_create_single(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *surface_info)
+{
+ emgd_fbdev_t *fbdev = container_of(helper, emgd_fbdev_t, helper);
+ int new_fb = false;
+
+
+ EMGD_TRACE_ENTER;
+
+ if (!helper->fb) {
+ int ret = emgd_fb_create(fbdev, surface_info);
+ if (ret) {
+ return ret;
+ }
+
+ new_fb = true;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return new_fb;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
new file mode 100644
index 0000000..f267fcf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
@@ -0,0 +1,874 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_fbcon.c
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Framebuffer Console related functions. This is the equivalent of
+ * what is in drm_fb_helper.c, a set of functions for configuring the
+ * framebuffer console.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.oal
+
+#include <drmP.h>
+#include <drm_crtc_helper.h>
+#include <linux/vga_switcheroo.h>
+
+
+#include "user_config.h"
+#include "drm_emgd_private.h"
+#include "mode_dispatch.h"
+#include "emgd_drm.h"
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+#include <linux/export.h>
+#endif
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *------------------------------------------------------------------------------
+ */
+extern emgd_drm_config_t config_drm;
+
+
+
+/*------------------------------------------------------------------------------
+ * Formal Declaration
+ *------------------------------------------------------------------------------
+ */
+extern int emgd_framebuffer_init(struct drm_device *dev,
+ emgd_framebuffer_t *emgd_fb,
+ struct DRM_MODE_FB_CMD_TYPE *mode_cmd,
+ unsigned long handle);
+extern int convert_bpp_depth_to_drm_pixel_formal(unsigned int bpp,
+ unsigned int depth);
+
+
+/* Sets up initial display configuration */
+int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev);
+
+
+/*------------------------------------------------------------------------------
+ * These are called by the framebuffer console
+ *------------------------------------------------------------------------------
+ */
+static int alloc_initial_fb(emgd_fbdev_t *emgd_fbdev);
+static void fill_fix(emgd_fbdev_t *emgd_fbdev, struct fb_info *info);
+static void fill_var(emgd_fbdev_t *emgd_fbdev, struct fb_info *info);
+
+
+
+/*------------------------------------------------------------------------------
+ * FBCON Functions
+ * These are called by the framebuffer console
+ *------------------------------------------------------------------------------
+ */
+static int emgd_fbcon_setcolreg(unsigned int regno,
+ unsigned int red, unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info);
+static int emgd_fbcon_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int emgd_fbcon_set_par(struct fb_info *info);
+static int emgd_fbcon_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int emgd_fbcon_blank(int blank, struct fb_info *info);
+static int emgd_fbcon_setcmap(struct fb_cmap *cmap, struct fb_info *info);
+
+
+/* This is called from within FBCON, the framebuffer console */
+const struct fb_ops emgd_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = emgd_fbcon_check_var,
+ .fb_set_par = emgd_fbcon_set_par,
+ .fb_setcolreg = emgd_fbcon_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_pan_display = emgd_fbcon_pan_display,
+ .fb_blank = emgd_fbcon_blank,
+ .fb_setcmap = emgd_fbcon_setcmap,
+ /* .fb_debug_enter = drm_fb_helper_debug_enter, */
+ /* .fb_debug_leave = drm_fb_helper_debug_leave, */
+};
+
+
+
+static void fill_fix(emgd_fbdev_t *emgd_fbdev, struct fb_info *info)
+{
+ struct drm_framebuffer *fb = &emgd_fbdev->emgd_fb->base;
+
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->fix.mmio_start = 0;
+ info->fix.mmio_len = 0;
+ info->fix.type_aux = 0;
+ info->fix.xpanstep = 1; /* doing it in hw */
+ info->fix.ypanstep = 1; /* doing it in hw */
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+ info->fix.type_aux = 0;
+ info->fix.line_length = fb->DRMFB_PITCH;
+}
+
+
+
+/**
+ * fill_var
+ *
+ * Fills in the fb_info structure. This function is called by alloc_init_fb,
+ * and as such an actual mode would not have been set yet. This means we
+ * don't really know what "var.xres" and "var.yres" will be, so we have to
+ * make the assumption that "config_drm->width" and "config_drm->height"
+ * sepcify the resolution for the eventual mode.
+ *
+ * @param emgd_fbdev [IN] FB device that contains the relevant information
+ * @param info [INOUT] fb_info structure to fill in
+ *
+ * @return 0 on success, an error code otherwise
+ */
+static void fill_var(emgd_fbdev_t *emgd_fbdev, struct fb_info *info)
+{
+ struct drm_framebuffer *fb = &emgd_fbdev->emgd_fb->base;
+
+
+ /* Actual resolution for the mode. We are assuming here that the
+ * mode requested through config_drm->width and config_drm->height can
+ * be set successfully */
+ info->var.xres = config_drm.width;
+ info->var.yres = config_drm.height;
+
+ /* Size of the framebuffer */
+ info->var.xres_virtual = fb->width;
+ info->var.yres_virtual = fb->height;
+
+ info->pseudo_palette = emgd_fbdev->pseudo_palette;
+ info->var.bits_per_pixel = fb->bits_per_pixel;
+ info->var.accel_flags = FB_ACCELF_TEXT;
+ info->var.xoffset = 0;
+ info->var.yoffset = 0;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+
+ switch (fb->depth) {
+ case 8:
+ info->var.red.offset = 0;
+ info->var.green.offset = 0;
+ info->var.blue.offset = 0;
+ info->var.red.length = 8; /* 8bit DAC */
+ info->var.green.length = 8;
+ info->var.blue.length = 8;
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ break;
+ case 15:
+ info->var.red.offset = 10;
+ info->var.green.offset = 5;
+ info->var.blue.offset = 0;
+ info->var.red.length = 5;
+ info->var.green.length = 5;
+ info->var.blue.length = 5;
+ info->var.transp.offset = 15;
+ info->var.transp.length = 1;
+ break;
+ case 16:
+ info->var.red.offset = 11;
+ info->var.green.offset = 5;
+ info->var.blue.offset = 0;
+ info->var.red.length = 5;
+ info->var.green.length = 6;
+ info->var.blue.length = 5;
+ info->var.transp.offset = 0;
+ break;
+ case 24:
+ info->var.red.offset = 16;
+ info->var.green.offset = 8;
+ info->var.blue.offset = 0;
+ info->var.red.length = 8;
+ info->var.green.length = 8;
+ info->var.blue.length = 8;
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ break;
+ case 32:
+ info->var.red.offset = 16;
+ info->var.green.offset = 8;
+ info->var.blue.offset = 0;
+ info->var.red.length = 8;
+ info->var.green.length = 8;
+ info->var.blue.length = 8;
+ info->var.transp.offset = 24;
+ info->var.transp.length = 8;
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+/**
+ * alloc_initial_fb
+ *
+ * This function creates a frame buffer using the config_drm.width and
+ * config_drm.height. The working assumption is this function will only be
+ * called once at initialization time. So the buffer allocated here is
+ * for the console.
+ * FIXME: need to make sure resources are freed properly for all the
+ * failed cases.
+ *
+ * @param emgd_fbdev [IN] Framebuffer device to allocate a buffer for.
+ *
+ * @return 0 on success, an error code otherwise
+ */
+static int alloc_initial_fb(emgd_fbdev_t *emgd_fbdev)
+{
+ struct fb_info *info = NULL;
+ struct drm_device *dev = emgd_fbdev->priv->ddev;
+ drm_emgd_priv_t *priv = emgd_fbdev->priv;
+ igd_context_t *context;
+ int ret;
+ unsigned long size;
+ struct DRM_MODE_FB_CMD_TYPE mode_cmd;
+ unsigned int bpp, depth;
+
+ EMGD_TRACE_ENTER;
+
+
+ context = priv->context;
+
+ memset(&priv->initfb_info, 0, sizeof(priv->initfb_info));
+ priv->initfb_info.width = config_drm.width;
+ priv->initfb_info.height = config_drm.height;
+ priv->initfb_info.pixel_format = IGD_PF_ARGB32;
+ bpp = IGD_PF_BPP(priv->initfb_info.pixel_format);
+ depth = bpp;
+
+ /* The initial framebuffer is a displayable surface. */
+ priv->initfb_info.flags = (priv->initfb_info.flags & IGD_FB_FLAGS_MASK) |
+ IGD_SURFACE_DISPLAY;
+
+ ret = context->dispatch.gmm_alloc_surface(
+ &priv->initfb_info.fb_base_offset,
+ priv->initfb_info.pixel_format,
+ &priv->initfb_info.width,
+ &priv->initfb_info.height,
+ &priv->initfb_info.screen_pitch,
+ &size,
+ IGD_GMM_ALLOC_TYPE_RESERVATION,
+ &priv->initfb_info.flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Allocation of buffer failed: %d", ret);
+ return -ENOMEM;
+ }
+
+ priv->initfb_info.allocated = 1;
+ priv->initfb_info.visible_offset = 0;
+
+
+ /* Allocate emgd_framebuffer_t */
+ emgd_fbdev->emgd_fb = kzalloc(sizeof(emgd_framebuffer_t), GFP_KERNEL);
+
+ if (!emgd_fbdev->emgd_fb) {
+ EMGD_ERROR_EXIT("Allocation of emgd_framebuffer_t failed");
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+ return -ENOMEM;
+ }
+
+
+ /* Initialize emgd_framebuffer_t */
+ mode_cmd.DRMMODE_HANDLE = EMGD_INITIAL_FRAMEBUFFER;
+ mode_cmd.DRMFB_PITCH = priv->initfb_info.screen_pitch;
+ mode_cmd.width = priv->initfb_info.width;
+ mode_cmd.height = priv->initfb_info.height;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
+ mode_cmd.pixel_format = convert_bpp_depth_to_drm_pixel_formal(bpp, depth);
+#else
+ mode_cmd.bpp = bpp;
+ mode_cmd.depth = depth;
+#endif
+
+ ret = emgd_framebuffer_init(dev, emgd_fbdev->emgd_fb, &mode_cmd,
+ EMGD_INITIAL_FRAMEBUFFER);
+ if (ret) {
+ kfree(emgd_fbdev->emgd_fb);
+ emgd_fbdev->emgd_fb = NULL;
+
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+
+ return ret;
+ }
+
+
+ /* Allocate fb_info */
+ info = kzalloc(sizeof(struct fb_info), GFP_KERNEL);
+ if (NULL == info) {
+ EMGD_ERROR_EXIT("Allocation of fb_info failed");
+ drm_framebuffer_cleanup(&emgd_fbdev->emgd_fb->base);
+
+ kfree(emgd_fbdev->emgd_fb);
+ emgd_fbdev->emgd_fb = NULL;
+
+ context->dispatch.gmm_free(priv->initfb_info.fb_base_offset);
+
+ return -ENOMEM;
+ }
+
+
+ info->par = emgd_fbdev; /* Private data for all FBCON functions */
+ info->flags = FBINFO_DEFAULT; /* | FBINFO_CAN_FORCE_OUTPUT */
+ info->fbops = (struct fb_ops*) &emgd_fb_ops;
+ strcpy(info->fix.id, "emgdfb"); /* fix.id is 16 bytes long */
+
+ priv->fbdev = info;
+
+ EMGD_DEBUG("EMGD: Call fb_alloc_cmap()");
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ EMGD_ERROR("%s: Can't allocate color map", info->fix.id);
+
+ return -ENOMEM;
+ }
+
+ /*
+ * Does this need to be filled in and if so, with what? Right now
+ * I'm trying to reuse the framebuffer that was already configured by
+ * the EMGD code.
+ *
+ * setup aperture base/size for vesafb takeover
+ */
+ info->apertures = alloc_apertures(1);
+ if (!info->apertures) {
+ EMGD_ERROR("%s: Can't allocate apertures", info->fix.id);
+ return -ENOMEM;
+ }
+
+ info->apertures->ranges[0].base =
+ (unsigned long)context->device_context.virt_gttadr;
+ info->apertures->ranges[0].size =
+ context->device_context.gatt_pages << PAGE_SHIFT;
+
+
+ /*
+ * FIXME: What is fix.smem_start vs screen_base?
+ *
+ * smem_start is the start of frame buffer mem (physical address), does
+ * that mean GTT or that it expects a physical contigous block in real
+ * memory?
+ *
+ * screen_base is a virtual address
+ *
+ */
+ /* Set up framebuffer surface */
+ EMGD_DEBUG("EMGD: Call pci_resource_start()");
+ info->fix.smem_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE) +
+ priv->initfb_info.fb_base_offset;
+ info->fix.smem_len = size;
+
+ /* Get kernel virtual memory address of framebuffer */
+ EMGD_DEBUG("EMGD: Call gmm_map()");
+ info->screen_base =
+ context->dispatch.gmm_map(priv->initfb_info.fb_base_offset);
+ if (!info->screen_base) {
+ EMGD_ERROR("%s: Can't map framebuffer surface", info->fix.id);
+ return -ENOSPC;
+ }
+
+ info->screen_size = size;
+ info->pixmap.size = 64 * 1024;
+ info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 1;
+
+ /* Initialize info->fix and info->var */
+ fill_fix(emgd_fbdev, info);
+ fill_var(emgd_fbdev, info);
+
+ EMGD_DEBUG("Frame buffer %dx%d @ 0x%08lx",
+ priv->initfb_info.width,
+ priv->initfb_info.height, priv->initfb_info.fb_base_offset);
+
+ EMGD_DEBUG("EMGD: Call vga_switcheroo_client_fb_set()");
+ vga_switcheroo_client_fb_set(dev->pdev, info);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+/**
+ * emgd_fbcon_setcmap
+ *
+ * Sets color map for the framebuffer console device. For now, we will set
+ * both CRTC to the same color map, regardless of which display configuration
+ * we are in. There may be a case in the future where we will have to set
+ * the color map for both CRTCs differently.
+ *
+ * We will also assume that we are dealing with FB_VISUAL_TRUECOLOR because
+ * our alloc_initial_fb() function will only allocate framebuffer of this
+ * type.
+ *
+ * @param cmap [IN] Input color map
+ * @param info [IN] framebuffer to set
+ *
+ * @return 0 on success
+ */
+static int emgd_fbcon_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ emgd_fbdev_t *emgd_fbdev = info->par;
+ struct drm_device *dev = emgd_fbdev->priv->ddev;
+ int ret = 0;
+ u16 *red, *green, *blue, *transp;
+ u16 hred, hgreen, hblue, htransp;
+ u32 new_value, mask;
+ int i, start_index;
+ struct drm_crtc *crtc;
+
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Set all the CRTCs to the same color map */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start_index = cmap->start;
+
+ for(i = 0; i < cmap->len; i++) {
+ htransp = 0xffff;
+ hred = *red++;
+ hgreen = *green++;
+ hblue = *blue++;
+
+ if (transp) {
+ htransp = *transp++;
+ }
+
+ /* The palette only has 17 entries */
+ if (16 < start_index ) {
+ ret = -IGD_ERROR_INVAL_PARAM;
+ break;
+ }
+
+ hred >>= (16 - info->var.red.length);
+ hgreen >>= (16 - info->var.green.length);
+ hblue >>= (16 - info->var.blue.length);
+
+ new_value = (hred << info->var.red.offset) |
+ (hgreen << info->var.green.offset) |
+ (hblue << info->var.blue.offset);
+
+ if (info->var.transp.length > 0) {
+ mask = (1 << info->var.transp.length) - 1;
+ mask <<= info->var.transp.offset;
+ new_value |= mask;
+ }
+
+ ((u32 *) info->pseudo_palette)[start_index] = new_value;
+
+ start_index++;
+ }
+
+ if (ret) {
+ EMGD_ERROR("Invalid parameter.");
+ break;
+ }
+
+ ((struct drm_crtc_helper_funcs *)crtc->helper_private)->load_lut(crtc);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+/*
+ * Currently, we are using the device indpendent DRM functions
+ * for these. If we need to do special processing, then uncomment
+ * these functions and hook them into the function table.
+ */
+static int emgd_fbcon_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+/*
+ * FIXME: Should this fbcon function be implemented this way?
+ * The logic in this function needs to be there in some fbcon function;
+ * through debugging, it was noticed that this particular function and
+ * fb_pan_display are called whenever we do a VT switch (away from Weston).
+ * This function was chosen arbitrarily to flip to the initial framebuffer.
+ */
+static int emgd_fbcon_set_par(struct fb_info *info)
+{
+ int ret = 0;
+ struct drm_device *dev;
+ emgd_fbdev_t *emgd_fbdev;
+ emgd_crtc_t *emgd_crtc;
+ igd_context_t *context;
+ drm_emgd_priv_t *priv;
+ igd_display_pipe_t *pipe;
+ igd_surface_t surface = {0};
+
+ EMGD_TRACE_ENTER;
+
+ emgd_fbdev = info->par;
+ priv = emgd_fbdev->priv;
+ dev = priv->ddev;
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+ /* Determine the active crtc by looking for a non-NULL display context.
+ * We might have to modify this logic if DC is not 1 (that is for single
+ * and extended modes, which we do not fully support at the kms level at
+ * this moment)
+ */
+ if (priv->crtcs[0]->igd_pipe->owner) {
+ emgd_crtc = priv->crtcs[0];
+ } else {
+ emgd_crtc = priv->crtcs[1];
+ }
+
+ pipe = emgd_crtc->igd_pipe;
+
+ /* During the initial modeset, when this function is called, it was observed
+ * the pipe timing and plane were NULL; therefore, this guard here is necesary.
+ */
+ if(!pipe->timing || !pipe->plane) {
+ return ret;
+ }
+
+ /* This logic is very similar to what is done in the flip worker; all that
+ * we are doing here is re-attaching the initial framebuffer to the crtc
+ * and flipping it onto the screen using set_surface.
+ * FIXME: Should we also do a modeset to be safe?
+ */
+ emgd_crtc->newfb = emgd_fbdev->emgd_fb;
+
+ surface.flags = IGD_SURFACE_DISPLAY;
+ surface.offset = emgd_crtc->newfb->gtt_offset;
+ surface.pitch = emgd_crtc->newfb->base.DRMFB_PITCH;
+ surface.width = emgd_crtc->newfb->base.width;
+ surface.height = emgd_crtc->newfb->base.height;
+ surface.pixel_format = IGD_PF_ARGB32;
+
+ ret = context->dispatch.set_surface(pipe->owner, IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY, &surface, NULL, 0);
+ // set mode here: crtc->set_config
+ // look at drm_fb_helper_set_par for reference
+
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+static int emgd_fbcon_setcolreg(unsigned int regno,
+ unsigned int red, unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
+{
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("STUBED emgd_fbcon_setcolreg");
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+
+static int emgd_fbcon_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+/*
+ * Currently, we are using the device indpendent DRM functions
+ * for these. If we need to do special processing, then uncomment
+ * these functions and hook them into the function table.
+ */
+static int emgd_fbcon_blank(int blank, struct fb_info *info)
+{
+ int ret = 0;
+ struct drm_device *dev;
+ struct drm_crtc *crtc = NULL;
+ struct drm_encoder *encoder = NULL;
+ struct drm_encoder_helper_funcs *encoder_funcs;
+ emgd_fbdev_t *emgd_fbdev;
+
+ EMGD_TRACE_ENTER;
+
+ emgd_fbdev = info->par;
+ dev = emgd_fbdev->priv->ddev;
+
+ switch(blank) {
+ case FB_BLANK_UNBLANK:
+ EMGD_DEBUG("Turn on Display");
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+ ((struct drm_crtc_helper_funcs *)crtc->helper_private)->dpms(crtc,
+ DRM_MODE_DPMS_ON);
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if(encoder->crtc == crtc) {
+ encoder_funcs = encoder->helper_private;
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+ }
+ }
+ }
+ break;
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ EMGD_DEBUG("Turn off Display");
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if(encoder->crtc == crtc) {
+ encoder_funcs = encoder->helper_private;
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+ }
+ }
+
+ ((struct drm_crtc_helper_funcs *)crtc->helper_private)->dpms(crtc,
+ DRM_MODE_DPMS_OFF);
+ }
+ break;
+ default:
+ EMGD_DEBUG("ERROR: Incorrect FB_BLANK value passed");
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+
+
+/*
+ * emgd_fbcon_initial_config
+ *
+ * Uses configurations in config_drm to set the start-up configuration.
+ * We will not support configurations that require more than one framebuffer
+ * at DRM boot time. The fallback configuration is SINGLE.
+ *
+ * @param emgd_fbdev (IN) Framebuffer device to initialize
+ *
+ * @return 0 on success, an error code otherwise
+ */
+int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev)
+{
+ int err;
+ unsigned long *dc_assigned;
+ igd_context_t *context;
+ unsigned short port_number;
+ emgd_crtc_t *emgd_crtc;
+ struct drm_crtc *crtc = NULL;
+ igd_display_context_t *primary = NULL, *secondary = NULL;
+ bool mode_set_ret = FALSE;
+ struct drm_device *dev = emgd_fbdev->priv->ddev;
+
+ struct drm_display_mode primary_mode, secondary_mode;
+
+ EMGD_TRACE_ENTER;
+
+
+ context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+
+ /* Basic error checking. SINGLE is the fallback configuration */
+ if( IGD_DISPLAY_CONFIG_CLONE != config_drm.dc &&
+ IGD_DISPLAY_CONFIG_SINGLE != config_drm.dc ) {
+ config_drm.dc = IGD_DISPLAY_CONFIG_SINGLE;
+ }
+
+
+ /*******************************************************
+ * Allocate DSP for the desired DC. This is to make sure the
+ * display context is valid for subsequent operations. The
+ * dc_assigned coming out will contain port info in addition to
+ * display configuration.
+ ******************************************************/
+ /* Query for the best DC that matches the request */
+ err = context->dispatch.query_dc(context, config_drm.dc,
+ &dc_assigned, IGD_QUERY_DC_INIT);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize the display as requested.\n"
+ "The query_dc() function returned %d.", err);
+ return -IGD_ERROR_INVAL;
+ }
+
+ emgd_fbdev->priv->dc = *dc_assigned;
+
+
+ /* Allocate and initialize igd_display_context */
+ err = context->mod_dispatch.dsp_alloc(context, *dc_assigned, 0);
+ if (err) {
+ EMGD_ERROR_EXIT("Cannot initialize display context.\n"
+ "The dsp_alloc() function returned %d.", err);
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Initialize pipe->owner for PRIMARY and SECONDARY */
+ port_number = IGD_DC_PRIMARY(*dc_assigned);
+
+ primary = context->mod_dispatch.dsp_display_list[port_number];
+ PIPE(primary)->owner = primary;
+
+ if (IGD_DC_SECONDARY(*dc_assigned)) {
+ port_number = IGD_DC_SECONDARY(*dc_assigned);
+ secondary = context->mod_dispatch.dsp_display_list[port_number];
+ PIPE(secondary)->owner = secondary;
+ }
+
+
+
+ /*******************************************************
+ * Allocate framebuffer
+ ******************************************************/
+ if (0 == (err = alloc_initial_fb(emgd_fbdev))) {
+
+ /* Attach the frame buffer to the CRTC(s) */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if (PIPE(primary) == emgd_crtc->igd_pipe) {
+ crtc->fb = &emgd_fbdev->emgd_fb->base;
+ }
+
+ /* Attach frame buffer to the secondary CRTC, if necessary */
+ if (IGD_DC_SECONDARY(*dc_assigned) &&
+ PIPE(secondary) == emgd_crtc->igd_pipe) {
+ crtc->fb = &emgd_fbdev->emgd_fb->base;
+ }
+ }
+
+
+ err = register_framebuffer(emgd_fbdev->priv->fbdev);
+
+ EMGD_DEBUG("fb%d: %s framebuffer device",
+ emgd_fbdev->priv->fbdev->node,
+ emgd_fbdev->priv->fbdev->fix.id);
+ }
+
+
+ /*******************************************************
+ * Set Mode for Primary
+ ******************************************************/
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if (PIPE(primary) == emgd_crtc->igd_pipe) {
+
+ memset(&primary_mode, 0, sizeof(primary_mode));
+ primary_mode.crtc_hdisplay = config_drm.width;
+ primary_mode.crtc_vdisplay = config_drm.height;
+ primary_mode.vrefresh = config_drm.refresh;
+
+ mode_set_ret = drm_crtc_helper_set_mode(crtc,
+ &primary_mode,
+ 0, 0,
+ NULL);
+ break;
+ }
+ }
+
+ if (FALSE == mode_set_ret) {
+ EMGD_ERROR_EXIT("Failed to set mode on primary CRTC. Abort.");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ /*******************************************************
+ * Set Mode for Secondary, if necessary
+ ******************************************************/
+ if (IGD_DC_SECONDARY(*dc_assigned)) {
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+ if (PIPE(secondary) == emgd_crtc->igd_pipe) {
+
+ memset(&secondary_mode, 0, sizeof(secondary_mode));
+ secondary_mode.crtc_hdisplay = config_drm.width;
+ secondary_mode.crtc_vdisplay = config_drm.height;
+ secondary_mode.vrefresh = config_drm.refresh;
+
+ mode_set_ret = drm_crtc_helper_set_mode(crtc,
+ &secondary_mode,
+ 0, 0,
+ NULL);
+ break;
+ }
+ }
+
+ }
+
+ if (FALSE == mode_set_ret) {
+ EMGD_ERROR_EXIT("Failed to set mode on secondary CRTC. Abort.");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
new file mode 100755
index 0000000..5625442
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
@@ -0,0 +1,2765 @@
+/*-----------------------------------------------------------------------------
+ * Filename: emgd_interface.c
+ * $Revision: 1.191 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file implements the kernel-space bridge between the IAL and the HAL.
+ * Each of the igd_dispatch_t functions are called by an ioctl's handling
+ * function, that's implemented in this file. All parameters coming from user
+ * space are copied and sent to the HAL. All return parameters and the
+ * overall return value is copied back to the user-space bridge code.
+ * See the description in the file "emgd_hal2drm.c" for more details.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.oal
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "drm_emgd_private.h"
+#include "emgd_drm.h"
+#include "emgd_drv.h"
+#include "memory.h"
+
+#include "module_init.h"
+#include "mode_dispatch.h"
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+#include "msvdx.h"
+#include "topaz.h"
+
+#include "memmap.h"
+#include "sched.h"
+
+#include "services.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+#include "syscommon.h"
+#include "pvr_drm.h"
+
+#include <linkage.h>
+
+#include "pvrversion.h"
+
+/* Turn on tracing for this file only */
+/*
+#undef EMGD_TRACE_ENTER
+#define EMGD_TRACE_ENTER printk( KERN_ERR "%s Entry. ",__FUNCTION__)
+*/
+
+/* The compile-time configuration found in "user_config.c": */
+extern emgd_drm_config_t config_drm;
+/* Module parameters from "emgd_drv.c": */
+extern int drm_emgd_dc;
+extern unsigned x_started;
+
+extern void emgd_init_display(int merge_mod_params, drm_emgd_priv_t *priv);
+
+/**
+ * The driver handle for talking with the HAL, within the DRM/kernel code.
+ * This is a "real handle" as opposed to the "fake handle" in user-space.
+ * Notice that there's only one handle, as the secondary device shares this
+ * handle, and so it is cached here to simplify the ioctl-handling procedures.
+ */
+static igd_driver_h handle = NULL;
+/** This is the dispatch table for the HAL. It is cached for quick access. */
+static igd_dispatch_t *dispatch = NULL;
+
+
+/*!
+ * This is called by emgd_driver_load() once it has a "real" driver handle, to
+ * allow the values to be cached in this file.
+ *
+ * @param drm_handle (IN) the kernel-space HAL's "real" driver handle
+ */
+void emgd_set_real_handle(igd_driver_h drm_handle)
+{
+ handle = drm_handle;
+} /* emgd_set_real_handle() */
+
+/*!
+ * This is called by emgd_driver_load() once it has a "real" dispatch table, to
+ * allow the values to be cached in this file.
+ *
+ * @param drm_dispatch (OUT) the kernel-space HAL's dispatch table
+ */
+void emgd_set_real_dispatch(igd_dispatch_t *drm_dispatch)
+{
+ dispatch = drm_dispatch;
+} /* emgd_set_real_dispatch() */
+
+
+/*
+ * Externally-accessible global variables and functions, for PreInit()-time
+ * configuration:
+ */
+extern mode_context_t mode_context[1];
+extern void dsp_shutdown(igd_context_t *context);
+extern int pi_pd_init(igd_display_port_t *port, unsigned long port_feature,
+ unsigned long second_port_feature, int drm_load_time);
+#ifdef DEBUG_BUILD_TYPE
+extern void emgd_print_params(igd_param_t *params);
+#endif
+extern void emgd_modeset_destroy(struct drm_device *dev);
+
+
+/*
+ * NOTE: The rest of this file contains implementations of the HAL-to-DRM
+ * ioctl-handling procedures.
+ *
+ * The naming convention is: emgd_<HAL-procedure-pointer-name>()
+ */
+
+
+/*!
+ * IOCTL to get chipset information from DRM.
+ */
+int emgd_get_chipset_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_driver_get_chipset_info_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+
+ drm_data->device_id = priv->init_info->device_id;
+ drm_data->revision_id = priv->init_info->vendor_id;
+
+ /*
+ * Copy over the name and description fields. Currently these
+ * are hard coded to a maximum of 40 and 20 characters respectively.
+ */
+ if (strlen(priv->init_info->name) > 39) {
+ strncpy(drm_data->name, priv->init_info->name, 39);
+ drm_data->name[39] = '\0';
+ } else {
+ strcpy(drm_data->name, priv->init_info->name);
+ }
+
+ if (strlen(priv->init_info->chipset) > 19) {
+ strncpy(drm_data->description, priv->init_info->chipset, 19);
+ drm_data->description[19] = '\0';
+ } else {
+ strcpy(drm_data->description, priv->init_info->chipset);
+ }
+
+ return 0;
+}
+
+
+int do_wait_vblank(void *display, int headline, int footline)
+{
+ int rtn;
+ int scnlne;
+ os_alarm_t timeout;
+ int ext = -99999;
+ unsigned long height = PIPE((igd_display_context_t *)display)->timing->height;
+
+ /*EMGD_TRACE_ENTER;*/
+
+ if (footline + 50 > height)
+ ext = IGD_IN_VBLANK;
+
+ timeout = OS_SET_ALARM(50);
+ do {
+ /* Call the HAL: */
+ rtn = dispatch->get_scanline((igd_display_context_t *)display, &scnlne);
+ if (rtn || (scnlne >= footline && scnlne <= footline + 50) || ext == scnlne) {
+ break;
+ }
+ OS_SCHEDULE();
+ } while (!OS_TEST_ALARM(timeout));
+
+ /*EMGD_DEBUG("rtn = %d", rtn);*/
+ /*EMGD_TRACE_EXIT;*/
+ return 0;
+}
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's wait_vblank() procedure.
+ */
+int emgd_wait_vblank(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ int rtn;
+ emgd_drm_driver_set_sync_refresh_t *refresh = arg;
+ igd_display_h *display_handle = &(refresh->display_handle);
+
+ /*EMGD_TRACE_ENTER;*/
+ rtn = do_wait_vblank((igd_display_context_t *)(*display_handle), refresh->start_line, refresh->bottom_line);
+
+ /*EMGD_DEBUG("rtn = %d", rtn);*/
+ /*EMGD_TRACE_EXIT;*/
+ return 0;
+} /* emgd_wait_vblank() */
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's alter_cursor() procedure.
+ */
+int emgd_alter_cursor(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_alter_cursor_t *drm_data = arg;
+
+ /*EMGD_TRACE_ENTER;*/
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->alter_cursor(drm_data->display_handle,
+ &(drm_data->cursor_info),
+ drm_data->image);
+
+
+ /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
+ /*EMGD_TRACE_EXIT;*/
+ return 0;
+} /* emgd_alter_cursor() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's alter_cursor_pos() procedure.
+ */
+int emgd_alter_cursor_pos(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_alter_cursor_pos_t *drm_data = arg;
+
+ /*EMGD_TRACE_ENTER;*/
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->alter_cursor_pos(drm_data->display_handle,
+ &(drm_data->cursor_info));
+
+
+ /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
+ /*EMGD_TRACE_EXIT;*/
+ return 0;
+} /* emgd_alter_cursor_pos() */
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's emgd_get_display_info() procedure.
+ */
+int emgd_get_display_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ /*
+ emgd_drm_get_display_info_t *drm_data = arg;
+
+ igd_context_t *context = (igd_context_t *) handle;
+ drm_emgd_priv_t *priv = (drm_emgd_priv_t *)dev->dev_private;
+*/
+ EMGD_TRACE_ENTER;
+/*
+ EMGD_DEBUG("drm_data->primary = 0x%lx", (unsigned long) drm_data->primary);
+ EMGD_DEBUG("drm_data->secondary = 0x%lx",(unsigned long) drm_data->secondary);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn); */
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_display_info() */
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's alter_displays() procedure.
+ */
+int emgd_alter_displays(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_alter_displays_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ int temp_dc = drm_data->dc;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * If we are in Vertical Extended mode and the caller's dc is also
+ * Vertical Extended, then set it to Clone instead as our HAL doesn't
+ * know anything about Vertical Extended mode.
+ */
+ if(IGD_DC_VEXT(drm_data->dc)) {
+ temp_dc = (drm_data->dc & ~IGD_DISPLAY_CONFIG_MASK) |
+ IGD_DISPLAY_CONFIG_CLONE;
+ if (drm_data->primary_fb_info.height ==
+ drm_data->secondary_fb_info.height) {
+ if(drm_data->primary_pt_info.height ==
+ drm_data->primary_fb_info.height) {
+ drm_data->primary_fb_info.height *= 2;
+ }
+
+ if(drm_data->secondary_pt_info.height ==
+ drm_data->secondary_fb_info.height) {
+ drm_data->secondary_fb_info.height *= 2;
+ }
+ }
+ }
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->alter_displays(handle,
+ /* Note: Since a pointer is passed to drm_data->primary/secondary,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->primary),
+ &(drm_data->primary_pt_info),
+ &(drm_data->primary_fb_info),
+ &(drm_data->secondary),
+ &(drm_data->secondary_pt_info),
+ &(drm_data->secondary_fb_info),
+ temp_dc,
+ drm_data->flags);
+
+ if (!drm_data->rtn) {
+ /*
+ * Special for Vertical Extended, pan the second display
+ */
+ if(IGD_DC_VEXT(drm_emgd_dc) && IGD_DC_VEXT(drm_data->dc)) {
+ dispatch->pan_display(drm_data->secondary, 0,
+ drm_data->secondary_fb_info.height / 2);
+ }
+ /* Communicate the new info to the IMG 3rd-party display driver: */
+ priv->dc = drm_data->dc;
+ priv->primary = drm_data->primary;
+ priv->secondary = drm_data->secondary;
+ priv->primary_port_number = (drm_data->dc & 0xf0) >> 4;
+ priv->secondary_port_number = (drm_data->dc & 0xf00000) >> 20;
+
+ if (priv->must_power_on_ports) {
+ /* The HAL was re-initialized during emgd_driver_pre_init()
+ * (i.e. because the X server was restarted). At that time, it
+ * turned off the port drivers' hardware (so that it could poke new
+ * values into the port drivers). It couldn't turn the hardware
+ * back on then. Do so now.
+ */
+ igd_context_t *context = (igd_context_t *) handle;
+ igd_display_port_t *port = NULL;
+
+ while ((port = context->mod_dispatch.dsp_get_next_port(context,
+ port, 0)) != NULL) {
+ /* only LVDS was turned off, so turn it back on */
+ if (port->pd_driver && (port->port_number == IGD_PORT_TYPE_LVDS)) {
+ EMGD_DEBUG("Turning on power for port %lu\n", port->port_number);
+
+ dispatch->power_display(context, port->port_number,
+ IGD_POWERSTATE_D0);
+ }
+ }
+ priv->must_power_on_ports = 0;
+ }
+
+ if (priv->reinit_3dd) {
+ priv->reinit_3dd(dev);
+ }
+ }
+
+ EMGD_DEBUG("drm_data->primary = 0x%lx", (unsigned long) drm_data->primary);
+ EMGD_DEBUG("drm_data->secondary = 0x%lx",(unsigned long) drm_data->secondary);
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_alter_displays() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
+ */
+int emgd_alter_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_alter_ovl_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Deprecated version of alter_ovl. FIX ME.");
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->alter_ovl2(drm_data->display_handle,
+ (igd_surface_t *) &(drm_data->src_surf),
+ (igd_rect_t *) &(drm_data->src_rect),
+ (igd_rect_t *) &(drm_data->dst_rect),
+ (igd_ovl_info_t *) &(drm_data->ovl_info),
+ drm_data->flags);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_alter_ovl() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's alter_ovl() procedure.
+ */
+int emgd_alter_ovl2(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_alter_ovl2_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+ /* Dump the overlay parameters for debugging */
+ /*
+ printk (KERN_ERR "emgd_alter_ovl2 Entry."
+ "offset=0x%X "
+ "pitch=0x%X "
+ "width=0x%X "
+ "height=0x%X "
+ "pixel_format=0x%X "
+ "flags=0x%X "
+ "virt_addr=0x%X "
+ "pvr2d_mem_info=0x%X "
+ "pvr2d_context_h=0x%X "
+ "hPVR2DFlipChain=0x%X "
+ "src_x1=0x%X "
+ "src_x2=0x%X "
+ "src_y1=0x%X "
+ "src_y2=0x%X "
+ "dest_x1=0x%X "
+ "dest_x2=0x%X "
+ "dest_y1=0x%X "
+ "dest_y2=0x%X "
+ "color_key.src_lo=0x%X "
+ "color_key.src_hi=0x%X "
+ "color_key.dest=0x%X "
+ "color_key.flags=0x%X "
+ "flags=0x%X "
+ ,
+ (unsigned int)drm_data->src_surf.offset ,
+ (unsigned int)drm_data->src_surf.pitch ,
+ (unsigned int)drm_data->src_surf.width ,
+ (unsigned int)drm_data->src_surf.height ,
+ (unsigned int)drm_data->src_surf.pixel_format ,
+ (unsigned int)drm_data->src_surf.flags ,
+ (unsigned int)drm_data->src_surf.virt_addr ,
+ (unsigned int)drm_data->src_surf.pvr2d_mem_info ,
+ (unsigned int)drm_data->src_surf.pvr2d_context_h ,
+ (unsigned int)drm_data->src_surf.hPVR2DFlipChain ,
+ (unsigned int)drm_data->src_rect.x1,
+ (unsigned int)drm_data->src_rect.x2,
+ (unsigned int)drm_data->src_rect.y1,
+ (unsigned int)drm_data->src_rect.y2,
+ (unsigned int)drm_data->dst_rect.x1,
+ (unsigned int)drm_data->dst_rect.x2,
+ (unsigned int)drm_data->dst_rect.y1,
+ (unsigned int)drm_data->dst_rect.y2,
+ (unsigned int)drm_data->ovl_info.color_key.src_lo,
+ (unsigned int)drm_data->ovl_info.color_key.src_hi,
+ (unsigned int)drm_data->ovl_info.color_key.dest,
+ (unsigned int)drm_data->ovl_info.color_key.flags,
+ (unsigned int)drm_data->flags
+ );
+ */
+ switch (drm_data->cmd) {
+ case CMD_ALTER_OVL2:
+ drm_data->rtn = dispatch->alter_ovl2(drm_data->display_handle,
+ &(drm_data->src_surf),
+ &(drm_data->src_rect),
+ &(drm_data->dst_rect),
+ &(drm_data->ovl_info),
+ drm_data->flags);
+ break;
+ case CMD_ALTER_OVL2_OSD:
+ drm_data->rtn = dispatch->alter_ovl2_osd(drm_data->display_handle,
+ &(drm_data->src_surf),
+ &(drm_data->src_rect),
+ &(drm_data->dst_rect),
+ &(drm_data->ovl_info),
+ drm_data->flags);
+ break;
+ default:
+ break;
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+
+ return 0;
+} /* emgd_alter_ovl2() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_ovl_init_params() procedure.
+ */
+int emgd_get_ovl_init_params(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_ovl_init_params_t *drm_data = arg;
+ ovl_um_context_t *ovl_um_context;
+
+ EMGD_TRACE_ENTER;
+
+ /* Call the HAL: */
+ /* there may not be a need to call the hal for this, since we have
+ * access to the overlay context. We can probably just copy what we need
+ * from the context to the drm_data
+ */
+
+ if (!drm_data) {
+ EMGD_DEBUG("Invalid drm_data in emgd_get_ovl_init_params.\n");
+ return 0;
+ }
+
+ ovl_um_context = drm_data->ovl_um_context;
+
+ if (!ovl_um_context) {
+ drm_data->rtn = -1;
+ return 0;
+ }
+
+ drm_data->rtn = dispatch->get_ovl_init_params(handle, ovl_um_context);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_ovl_init_params() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's appcontext_alloc() procedure.
+ */
+int emgd_appcontext_alloc(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_appcontext_alloc_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ /* NOTE: the return value is different than normal: */
+ drm_data->appcontext_h =
+ dispatch->appcontext_alloc(drm_data->display_handle,
+ drm_data->priority,
+ drm_data->flags);
+
+
+ EMGD_DEBUG("drm_data->appcontext_h = %p", drm_data->appcontext_h);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_appcontext_alloc() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's appcontext_free() procedure.
+ */
+int emgd_appcontext_free(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_appcontext_free_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ /* NOTE: no return value is desired: */
+ dispatch->appcontext_free(drm_data->display_handle,
+ drm_data->priority,
+ drm_data->appcontext_h);
+
+
+ EMGD_DEBUG("This function has no drm_data->rtn value");
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_appcontext_free() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's driver_save_restore() procedure.
+ */
+int emgd_driver_save_restore(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ emgd_drm_driver_save_restore_t *drm_data = arg;
+ unsigned long save_flags = 0;
+
+ EMGD_TRACE_ENTER;
+
+ if (config_drm.init) {
+ save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
+ }
+ else {
+ save_flags = IGD_REG_SAVE_ALL;
+ }
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->driver_save_restore(handle, save_flags);
+
+ /* Change the state of what's saved: */
+ if (priv->saved_registers == CONSOLE_STATE_SAVED) {
+ priv->saved_registers = X_SERVER_STATE_SAVED;
+ EMGD_DEBUG("State of saved registers is X_SERVER_STATE_SAVED");
+ } else {
+ priv->saved_registers = CONSOLE_STATE_SAVED;
+ EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
+ }
+
+ if (priv->saved_registers == X_SERVER_STATE_SAVED &&
+ !priv->qb_seamless && !config_drm.kms && config_drm.init) {
+ emgd_init_display(FALSE, priv);
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_driver_save_restore() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's enable_port() procedure.
+ */
+int emgd_enable_port(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_enable_port_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->enable_port(drm_data->display_handle,
+ drm_data->port_number,
+ drm_data->flag,
+ drm_data->test);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_enable_port() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_attrs() procedure.
+ */
+int emgd_get_attrs(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_attrs_t *drm_data = arg;
+ igd_attr_t *attr_list = NULL;
+ igd_attr_t *ext_list = NULL;
+ igd_extension_attr_t *tmp = NULL;
+ int i = 0;
+ int extended = 0;
+ int core_cnt = 0;
+ int ext_cnt = 0;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_attrs(handle,
+ drm_data->port_number,
+ &(drm_data->list_size),
+ /* Note: get_attrs() returns a pointer to live data, that the caller
+ * (i.e. this procedure) is not supposed to free/alter. Therefore,
+ * this data must be copied into the space pointed to by
+ * drm_data->attr_list (assuming enough memory was allocated for it--if
+ * not, the hal2drm code will allocate drm_data->list_size and call
+ * this ioctl again).
+ */
+ &(attr_list));
+
+ /*
+ * The attribute list may have an extension list in addition to
+ * the core attributes. The caller may want the core list or
+ * the extenstion list. Use the extended flag in drm_data to
+ * determine this. If the caller is looking for the count, then
+ * return either core or extended size.
+ */
+
+ while ((i < drm_data->list_size) && (attr_list[i].id != PD_ATTR_LIST_END)){
+ if (attr_list[i].id == PD_ATTR_ID_EXTENSION) {
+ extended = 1;
+ tmp = (igd_extension_attr_t *)&attr_list[i];
+ ext_list = tmp->extension;
+
+ /* Count extension attributes */
+ while ((ext_cnt < drm_data->list_size) &&
+ (ext_list[ext_cnt].id != PD_ATTR_LIST_END)){
+ ext_cnt++;
+ }
+ }
+ core_cnt++;
+ i++;
+ }
+
+ if(drm_data->port_number == IGD_PORT_TYPE_LVDS) {
+ /* LVDS port driver returns +1 is to include the end attribute */
+ ext_cnt++;
+ }
+ if (drm_data->extended) {
+ drm_data->list_size = ext_cnt; /* size of extension list */
+
+ /* Copy the attribute array back to user-space, if enough room: */
+ if ((drm_data->allocated_size > 0) &&
+ (drm_data->list_size <= drm_data->allocated_size)) {
+ OS_MEMCPY(drm_data->attr_list, ext_list,
+ (drm_data->list_size * sizeof(igd_attr_t)));
+ }
+ } else {
+ drm_data->list_size = core_cnt;
+
+ /* Copy the attribute array back to user-space, if enough room: */
+ if ((drm_data->allocated_size > 0) &&
+ (drm_data->list_size <= drm_data->allocated_size)) {
+ OS_MEMCPY(drm_data->attr_list, attr_list,
+ (drm_data->list_size * sizeof(igd_attr_t)));
+ }
+ }
+
+
+ drm_data->extended = extended;
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_attrs() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_display() procedure.
+ */
+int emgd_get_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ igd_context_t *context = (igd_context_t *) handle;
+ emgd_drm_get_display_t *drm_data = arg;
+ igd_display_context_t *display =
+ (igd_display_context_t *) drm_data->display_handle;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ int dc, port_num;
+ int do_reinit_3dd = 1;
+
+ EMGD_TRACE_ENTER;
+
+ /* Can we overload this to get the display handle if it's null? */
+ if (display == NULL) {
+ display = context->mod_dispatch.dsp_display_list[drm_data->port_number];
+ drm_data->display_handle = display;
+ }
+
+ /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
+ if ((display == NULL) || (PORT(display, drm_data->port_number) == NULL)) {
+ EMGD_ERROR_EXIT("emgd_get_display() given invalid display "
+ "handle (0x%x) or port number (%d)", (unsigned int) display,
+ drm_data->port_number);
+ return -IGD_ERROR_INVAL;
+ }
+
+ dc = *(context->mod_dispatch.dsp_current_dc);
+ port_num = drm_data->port_number;
+
+ if (drm_data->flags & IGD_GET_DISPLAY_NO_3DD_REINIT){
+ do_reinit_3dd = 0;
+ drm_data->flags &= (~IGD_GET_DISPLAY_NO_3DD_REINIT);
+ }
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_display(drm_data->display_handle,
+ drm_data->port_number,
+ /* Note: Since a pointer is passed to drm_data->fb_info/pt_info,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->fb_info),
+ &(drm_data->pt_info),
+ drm_data->flags);
+
+ /* In seamless mode this gets called instead of alter_displays */
+ /* The reason why we do not want to call reinit_3dd() if the clone mode is
+ * set and if this function was called to get the secondary handle is because
+ * reinit_3dd() calls init_display() which in turn calls get_display() and passes
+ * the handle for secondary, and primary port number hence leading to an incorrect
+ * combination. Also, we may not have to call reinit_3dd() as this is already done
+ * as a part of configuring the primary.
+ */
+ if (do_reinit_3dd) {
+ if(mode_context->seamless && !(IGD_DC_CLONE(dc) && port_num == priv->secondary_port_number)) {
+ if (priv->reinit_3dd) {
+ if(IGD_DC_VEXT(drm_emgd_dc)) {
+ priv->dc = drm_emgd_dc;
+ } else {
+ priv->dc = *(context->mod_dispatch.dsp_current_dc);
+ }
+ EMGD_DEBUG("priv->dc = 0x%lX", priv->dc);
+ priv->primary = drm_data->display_handle;
+ priv->secondary = NULL;
+ priv->primary_port_number = (priv->dc & 0xf0) >> 4;
+ priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
+ priv->reinit_3dd(dev);
+ }
+ }
+ }
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_display() */
+
+
+/*!
+ * IOCTL to support emgd_hal2drm_drm_config(), which returns to the X driver
+ * the igd_param_t that was used at load time, as well as the "config ID" that
+ * was either specified by the "configid" module parameter of stored in the
+ * VBOIS (by calling igd_get_param(...,IGD_PARAM_PANEL_ID,...)).
+ */
+int emgd_get_drm_config(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_drm_config_t *drm_data = arg;
+ igd_param_t *params;
+ int i;
+
+
+ EMGD_TRACE_ENTER;
+
+
+ /*
+ * Return the igd_param_t parameter values used at module load time:
+ */
+ if (drm_emgd_configid < 0) {
+ params = config_drm.hal_params[0];
+ } else {
+ params = config_drm.hal_params[drm_emgd_configid-1];
+ }
+ if (config_drm.init) {
+ drm_data->display_config = drm_emgd_dc;
+ } else {
+ drm_data->display_config = config_drm.dc;
+ }
+ drm_data->params.page_request = params->page_request;
+ drm_data->params.max_fb_size = params->max_fb_size;
+ drm_data->params.preserve_regs = params->preserve_regs;
+ drm_data->params.display_flags = params->display_flags;
+ drm_data->params.display_color = params->display_color;
+ drm_data->params.quickboot = params->quickboot;
+ drm_data->params.qb_seamless = params->qb_seamless;
+ drm_data->params.qb_video_input = params->qb_video_input;
+ drm_data->params.qb_splash = params->qb_splash;
+ drm_data->params.polling = params->polling;
+ drm_data->params.ref_freq = params->ref_freq;
+ drm_data->params.tuning_wa = params->tuning_wa;
+ drm_data->params.clip_hw_fix = params->clip_hw_fix;
+ drm_data->params.async_flip_wa = params->async_flip_wa;
+ drm_data->params.en_reg_override = params->en_reg_override;
+ drm_data->params.disp_arb = params->disp_arb;
+ drm_data->params.fifo_watermark1 = params->fifo_watermark1;
+ drm_data->params.fifo_watermark2 = params->fifo_watermark2;
+ drm_data->params.fifo_watermark3 = params->fifo_watermark3;
+ drm_data->params.fifo_watermark4 = params->fifo_watermark4;
+ drm_data->params.fifo_watermark5 = params->fifo_watermark5;
+ drm_data->params.fifo_watermark6 = params->fifo_watermark6;
+ drm_data->params.gvd_hp_control = params->gvd_hp_control;
+ drm_data->params.bunit_chicken_bits = params->bunit_chicken_bits;
+ drm_data->params.bunit_write_flush = params->bunit_write_flush;
+ drm_data->params.disp_chicken_bits = params->disp_chicken_bits;
+ drm_data->params.punt_to_3dblit = params->punt_to_3dblit;
+
+ for (i = 0 ; i < IGD_MAX_PORTS ; i++) {
+ drm_data->params.port_order[i] = params->port_order[i];
+ drm_data->params.display_params[i].port_number =
+ params->display_params[i].port_number;
+ drm_data->params.display_params[i].present_params =
+ (params->display_params[i].present_params &
+ ~(IGD_PARAM_DTD_LIST | IGD_PARAM_ATTR_LIST));
+ drm_data->params.display_params[i].flags =
+ params->display_params[i].flags;
+ drm_data->params.display_params[i].edid_avail =
+ params->display_params[i].edid_avail;
+ drm_data->params.display_params[i].edid_not_avail =
+ params->display_params[i].edid_not_avail;
+ drm_data->params.display_params[i].ddc_gpio =
+ params->display_params[i].ddc_gpio;
+ drm_data->params.display_params[i].ddc_speed =
+ params->display_params[i].ddc_speed;
+ drm_data->params.display_params[i].ddc_dab =
+ params->display_params[i].ddc_dab;
+ drm_data->params.display_params[i].i2c_gpio =
+ params->display_params[i].i2c_gpio;
+ drm_data->params.display_params[i].i2c_speed =
+ params->display_params[i].i2c_speed;
+ drm_data->params.display_params[i].i2c_dab =
+ params->display_params[i].i2c_dab;
+ drm_data->params.display_params[i].fp_info =
+ params->display_params[i].fp_info;
+ /* No DTDs nor attrs are sent up. If "xorg.conf" lists none, the
+ * defaults (in "user_config.c") are still in force. If anything
+ * is listed in "xorg.conf", it overrides the defaults. Thus,
+ * there's no need to send them up.
+ */
+ }
+
+ /*
+ * Return the "ConfigID" to return (either the module parameter or the
+ * value stored in VBIOS:
+ */
+ if (drm_emgd_configid > 0) {
+ drm_data->config_id = drm_emgd_configid;
+ } else {
+ /* Call the HAL: */
+ int err = igd_get_param(handle, IGD_PARAM_PANEL_ID,
+ /* Note: Since a pointer is passed to drm_data->value,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &drm_data->config_id);
+ if (err) {
+ /* Either the vBIOS doesn't exist, or there was a problem reading
+ * it. Either way, don't error; just set the config_id to an
+ * invalid value:
+ */
+ drm_data->config_id = -1;
+ }
+ }
+
+ /* Fill in DDK & EMGD version numbers and debug status */
+ drm_data->build_config.ddk_version = PVRVERSION_BUILD;
+ drm_data->build_config.emgd_version = IGD_BUILD_NUM;
+#ifdef DEBUG
+ drm_data->build_config.debug = 1;
+#else
+ drm_data->build_config.debug = 0;
+#endif
+
+ drm_data->rtn = 0;
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_drm_config() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_EDID_block() procedure.
+ */
+int emgd_get_EDID_block(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_EDID_block_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_EDID_block(handle,
+ drm_data->port_number,
+ /* Note: Since a pointer is passed to drm_data->edid_block,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ drm_data->edid_block,
+ drm_data->block_number);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_EDID_block() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_EDID_info() procedure.
+ */
+int emgd_get_EDID_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_EDID_info_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_EDID_info(handle,
+ drm_data->port_number,
+ /* Note: Since a pointer is passed to drm_data->edid_*,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->edid_version),
+ &(drm_data->edid_revision),
+ &(drm_data->edid_size));
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_EDID_info() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_pixelformats() procedure.
+ */
+int emgd_get_pixelformats(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_pixelformats_t *drm_data = arg;
+ unsigned long *format_list = NULL;
+ unsigned long *fb_list_pfs = NULL;
+ unsigned long *cu_list_pfs = NULL;
+ unsigned long *overlay_pfs = NULL;
+ unsigned long *render_pfs = NULL;
+ unsigned long *texture_pfs = NULL;
+ unsigned long *pf;
+ int count = 1;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* The HAL's get_pixelformats() procedure determines which formats are
+ * wanted based on whether a pointer is NULL or not, and so we need to make
+ * the desired-format's pointer non-NULL (setting it to 1 works, though it
+ * is kinda cheating:-):
+ */
+ if (drm_data->format == PIXEL_FORMAT_FRAMEBUFFER) {
+ fb_list_pfs = (unsigned long *) 1;
+ } else if (drm_data->format == PIXEL_FORMAT_CURSOR) {
+ cu_list_pfs = (unsigned long *) 1;
+ } else if (drm_data->format == PIXEL_FORMAT_OVERLAY) {
+ overlay_pfs = (unsigned long *) 1;
+ } else if (drm_data->format == PIXEL_FORMAT_RENDER) {
+ render_pfs = (unsigned long *) 1;
+ } else if (drm_data->format == PIXEL_FORMAT_TEXTURE) {
+ texture_pfs = (unsigned long *) 1;
+ }
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_pixelformats(drm_data->display_handle,
+ &fb_list_pfs, &cu_list_pfs, &overlay_pfs, &render_pfs, &texture_pfs);
+
+
+ /* Next, point format_list at the correct list: */
+ if (drm_data->format == PIXEL_FORMAT_FRAMEBUFFER) {
+ format_list = fb_list_pfs;
+ } else if (drm_data->format == PIXEL_FORMAT_CURSOR) {
+ format_list = cu_list_pfs;
+ } else if (drm_data->format == PIXEL_FORMAT_OVERLAY) {
+ format_list = overlay_pfs;
+ } else if (drm_data->format == PIXEL_FORMAT_RENDER) {
+ format_list = render_pfs;
+ } else if (drm_data->format == PIXEL_FORMAT_TEXTURE) {
+ format_list = texture_pfs;
+ }
+
+
+ /* Count how many pixelformats were returned: */
+ pf = format_list;
+ while (*pf) {
+ pf++;
+ count++;
+ }
+ drm_data->list_size = count;
+
+
+ /* Copy the pixel format list/array back to user-space, if enough room. If
+ * there isn't enough memory allocated, the hal2drm code will allocate
+ * drm_data->list_size and call this ioctl again).
+ */
+ if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
+ OS_MEMCPY(drm_data->format_list, format_list,
+ (count * sizeof(unsigned long)));
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_pixelformats() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_port_info() procedure.
+ */
+int emgd_get_port_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_port_info_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->get_port_info(handle,
+ drm_data->port_number,
+ /* Note: Since a pointer is passed to drm_data->port_info,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->port_info));
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_port_info() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's gmm_alloc_region() procedure.
+ */
+int emgd_gmm_alloc_region(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_alloc_region_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->gmm_alloc_region(
+ /* Note: Since a pointer is passed to drm_data->offset/size,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->offset),
+ &(drm_data->size),
+ drm_data->type,
+ drm_data->flags);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_gmm_alloc_region() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's gmm_alloc_surface() procedure.
+ */
+int emgd_gmm_alloc_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_alloc_surface_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->gmm_alloc_surface(
+ /* Note: Since a pointer is passed to drm_data->*,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->offset),
+ drm_data->pixel_format,
+ &(drm_data->width),
+ &(drm_data->height),
+ &(drm_data->pitch),
+ &(drm_data->size),
+ drm_data->type,
+ &(drm_data->flags));
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_gmm_alloc_surface() */
+
+int emgd_gmm_get_num_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_get_num_surface_t *drm_data = arg;
+ EMGD_TRACE_ENTER;
+
+ drm_data->rtn = dispatch->gmm_get_num_surface(
+ &(drm_data->count));
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int emgd_gmm_get_surface_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_get_surface_list_t *drm_data = arg;
+ igd_surface_list_t *surface_list = NULL;
+ EMGD_TRACE_ENTER;
+
+ drm_data->rtn = dispatch->gmm_get_surface_list(
+ drm_data->allocated_size,
+ &(drm_data->list_size),
+ &(surface_list));
+
+ /* Copy the surface array back to user-space, if enough room */
+ if ((drm_data->allocated_size > 0) &&
+ (drm_data->list_size <= drm_data->allocated_size)) {
+ OS_MEMCPY(*(drm_data->surface_list), surface_list,
+ (drm_data->list_size * sizeof(igd_surface_list_t)));
+ }
+
+ vfree(surface_list);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's gmm_free() procedure.
+ */
+int emgd_gmm_free(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_free_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ /* NOTE: no return value is desired: */
+ dispatch->gmm_free(drm_data->offset);
+
+
+ EMGD_DEBUG("This function has no drm_data->rtn value");
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_gmm_free() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's gmm_flush_cache() procedure.
+ */
+int emgd_gmm_flush_cache(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_gmm_flush_cache_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->gmm_flush_cache();
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_gmm_flush_cache() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's pan_display() procedure.
+ */
+int emgd_pan_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_pan_display_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ /* NOTE: the return value is different than normal: */
+ drm_data->rtn = dispatch->pan_display(drm_data->display_handle,
+ drm_data->x_offset,
+ drm_data->y_offset);
+
+ /* after call this func, we are not in clone mode, is it? */
+ if (drm_data->rtn == 0) {
+ context->mod_dispatch.in_dih_clone_mode = false;
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %ld", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_pan_display() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's power_display() procedure.
+ */
+int emgd_power_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_power_display_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+ igd_display_context_t *display;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
+ display = context->mod_dispatch.dsp_display_list[drm_data->port_number];
+ if ((display == NULL) || (PORT(display, drm_data->port_number) == NULL)) {
+ EMGD_ERROR_EXIT("emgd_power_display() given an invalid port "
+ "number (%d)\n", drm_data->port_number);
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->power_display(handle,
+ drm_data->port_number,
+ drm_data->power_state);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_power_display() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's pwr_alter() procedure.
+ */
+int emgd_pwr_alter(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_pwr_alter_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->pwr_alter(handle, drm_data->power_state);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_pwr_alter() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's query_dc() procedure.
+ */
+int emgd_query_dc(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_query_dc_t *drm_data = arg;
+ unsigned long *dc_list = NULL;
+ unsigned long *dc;
+ int count = 1;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Next, We don't need to copy the DC list from user-space, since
+ * the HAL is going to point us to its internal list.
+ */
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->query_dc(handle,
+ drm_data->request,
+ /* Note: query_dc() returns a pointer to its live internal list, that
+ * the caller (i.e. this procedure) is not supposed to free/alter.
+ * Therefore, this data must be copied into the space pointed to by
+ * drm_data->dc_list (assuming enough memory was allocated for it--if
+ * not, the hal2drm code will allocate drm_data->list_size and call
+ * this ioctl again).
+ */
+ &dc_list,
+ drm_data->flags);
+
+
+ /* Count how many DCs were returned: */
+ if(dc_list == NULL){
+ EMGD_ERROR("query_dc() returned NULL !");
+ return 1;
+ }
+ dc = dc_list;
+ while (*dc) {
+ dc++;
+ count++;
+ }
+
+ drm_data->list_size = count;
+ EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
+
+
+ /* Copy the DC list back to user-space, if enough room: */
+ if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
+ EMGD_DEBUG("Copying list");
+ OS_MEMCPY(drm_data->dc_list, dc_list, (count * sizeof(unsigned long)));
+ EMGD_DEBUG("Copied list");
+ }
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_query_dc() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's query_max_size_ovl() procedure.
+ */
+int emgd_query_max_size_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_query_max_size_ovl_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->query_max_size_ovl(drm_data->display_handle,
+ drm_data->pf,
+ /* Note: Since a pointer is passed to drm_data->*,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->max_width),
+ &(drm_data->max_height));
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_query_max_size_ovl() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's query_ovl() procedure.
+ */
+int emgd_query_ovl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_query_ovl_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->query_ovl(drm_data->display_handle,
+ drm_data->flags);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_query_ovl() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's query_mode_list() procedure.
+ */
+int emgd_query_mode_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_query_mode_list_t *drm_data = arg;
+ igd_display_info_t *mode_list = NULL;
+ igd_display_info_t *mode;
+ int count = 1;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->query_mode_list(handle,
+ drm_data->dc,
+ /* Note: query_mode_list() **MAY** return a pointer to live data, that
+ * the caller (i.e. this procedure) is not supposed to free/alter.
+ * Therefore, this data is copied into the space pointed to by
+ * drm_data->mode_list (assuming enough memory was allocated for it--if
+ * not, the hal2drm code will allocate drm_data->list_size and call
+ * this ioctl again).
+ */
+ &mode_list,
+ drm_data->flags);
+
+
+ /* Count how many modes were returned: */
+ mode = mode_list;
+ while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+ mode++;
+ count++;
+ }
+ drm_data->list_size = count;
+ EMGD_DEBUG("drm_data->list_size = %d", drm_data->list_size);
+
+
+ /* Next, copy the mode list back to user-space: */
+ if ((drm_data->allocated_size > 0) && (count <= drm_data->allocated_size)) {
+ EMGD_DEBUG("Copying list");
+ OS_MEMCPY(drm_data->mode_list, mode_list,
+ (count * sizeof(igd_display_info_t)));
+ EMGD_DEBUG("Copied list");
+ }
+
+ /* Finally, if a non-live list was requested, free the kernel memory: */
+ if (!(drm_data->flags & IGD_QUERY_LIVE_MODES)) {
+ dispatch->free_mode_list(mode_list);
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_query_mode_list() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's set_attrs() procedure.
+ */
+int emgd_set_attrs(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_set_attrs_t *drm_data = arg;
+ igd_attr_t *attr_list = drm_data->attr_list;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_attrs(handle,
+ drm_data->port_number,
+ /* Note: Since a pointer is passed to drm_data->num_attrs and
+ * drm_data->attr_list, there's no need to copy anything back into
+ * drm_data, except for the return value.
+ */
+ drm_data->list_size,
+ attr_list);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_set_attrs() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's set_palette_entry() procedure.
+ */
+int emgd_set_palette_entry(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_set_palette_entry_t *drm_data = arg;
+
+ /*EMGD_TRACE_ENTER;*/
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_palette_entry(drm_data->display_handle,
+ drm_data->palette_entry,
+ drm_data->palette_color);
+
+
+ /*EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);*/
+ /*EMGD_TRACE_EXIT;*/
+ return 0;
+} /* emgd_set_palette_entry() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's set_surface() procedure.
+ */
+int emgd_set_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_set_surface_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(drm_data->display_handle,
+ drm_data->priority,
+ drm_data->type,
+ &(drm_data->surface),
+ drm_data->appcontext,
+ drm_data->flags);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_set_surface() */
+
+
+
+/*!
+ * IOCTL to set surface to dih_clone or back to dih.
+ * drm_data->mode = CLONE - sets fake clone clone
+ * drm_data->mode = DIH - reverts back to DIH
+ * drm_data->dih_clone_display = CLONE_PRIMARY, primary cloned
+ * drm_data->dih_clone_display = CLONE_SECONDARY, secondary cloned
+ *
+ */
+int emgd_dihclone_set_surface(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_dihclone_set_surface_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+ igd_plane_t *display_plane1, *display_plane2;
+ igd_display_pipe_t *pipe1, *pipe2;
+ igd_display_context_t *display;
+ igd_surface_t surf;
+ unsigned long dc ;
+ unsigned long x_offset, y_offset;
+ drm_emgd_priv_t *priv = dev->dev_private;
+
+ EMGD_TRACE_ENTER;
+
+ memset(&surf, 0, sizeof(igd_surface_t));
+ dc = *(context->mod_dispatch.dsp_current_dc);
+
+ context->mod_dispatch.dsp_get_planes_pipes(
+ &display_plane1, &display_plane2,
+ &pipe1, &pipe2);
+
+ /* check if the resolutions match */
+ if((pipe1->plane->fb_info->width != pipe2->plane->fb_info->width) ||
+ (pipe1->plane->fb_info->height != pipe2->plane->fb_info->height)){
+ EMGD_ERROR(" emgd_dihclone_set_surface: resolutions don't match");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ if( drm_data->dih_clone_display != CLONE_PRIMARY && drm_data->dih_clone_display != CLONE_SECONDARY){
+
+ EMGD_ERROR(" emgd_dihclone_set_surface: Invalid Clone Display number");
+ return -IGD_ERROR_INVAL;
+ }
+
+ surf.pitch = pipe1->plane->fb_info->screen_pitch;
+ surf.width = pipe1->plane->fb_info->width;
+ surf.height = pipe1->plane->fb_info->height;
+ surf.pixel_format = pipe1->plane->fb_info->pixel_format;
+ surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
+
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+
+ /*reverting back to DIH from fake clone */
+ if( drm_data->mode == DIH){
+ if (IGD_DC_VEXT(drm_emgd_dc)) {
+ /* Clone to VEXT */
+ x_offset = 0;
+
+ y_offset = 0;
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+ /* Call pan display to revert Primary to VEXT */
+ drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
+
+ y_offset = (pipe1->plane->fb_info->height / 2);
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+ /* Call pan_display to revert Secondary to VEXT */
+ drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
+ }else {/* in DIH mode */
+
+ if(context->mod_dispatch.dih_clone_display == CLONE_PRIMARY) {
+
+ EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH1");
+ if (pipe1->owner->port_number == priv->primary_port_number)
+ surf.offset = pipe1->plane->fb_info->fb_base_offset;
+ else
+ surf.offset = pipe2->plane->fb_info->fb_base_offset;
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+
+ if(drm_data->rtn) {
+ EMGD_ERROR(" emgd_dihclone_set_surface1: failed");
+ return -IGD_ERROR_INVAL;
+ }
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+ surf.offset = pipe2->plane->fb_info->saved_offset;
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+ if(drm_data->rtn) {
+ EMGD_ERROR(" emgd_dihclone_set_surface2: failed");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ } else { // if secondary clone
+
+ EMGD_DEBUG(" emgd_dihclone_set_surface: setting DIH2");
+ surf.offset = pipe1->plane->fb_info->saved_offset;
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+ if (pipe1->owner->port_number == priv->secondary_port_number)
+ surf.offset = pipe1->plane->fb_info->fb_base_offset;
+ else
+ surf.offset = pipe2->plane->fb_info->fb_base_offset;
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+
+ }
+ }
+ if (drm_data->rtn == 0) {
+ context->mod_dispatch.in_dih_clone_mode = false;
+ }
+ }
+ /* setting fake clone (dih clone) mode */
+ if (drm_data->mode == CLONE) {
+ if (IGD_DC_VEXT(drm_emgd_dc)) {
+ x_offset = 0;
+
+ if( drm_data->dih_clone_display == CLONE_PRIMARY){
+ y_offset = 0;
+ } else {
+ y_offset = (pipe1->plane->fb_info->height / 2);
+ }
+
+ /* Call Pan display to affect pt_info offsets */
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+ drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+ drm_data->rtn = dispatch->pan_display(display, x_offset, y_offset);
+ } else { /* in DIH mode */
+
+ /*first save the display's original offset */
+ surf.offset = pipe1->plane->fb_info->fb_base_offset;
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_SAVE,
+ &surf,
+ NULL,
+ 0);
+
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+ surf.offset = pipe2->plane->fb_info->fb_base_offset;
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_SAVE,
+ &surf,
+ NULL,
+ 0);
+
+
+ /* primary display */
+ if( drm_data->dih_clone_display == CLONE_PRIMARY){
+ if (pipe1->owner->port_number == priv->primary_port_number)
+ surf.offset = pipe1->plane->fb_info->fb_base_offset;
+ else
+ surf.offset = pipe2->plane->fb_info->fb_base_offset;
+ } else {
+ if (pipe1->owner->port_number == priv->secondary_port_number)
+ surf.offset = pipe1->plane->fb_info->fb_base_offset;
+ else
+ surf.offset = pipe2->plane->fb_info->fb_base_offset;
+ }
+
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+
+ /* secondary display */
+ display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+
+ drm_data->rtn = dispatch->set_surface(display,
+ IGD_PRIORITY_NORMAL,
+ IGD_BUFFER_DISPLAY,
+ &surf,
+ NULL,
+ 0);
+
+ }
+ if(drm_data->rtn == 0){
+ context->mod_dispatch.in_dih_clone_mode = true;
+ context->mod_dispatch.dih_clone_display = drm_data->dih_clone_display;
+ }
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_dihclone_set_surface() */
+
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's sync() procedure.
+ */
+int emgd_sync(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_sync_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = dispatch->sync(drm_data->display_handle,
+ drm_data->priority,
+ /* Note: Since a pointer is passed to drm_data->in_sync,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ &(drm_data->in_sync),
+ drm_data->flags);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_sync() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's driver_pre_init() procedure.
+ */
+int emgd_driver_pre_init(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = NULL;
+ emgd_drm_driver_pre_init_t *drm_data = (emgd_drm_driver_pre_init_t *) arg;
+ igd_param_t *x_params = NULL;
+ igd_param_t *uc_params = NULL;
+ igd_fb_caps_t *pf_caps;
+ igd_display_port_t *port = NULL;
+ int i, err = 0, need_to_startup_hal = (!priv->hal_running) ? 1 : 0;
+ unsigned long save_flags;
+
+ EMGD_TRACE_ENTER;
+
+ /* This flag will cause a call to emgd_init_display() in
+ * emgd_driver_lastclose() if config_drm.init is true */
+ x_started = true;
+
+ /*
+ * Need to apply the "x_params" (e.g. "xorg.conf" values, from user-space)
+ * in the same order as igd_module_init():
+ * - Nothing to do for REG_INIT(), gmm_init(), nor CMD_INIT().
+ * - mode_init() has several steps (see below).
+ * - Nothing to do for APPCONTEXT_INIT().
+ * - OVERLAY_INIT() is simple (see below).
+ * - Nothing to do for PWR_INIT(), RESET_INIT(), OS_INIT_INTERRUPT(),
+ * BLEND_INIT(), nor INIT_2D().
+ */
+ x_params = &(drm_data->params);
+
+
+ /* Before applying them, first see if the X driver sent any DTD or attr
+ * list(s) for the given ports (i.e. from "xorg.conf"). If not, the values
+ * from "user_config.c" are supposed to be used (and so they need to be
+ * looked up and copied).
+ */
+ if (drm_emgd_configid < 0) {
+ uc_params = config_drm.hal_params[0];
+ } else {
+ uc_params = config_drm.hal_params[drm_emgd_configid-1];
+ }
+ for (i = 0 ; i < IGD_MAX_PORTS ; i++) {
+ igd_display_params_t *x_dp = &x_params->display_params[i];
+ igd_display_params_t *uc_dp = NULL;
+ int j;
+
+ if ((x_dp->port_number > 0) && (x_dp->dtd_list.num_dtds == 0)) {
+ /* X didn't have any DTDs for this port. Look up the corresponding
+ * display params from "user_config.c"
+ */
+ for (j = 0 ; j < IGD_MAX_PORTS ; j++) {
+ uc_dp = &uc_params->display_params[j];
+ if (uc_dp->port_number == x_dp->port_number) {
+ break;
+ }
+ }
+ if ((x_dp->port_number == uc_dp->port_number) ||
+ (uc_dp->dtd_list.num_dtds > 0)) {
+ /* Have X's DTD list point to "user_config.c"'s DTD list */
+ x_dp->dtd_list.num_dtds = uc_dp->dtd_list.num_dtds;
+ x_dp->dtd_list.dtd = uc_dp->dtd_list.dtd;
+ x_dp->present_params |= IGD_PARAM_DTD_LIST;
+ }
+ }
+
+ if ((x_dp->port_number > 0) && (x_dp->attr_list.num_attrs == 0)) {
+ /* X didn't have any ATTRs for this port. Look up the corresponding
+ * display params from "user_config.c"
+ */
+ for (j = 0 ; j < IGD_MAX_PORTS ; j++) {
+ uc_dp = &uc_params->display_params[j];
+ if (uc_dp->port_number == x_dp->port_number) {
+ break;
+ }
+ }
+ if ((x_dp->port_number == uc_dp->port_number) ||
+ (uc_dp->attr_list.num_attrs > 0)) {
+ /* Have X's ATTR list point to "user_config.c"'s attr list */
+ x_dp->attr_list.num_attrs = uc_dp->attr_list.num_attrs;
+ x_dp->attr_list.attr = uc_dp->attr_list.attr;
+ x_dp->present_params |= IGD_PARAM_ATTR_LIST;
+ }
+ }
+ }
+#ifdef DEBUG_BUILD_TYPE
+ if(emgd_debug && emgd_debug->MODULE_NAME)
+ emgd_print_params(x_params);
+#endif
+
+
+ if (need_to_startup_hal) {
+ /* emgd_driver_load() deferred driver initialization and configuration.
+ * Therefore, do it now.
+ *
+ * Before doing so, ensure both ports are turned on, even if the user
+ * only requested one port.
+ *
+ * TODO/FIXME - This assumes only two ports; is that wise long-term?
+ */
+ if (x_params->port_order[1] == 0) {
+ if (x_params->port_order[0] == 2) {
+ x_params->port_order[1] = 4;
+ } else {
+ x_params->port_order[1] = 2;
+ }
+ }
+
+ EMGD_DEBUG("Starting the HAL");
+ err = emgd_startup_hal(dev, x_params);
+ if (err != 0) {
+ mutex_unlock(&dev->struct_mutex);
+ return err;
+ } else {
+ priv = dev->dev_private;
+ priv->hal_running = 1;
+ }
+ }
+ /* Now that we know the driver is initialized, we can do the following: */
+ context = (igd_context_t *) handle;
+ context->mod_dispatch.init_params = x_params;
+
+ if (config_drm.init) {
+ if (config_drm.kms) {
+ save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT)| IGD_REG_SAVE_TYPE_REG;
+ } else {
+ save_flags = (IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT &
+ ~IGD_REG_SAVE_RB) | IGD_REG_SAVE_TYPE_REG;
+ }
+ dispatch->driver_save(handle, save_flags);
+ EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
+ priv->saved_registers = CONSOLE_STATE_SAVED;
+ }
+
+ if (!need_to_startup_hal) {
+ /* emgd_driver_load() initialized and configured the driver.
+ * Therefore, we must now re-initialize and poke x_params values into
+ * various parts of the driver.
+ */
+ EMGD_DEBUG("Re-initializing the HAL with X driver values");
+
+ /* mode_init() (in "micro_mode.c") only sets the following value, which
+ * affects future alter_displays() calls. Note that no code seems to
+ * set x_params->display_color in the X driver.
+ */
+ mode_context->display_color = x_params->display_color;
+
+ /* mode_init() calls full_mode_init() (in "igd_mode.c"), which set the
+ * following values, of which, only seamless is used in the HAL.
+ *
+ * If seamless is TRUE, full_mode_init() will call the static procedure
+ * get_fw_info(), which will get firmware-programmed info before the
+ * driver starts re-programming it. get_fw_info will set seamless to
+ * FALSE if there's any errors. The get_fw_info() procedure can't be
+ * called here because it's static. It may also be too late to call it
+ * at this point (i.e. if the HAL has already touched anything, and
+ * that may have something to do with how many times the X server
+ * process starts).
+ */
+ mode_context->quickboot = x_params->quickboot;
+ mode_context->seamless = x_params->qb_seamless;
+ mode_context->video_input = x_params->qb_video_input;
+ mode_context->splash = x_params->qb_splash;
+ mode_context->first_alter = TRUE;
+
+ if (config_drm.init) {
+ for (i=0; i < IGD_MAX_PORTS; i++) {
+ mode_context->batch_blits[x_params->display_params[i].port_number - 1]
+ = x_params->display_params[i].flags & IGD_DISPLAY_BATCH_BLITS;
+ }
+ toggle_vblank_interrupts(TRUE);
+ }
+
+ /* In case the X server ran, exited, and is starting again, we may need
+ * to put the X server's state back:
+ */
+ if (priv->saved_registers == X_SERVER_STATE_SAVED) {
+ EMGD_DEBUG("Need to restore the X server's saved register state");
+
+ if (config_drm.init) {
+ save_flags = IGD_REG_SAVE_ALL & ~IGD_REG_SAVE_GTT;
+ }
+ else {
+ save_flags = IGD_REG_SAVE_ALL;
+ }
+ err = dispatch->driver_save_restore(handle, save_flags);
+ EMGD_DEBUG("State of saved registers is CONSOLE_STATE_SAVED");
+ priv->saved_registers = CONSOLE_STATE_SAVED;
+ }
+
+ if(!mode_context->seamless) {
+ /* NOTE: In order for some new values to be poked into the port
+ * drivers' hardware (e.g. the LVDS panel depth), the power must be
+ * turned off on those devices. This used to be done during the
+ * emgd_driver_lastclose() function, but that prevents the console from
+ * being seen after X quits.
+ */
+ while ((port = context->mod_dispatch.dsp_get_next_port(context,
+ port, 0)) != NULL) {
+ /* power off LVDS only */
+ if (port->pd_driver && (port->port_number == IGD_PORT_TYPE_LVDS) &&
+ !mode_context->seamless) {
+ EMGD_DEBUG("Turning off power for port %lu\n", port->port_number);
+ dispatch->power_display(context, port->port_number,
+ IGD_POWERSTATE_D3);
+ }
+ }
+
+ /* mode_init() calls dsp_init() (in "dsp.c"), which uses the
+ * display_flags, display_params & port_order params. In the case of
+ * display_params, each element of the array contains dtd_list and
+ * attr_list, both of which point to memory that must be separately
+ * copied to kernel-space. The display_flags, display_params &
+ * port_order params affect the initialization of the DSP module, and
+ * as such, it may not be easy to simply poke values here.
+ *
+ * Thus, it appears that the DSP module must somehow be re-initialized.
+ *
+ * Note: dsp_init() also calls full_dsp_init() and the device-specific
+ * init procedures, none of which uses any params.
+ */
+ EMGD_DEBUG("Calling dsp_shutdown()");
+ dsp_shutdown(handle);
+
+ EMGD_DEBUG("Calling dsp_init()");
+ dsp_init(handle);
+
+
+ /* Poke any new port attributes & DTDs into the port drivers: */
+ while ((port = context->mod_dispatch.dsp_get_next_port(context,
+ port, 0)) != NULL) {
+ if (port->pd_driver && !mode_context->seamless) {
+ EMGD_DEBUG("Insert new port attrs/DTDs for port %lu",
+ port->port_number);
+ pi_pd_init(port, 0, 0, FALSE);
+ }
+ }
+
+ /*
+ * Because dsp_init was called above, a lot of the configuration
+ * performed by the driver at initializat is now invalid.
+ *
+ * Setting the dc to 0 makes sure we don't try to use other
+ * data structures before alter_displays has been called again.
+ */
+ priv->dc = 0;
+ }
+
+
+ /* Set a flag so that emgd_alter_displays() will turn back on the port
+ * drivers' hardware:
+ */
+ if(!mode_context->seamless) {
+ priv->must_power_on_ports = 1;
+ }
+
+ /* OVERLAY_INIT() translates to the _overlay_init() procedure (in
+ * "micro_ovl.c"). It calls ovl_full_init() (in "igd_ovl.c"). If the
+ * IGD_DISPLAY_FB_BLEND_OVL bit in "display_flags" is set, it sets
+ * ovl_context->fb_blend_ovl to 1, which affects future atler_ovl()
+ * calls.
+ */
+ if (x_params->display_flags & IGD_DISPLAY_FB_BLEND_OVL) {
+ ovl_context->fb_blend_ovl = 1;
+ }
+ } /* if (!need_to_startup_hal) */
+
+/* NOTE -- Below is our original analysis of what values/modules need
+ * to be dealt with (above):
+ *
+ * - mode_init() (in "micro_mode.c") uses display_color.
+ *
+ * - Note: the value is stored in a global variable:
+ * mode_context->display_color. This value is used only once--in
+ * full_clear_fb() (igd_mode.c), which is only called by
+ * configure_display() (micro_mode.c), which is only called by
+ * igd_alter_displays() (micro_mode.c).
+ *
+ * [ ] Implemented proposal: set the value. Correct approach?
+ *
+ * - full_mode_init() (in "igd_mode.c", called by mode_init(); lives in
+ * "micro_mode.c", which is called by init_modules()) uses the quickboot &
+ * qb_* params. The values are stored in a global variable: mode_context->*.
+ * Here's what I learned in terms of what is used (same is true for IEGD
+ * source):
+ *
+ * - The mode_context->quickboot value is only set (here) and is never used.
+ *
+ * - mode_context->seamless (corresponding to params->qb_seamless) is
+ * used in full_mode_init() (igd_mode.c) to decide whether (if TRUE) to
+ * call get_fw_info(), which may set it to FALSE depending on whether
+ * there is firmware info that should affect it. It is also read by
+ * configure_display() (micro_mode.c), which is only called by
+ * igd_alter_displays() (micro_mode.c). It is also read & used to decide
+ * something by igd_alter_displays() (micro_mode.c).
+ *
+ * - mode_context->video_input (corresponding to params->qb_video_input) is
+ * only set (here) and is never used.
+ *
+ * - mode_context->splash (corresponding to params->qb_splash) is only set
+ * (here) and is never used.
+ *
+ * [ ] New Proposal: potentially set the values and do nothing else. Is this
+ * the correct approach?
+ *
+ * [-] Old Proposal: set the values, and if seamless is TRUE, call
+ * get_fw_info(). Can't actually do so, as get_fw_info() is a static
+ * procedure.
+ *
+ * - dsp_init() (in "dsp.c", called by mode_init(); lives in "micro_mode.c",
+ * which is called by init_modules()) uses the display_flags, display_params
+ * & port_order params. It also calls full_dsp_init() and the
+ * device-specific init procedures, neither of which uses any params. Within
+ * display_params, there are several params looked at: port_number,
+ * present_params, ddc_gpio, ddc_speed, ddc_dab, i2c_gpio, i2c_speed,
+ * i2c_dab, fp_info, dtd_list, and attr_list. Right now, none of these are
+ * set.
+ *
+ * - Notes: Here's what I learned in terms of what is used:
+ *
+ * - params->display_flags is stored in dsp_context->display_flags. The
+ * value is used by dsp_dc_init() (dsp.c, called by igd_query_dc() and
+ * mode_init()--called after dsp_init()) to determine if
+ * IGD_DISPLAY_DETECT is set (used frequently in that procedure). The
+ * value is used by igd_query_dc() (dsp.c, called by igd_query_dc() and
+ * mode_init()--called after dsp_init())--after calling dsp_dc_init()
+ * once, if there's only 1 DC, it uses this value to determine if
+ * IGD_DISPLAY_DETECT is set, and if so the bit is immediately turned off
+ * and dsp_dc_init() is called again.
+ *
+ * - params->port_order is used as a parameter to do_port_order() (in
+ * "dsp.c"), which is only called this once via dsp_init(). Based on
+ * this, it seems that we should try to figure out how to re-init this
+ * code. Correct approach?
+ *
+ * - params->display_params is iterated over ... OUCH! display_params IS A
+ * STRUCT OF TYPE igd_param_attr_list_t, AND SOME OF ITS MEMBERS HAVE
+ * POINTERS WITHIN THEM (i.e. HARDER TO GET ACROSS THE IOCTL BOUNDARY).
+ *
+ * Based on the above, it seems that the idea of
+ * re-initializing the DSP module seems like the correct approach. I'm
+ * not quite sure how to do that, but it seems like the right direction
+ * to both keep the HAL code unmodified, and do the user/kernel-space
+ * split.
+ *
+ * [X] Implemented proposal: copy all user-space memory to kernel-space,
+ * and later free any temporarily allocated memory.
+ * [ ] Proposal: re-initialize the DSP module. Correct approach?
+ *
+ * - OVERLAY_INIT() translates to _overlay_init() (in "micro_ovl.c") takes
+ * params as a parameter, which it passes to ovl_full_init() (in
+ * "igd_ovl.c"). If the IGD_DISPLAY_FB_BLEND_OVL bit in "display_flags" is
+ * set, it sets ovl_context->fb_blend_ovl to 1. This flag is used in the
+ * following procedures:
+ *
+ * - ovl_send_instr_plb() (in "emgd_drm/video/overlay/plb/ovl_plb.c") is
+ * called by alter_ovl_plb(), which is called through the ovl_dispatch_plb
+ * table (of type ovl_dispatch_t).
+ *
+ * - ovl2_send_instr_plb() (in "emgd_drm/video/overlay/plb/ovl2_plb.c") is
+ * called by alter_ovl2_plb(), which is called through the ovl_dispatch_plb
+ * table (of type ovl_dispatch_t).
+ *
+ * - ovl_send_instr_tnc() (in "emgd_drm/video/overlay/tnc/ovl_tnc.c") is
+ * called by alter_ovl_tnc(), which is called through the ovl_dispatch_tnc
+ * table (of type ovl_dispatch_t).
+ *
+ * [ ] Implemented proposal: If the IGD_DISPLAY_FB_BLEND_OVL bit in
+ * "display_flags" is set, set ovl_context->fb_blend_ovl to 1. Correct
+ * approach?
+ *
+ * - pi_pd_init() (in the file "emgd_drm/display/pi/cmd/pi.c") accesses
+ * params->display_params. It is called by pi_pd_register() ("pi.c"), which
+ * is called by both igd_pd_register() (in "igd_pi.c") and pd_register() (in
+ * "emgd_drm/display/pd/pd.c"). igd_pd_register() is called by
+ * load_port_drivers() (in "emgd_drv/emgd_dpdloader.c") which is no longer
+ * called (was called during PreInit()).
+ * pd_register() is called by lvds_init() and sdvo_init(), both of which are
+ * called by pi_init_all(), which is not being called.
+ *
+ * [ ] TODO - LEARN ABOUT HOW THE STATICALLY-LOADED PORT DRIVERS WILL GET
+ * THEIR params INFO, AND WHEN THEY WILL WANT IT (i.e. IN RELATION TO X
+ * DRIVER PreInit())
+ *
+ * None of the other modules use and/or need any params at this point:
+ *
+ * - REG_INIT translates to _reg_init() and uses preserve_reg. It's too late
+ * to undo what we chose at kernel init time.
+ * - gmm_init() ignores page_request and max_fb_size.
+ * - CMD_INIT() translates to 0 (i.e. Koheo doesn't use this module).
+ * - pi_init() (in "pi.c", called by mode_init(); lives in "micro_mode.c",
+ * which is called by init_modules()) uses no params.
+ * - APPCONTEXT_INIT() translates to appcontext_init() doesn't use any params
+ * - PWR_INIT() translates to _pwr_init() (in "igd_pwr.c") doesn't look a any
+ * params in context, nor does pwr_init_plb() (in "pwr_plb.c").
+ * - RESET_INIT() translates to _reset_init() IS MISSING. IS IT NEEDED???
+ * Just in case, I looked at the IEGD version (in "igd_reset.c"), which
+ * doesn't look at any params.
+ * - OS_INIT_INTERRUPT() doesn't translate into anything real (i.e. IT IS
+ * MISSING). IS IT NEEDED??? Just in case, I looked at the IEGD version (in
+ * "oal/xfree86/src/interrupt/interrupt.c"), and it is a no-op.
+ * - BLEND_INIT() translates to 0 (i.e. Koheo doesn't use this module).
+ * - INIT_2D() translates to 0 (i.e. Koheo doesn't use this module).
+ */
+
+
+ /* Call the HAL's igd_get_config_info() procedure: */
+ drm_data->rtn = igd_get_config_info(handle,
+ /* Note: Since a pointer is passed to drm_data->config_info, there's no
+ * need to copy anything back into drm_data, except for the return
+ * value.
+ */
+ &(drm_data->config_info));
+
+ /* Check for a bit depth we support */
+ pf_caps = drm_data->config_info.fb_caps;
+
+ while (pf_caps && pf_caps->pixel_format != 0) {
+ if (drm_data->bpp == IGD_PF_DEPTH(pf_caps->pixel_format)) {
+ EMGD_DEBUG("Found matching PF: %lx for depth %lx bpp.",
+ pf_caps->pixel_format, drm_data->bpp);
+ drm_data->config_info.pixel_format = pf_caps->pixel_format;
+ break;
+ }
+ pf_caps++;
+ }
+ if (!drm_data->config_info.pixel_format) {
+ EMGD_DEBUG("Given depth (%lx) is not supported.", drm_data->bpp);
+ }
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_driver_pre_init() */
+
+
+/*!
+ * IOCTL to support emgd_hal2drm_get_ports(), which replaces the X driver's
+ * usage of igd_get_param(...,IGD_PARAM_PORT_LIST,...)
+ */
+int emgd_driver_get_ports(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_driver_get_ports_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Call the HAL: */
+ drm_data->rtn = igd_get_param(handle, IGD_PARAM_PORT_LIST,
+ /* Note: Since a pointer is passed to drm_data->ports,
+ * there's no need to copy anything back into drm_data, except
+ * for the return value.
+ */
+ drm_data->ports);
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_driver_get_ports() */
+
+/*!
+ * IOCTL to support emgd_hal2drm_get_page_list(), which get's the list
+ * of page address that make up a memory allocation.
+ */
+int emgd_get_page_list(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_get_page_list_t *drm_data = arg;
+ unsigned long cnt;
+ unsigned long *list;
+ unsigned long *new_list;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+ dispatch->gmm_get_page_list(drm_data->offset, &list, &cnt);
+ if (cnt > drm_data->addr_count) {
+ /*
+ * The user didn't allocate enough space for the
+ * page list, this is an error.
+ */
+ drm_data->addr_count = cnt;
+ drm_data->rtn = -IGD_NO_MEM;
+ } else {
+ /* Copy the address list to the caller */
+ new_list = (unsigned long *)(arg + sizeof(emgd_drm_get_page_list_t));
+ for (i = 0; i < cnt; i++) {
+ new_list[i] = list[i];
+ }
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_driver_get_page_list() */
+
+/*!
+ * IOCTL to allow the X driver (in "egd_driver.c") to start the Imagination
+ * Technologies PVR services DRM/kernel module, which will start our 3rd-party
+ * display driver (3DD).
+ */
+int emgd_start_pvrsrv(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_start_pvrsrv_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+
+ EMGD_TRACE_ENTER;
+
+ /* Tell the 3DD the status of whether the X server is running: */
+ if (!priv->xserver_running && drm_data->xserver) {
+ priv->xserver_running = 1;
+ if (priv->reinit_3dd) {
+ priv->reinit_3dd(dev);
+ }
+ }
+
+ drm_data->rtn = 0;
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_start_pvrsrv() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's video_cmd_buf() procedure.
+ */
+int emgd_video_cmd_buf(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_video_cmd_buf_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = priv->context;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Call the HAL: */
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = process_video_decode_plb(context, drm_data->offset,
+ drm_data->mem_handle,
+ &(drm_data->fence_id));
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = process_video_encode_tnc(context, drm_data->offset,
+ drm_data->mem_handle,
+ &(drm_data->fence_id));
+ break;
+ default:
+ break;
+ }
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_video_cmd_buf() */
+
+
+/*!
+ * IOCTL to bridge the IAL to the HAL's get_device_info() procedure.
+ */
+int emgd_get_device_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_device_info_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = priv->context;
+
+ EMGD_TRACE_ENTER;
+
+ drm_data->display_memory_offset = context->device_context.fb_adr;
+ drm_data->display_memory_size = context->device_context.mem_size;
+ drm_data->device_id = context->device_context.did;
+ drm_data->revision_id = context->device_context.rid;
+ drm_data->bridge_id = context->device_context.bid;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_get_device_info() */
+
+
+int emgd_init_video(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_init_video_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = priv->context;
+
+ EMGD_TRACE_ENTER;
+
+ switch (drm_data->cmd) {
+ case CMD_VIDEO_STATE :
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_query_plb(context, &drm_data->status);
+ break;
+ default:
+ drm_data->rtn = 1;
+ break;
+ }
+ break;
+ case CMD_VIDEO_INITIALIZE :
+ /* Call the HAL: */
+ switch (drm_data->engine) {
+ case PSB_ENGINE_COMPOSITOR_MMU:
+ drm_data->rtn = msvdx_init_compositor_mmu(drm_data->base0);
+ break;
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_init_plb(drm_data->base0, drm_data->base1,
+ drm_data->mem_handle_fw,0);
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = topaz_init_tnc(drm_data->wb_offset,
+ drm_data->mem_handle_writeback,
+ drm_data->mem_handle_enc_fw);
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDEO_UNINITIALIZE :
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_uninit_plb(context);
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDEO_CLOSE_CONTEXT :
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_close_context(context, drm_data->context_id);
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDEO_CREATE_CONTEXT:
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_create_context(context, (void *) file_priv, drm_data->context_id);
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDEO_SHUTDOWN:
+ switch (drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_shutdown_plb(context);
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = topaz_shutdown_tnc(context);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_init_video() */
+
+int emgd_video_get_info(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_video_get_info_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = priv->context;
+
+ EMGD_TRACE_ENTER;
+
+ switch(drm_data->cmd) {
+ case CMD_VIDEO_GET_FENCE_ID:
+ switch(drm_data->engine){
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = msvdx_get_fence_id(context, &(drm_data->fence_id));
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = topaz_get_fence_id(context, &(drm_data->fence_id));
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDOE_GET_FRAME_SKIP:
+ switch(drm_data->engine){
+ case PSB_ENGINE_VIDEO:
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = topaz_get_frame_skip(context, &(drm_data->frame_skip));
+ break;
+ default:
+ break;
+ }
+ break;
+ case CMD_VIDEO_GET_MSVDX_STATUS:
+ if ((&context->mod_dispatch) && context->mod_dispatch.msvdx_status)
+ drm_data->rtn = context->mod_dispatch.msvdx_status(context, &drm_data->queue_status, &drm_data->mtx_msg_status);
+ break;
+ default:
+ break;
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+int emgd_video_flush_tlb(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_video_flush_tlb_t *drm_data = arg;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ igd_context_t *context = priv->context;
+
+ EMGD_TRACE_ENTER;
+
+ switch(drm_data->engine) {
+ case PSB_ENGINE_VIDEO:
+ drm_data->rtn = 0;
+ break;
+ case TNC_ENGINE_ENCODE:
+ drm_data->rtn = topaz_flush_tnc(context);
+ break;
+ default:
+ break;
+ }
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int emgd_preinit_mmu(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_preinit_mmu_t *drm_data = arg;
+
+ EMGD_TRACE_ENTER;
+
+ drm_data->rtn = msvdx_preinit_mmu(drm_data->memcontext);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int emgd_get_golden_htotal(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv){
+
+
+ emgd_drm_get_golden_htotal_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+ igd_display_context_t *display;
+ pd_timing_t igd_mode_table_in[2];
+ pd_timing_t igd_mode_table_out;
+
+ igd_display_info_t *out_mode = (igd_display_info_t *) drm_data->out_mode;
+ igd_display_info_t *in_mode = (igd_display_info_t *) drm_data->in_mode;
+
+
+ EMGD_DEBUG("emgd_get_golden_htotal : Entry");
+
+ /* parameters sanity check */
+ if (out_mode == NULL) {
+ EMGD_ERROR("emgd_get_golden_htotal : NO Output Buffer");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (in_mode == NULL) {
+ EMGD_ERROR("emgD_get_golden_htotal : NO Input Buffer");
+ return -IGD_ERROR_INVAL;
+
+ }
+
+ /* Zero out the data structures so that we can check for error later */
+ memset(igd_mode_table_in, 0, 2 * sizeof(pd_timing_t));
+ memset(&igd_mode_table_out, 0, sizeof(pd_timing_t));
+
+ /* To prevent a kernel OOPS, ensure the following value is non-NULL: */
+ display = context->mod_dispatch.dsp_display_list[2];
+ if ((display == NULL) || (PORT(display, 2) == NULL)) {
+ EMGD_ERROR_EXIT("emgd_get_golden_htotal() given an invalid port "
+ "number (%d)\n", 2);
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* convert the data from escape structure to pd_timing */
+ igd_mode_table_in[0].width = in_mode->width;
+ igd_mode_table_in[0].height = in_mode->height;
+ igd_mode_table_in[0].refresh = in_mode->refresh;
+
+ /* Set the end of list */
+ igd_mode_table_in[1].width = PD_TIMING_LIST_END;
+ igd_mode_table_in[1].extn_ptr = NULL;
+
+ /************************************************************/
+ /* call dispatch function that will generate the golden htotal
+ * for all the modes. The pd_timing_t has the same structure as
+ * igd_display_t so we can typecast without issue.
+ */
+ /************************************************************/
+ context->mod_dispatch.get_dd_timing(display,
+ (pd_timing_t*)&igd_mode_table_in);
+
+ /************************************************************/
+ /* Send back the modified mode list that contains the delta */
+ /************************************************************/
+
+ memcpy (out_mode, in_mode, sizeof(igd_display_info_t));
+ out_mode->reserved_dd = igd_mode_table_in[0].reserved_dd;
+
+ out_mode->hblank_end = igd_mode_table_in[0].hblank_end;
+ out_mode->vblank_end = igd_mode_table_in[0].vblank_end;
+
+
+ return 0;
+}
+
+int emgd_control_plane_format(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_control_plane_format_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+ igd_plane_t *plane_override;
+
+ EMGD_DEBUG("emgd_control_plane_format : Entry");
+
+ if (drm_data->use_plane == FALSE)
+ {
+ /* Do some error checking first */
+ if((drm_data->enable != 0 && drm_data->enable != 1) ||
+ (drm_data->primary_secondary_dsp == NULL)) {
+ EMGD_ERROR("emgd_control_plane_format: Invalid parameters");
+ return -IGD_ERROR_INVAL;
+ }
+
+ plane_override = ((igd_plane_t *)(PLANE(drm_data->primary_secondary_dsp)));
+ } else {
+ /* Do some error checking first */
+ if((drm_data->enable != 0 && drm_data->enable != 1) ||
+ (drm_data->display_plane != 0 && drm_data->display_plane != 1)) {
+ EMGD_ERROR("emgd_control_plane_format: Invalid parameters");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Set plane_override to NULL */
+ plane_override = NULL;
+ }
+
+ /* Call the DSP modules function if no errors */
+ context->mod_dispatch.dsp_control_plane_format(drm_data->enable,
+ drm_data->display_plane, plane_override);
+
+ return 0;
+}
+
+int emgd_set_overlay_display(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_set_overlay_display_t *drm_data = arg;
+ igd_context_t *context = (igd_context_t *) handle;
+
+ EMGD_DEBUG("emgd_set_overlay_display : Entry");
+
+ /* Do some error checking first */
+ if((drm_data->ovl_display[OVL_PRIMARY] == 0) ||
+ (drm_data->ovl_display[OVL_SECONDARY] == 0)) {
+ /* Both Ovl displays need to have valid handle
+ * (i.e. Single mode is not supported) */
+ EMGD_ERROR("emgd_set_overlay_display: Invalid parameters");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Call the set_ovl_display if no errors */
+ context->dispatch.set_ovl_display(drm_data->ovl_display);
+
+ return 0;
+}
+
+int emgd_query_2d_caps_hwhint(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv){
+
+
+ emgd_drm_query_2d_caps_hwhint_t *drm_data;
+ unsigned long caps_val;
+ unsigned long *status;
+
+ EMGD_DEBUG("emgd_query_2d_caps_hwhint : Entry");
+
+ /* parameters sanity check */
+ if (arg == NULL) {
+ EMGD_ERROR("emgd_query_2d_caps_hwhint : invalid argument");
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ drm_data = arg;
+ caps_val = (unsigned long) drm_data->caps_val;
+ status = (unsigned long *) drm_data->status;
+
+ igd_query_2d_caps_hwhint(handle, caps_val, status);
+
+ return 0;
+}
+
+int emgd_unlock_planes(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ emgd_drm_unlock_planes_t *drm_data;
+ drm_data = arg;
+
+ /* do plane unlocking */
+ drm_data->rtn = dispatch->unlock_planes(drm_data->display_handle, drm_data->screen_num);
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
new file mode 100644
index 0000000..c1d13a2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
@@ -0,0 +1,186 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_mmap.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Memory mapping functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.gart
+
+#include <linux/mm.h>
+#include <drm_emgd_private.h>
+#include <emgd_drv.h>
+#include <emgd_drm.h>
+#include <memory.h>
+#include <memlist.h>
+#include <io.h>
+
+/*
+ * Bottom 256MB reserved for display
+ */
+#define DRM_PSB_FILE_PAGE_OFFSET (0x10000000UL >> PAGE_SHIFT)
+
+extern gmm_chunk_t *gmm_get_chunk(igd_context_t *context,
+ unsigned long vm_pgoff);
+extern int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+
+static int emgd_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+static void emgd_vm_open(struct vm_area_struct *vma);
+static void emgd_vm_close(struct vm_area_struct *vma);
+
+static struct vm_operations_struct emgd_vm_ops = {
+ .fault = emgd_vm_fault,
+ .open = emgd_vm_open,
+ .close = emgd_vm_close
+};
+
+/*
+ * Create a virtual address mapping for physical pages of memory.
+ *
+ * This needs to handle requrests for both the EMGD display driver
+ * and the IMG 2D/3D drivers.
+ *
+ * If the page offset falls below the 256MB limit for display,
+ * then map display memory. If above, route to the IMG handler.
+ */
+int emgd_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *file_priv;
+ drm_emgd_priv_t *emgd_priv;
+ gmm_chunk_t *chunk;
+ unsigned long offset;
+
+ /*
+ * re-direct offsets beyond the 256MB display range to PVRMMap
+ */
+ if (vma->vm_pgoff > DRM_PSB_FILE_PAGE_OFFSET) {
+ EMGD_DEBUG("emgd_mmap: Calling PVRMMap().");
+ return PVRMMap(filp, vma);
+ }
+
+ file_priv = (struct drm_file *) filp->private_data;
+ emgd_priv = (drm_emgd_priv_t *)file_priv->minor->dev->dev_private;
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ /*
+ * Look up the buffer in the gmm chunk list based on offset
+ * and size.
+ */
+ /* chunk = emgd_priv->context->dispatch->gmm_get_chunk(vma->vm_pgoff);*/
+ chunk = gmm_get_chunk(emgd_priv->context, offset);
+ if (chunk == NULL) {
+ printk(KERN_ERR "emgd_mmap: Failed to find memory at 0x%lx.", offset);
+ }
+
+ /*
+ * Fill in the vma
+ */
+ vma->vm_ops = &emgd_vm_ops;
+ vma->vm_private_data = chunk;
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+ pgprot_val(vma->vm_page_prot) =
+ pgprot_val(vma->vm_page_prot) | _PAGE_CACHE_UC_MINUS;
+
+ return 0;
+}
+
+
+static int emgd_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ unsigned long offset;
+ unsigned long pg_offset;
+ gmm_chunk_t *chunk;
+ struct page *page;
+
+ offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+ pg_offset = offset >> PAGE_SHIFT;
+
+ chunk = (gmm_chunk_t *)vma->vm_private_data;
+
+ if (chunk == NULL) {
+ printk(KERN_ERR "emgd_vm_fault: Chunk is NULL.\n");
+ vmf->page = NULL;
+ return VM_FAULT_SIGBUS;
+ }
+
+ if (pg_offset > chunk->gtt_mem->page_count) {
+ printk(KERN_ERR "emgd_vm_fault: page offet (%lu) > page count (%d)\n",
+ pg_offset, chunk->gtt_mem->page_count);
+ return VM_FAULT_SIGBUS;
+ }
+
+ page = chunk->gtt_mem->pages[pg_offset];
+ get_page(page);
+ vmf->page = page;
+
+ return 0;
+}
+
+/*
+ * Increase the refrence count on the memory object
+ */
+static void emgd_vm_open(struct vm_area_struct *vma)
+{
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->minor->dev;
+
+
+ /*
+ * Does the DRM really need to keep track of the count if we're managing
+ * everything?
+ */
+ atomic_inc(&dev->vma_count);
+
+ /*
+ * DRM code maintains a list of vma's and when open is
+ * called, the vma is added to the list.
+ */
+
+}
+
+/*
+ * Decrease the reference count on the memory object and
+ * remove the refrence to the memory object.
+ */
+static void emgd_vm_close(struct vm_area_struct *vma)
+{
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->minor->dev;
+
+ /*
+ * Does the DRM really need to keep track of the count if we're managing
+ * everything?
+ */
+ atomic_dec(&dev->vma_count);
+
+ /*
+ * DRM code maintains a list of vma's and when close is
+ * called, the vma is removed to the list.
+ */
+
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
new file mode 100644
index 0000000..6ba4567
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
@@ -0,0 +1,1365 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_test_pvrsrv.c
+ * $Revision: 1.23 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file implements an ioctl devoted to the "ult/drmtest_surface.c" test.
+ * It tests the 3rd-Party Display Driver (and as such, it tests some of the
+ * PVR services) within kernel-space.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.oal
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "drm_emgd_private.h"
+#include "emgd_drm.h"
+#include "emgd_drv.h"
+#include "memory.h"
+
+#include "module_init.h"
+#include "mode_dispatch.h"
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+#include "msvdx.h"
+
+#include "memmap.h"
+#include "sched.h"
+
+#include "services.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+#include "syscommon.h"
+#include "pvr_drm.h"
+/* Pull in whether HAL & 3rd-party display driver (3DD) should use interrupts */
+#include "emgd_shared.h"
+
+
+
+/* Note: The following "TEST_ERROR" macro is only for this function. It prints
+ * the message to the kernel log, and it formats and inserts the same message
+ * into the drm_data->rtn_msg, so that the user-space code can print it.
+ */
+#define TEST_ERROR(format, arg...) \
+ printk(KERN_ERR format, ##arg);\
+ snprintf(drm_data->rtn_msg, 1024, format, ##arg);
+
+
+#define NUM_FRONT_BUFFERS 1
+#define NUM_BACK_BUFFERS 2
+#define NUM_BUFFERS (NUM_FRONT_BUFFERS + NUM_BACK_BUFFERS)
+
+
+#define DEVICE1 0
+#define DEVICE2 1
+
+
+/* Common colors: */
+#define BLACK 0xff000000
+#define WHITE 0xffffffff
+#define RED 0xffff0000
+#define GREEN 0xff00ff00
+#define BLUE 0xff0000ff
+#define CYAN 0xff00ffff
+#define YELLOW 0xffffff00
+#define MAGENTA 0xffff00ff
+
+
+/*
+ * Note: Am using the following global variables as a sort-of "poor man's OO"
+ * class members:
+ */
+static emgd_drm_test_pvrsrv_t *drm_data;
+static drm_emgd_priv_t *priv;
+
+static PVRSRV_PER_PROCESS_DATA *pp_data = NULL;
+static void *sgx_cookie = NULL;
+
+static void *dev_mem_context = NULL;
+static unsigned long heap_count = 0;
+static IMG_BOOL mem_created, dummy, mem_destroyed;
+
+static unsigned long dev_ids[2] = {0, 0};
+static void *dev_handle[2] = {NULL, NULL};
+static DISPLAY_INFO display_info;
+static DISPLAY_FORMAT *pf = NULL, *pixel_formats = NULL;
+static unsigned long num_dims = 0;
+static DISPLAY_DIMS *dim = NULL, *dimensions = NULL;
+
+static void *sys_buffer = NULL;
+static PVRSRV_KERNEL_MEM_INFO *sysbuf_mem_info = NULL;
+static void *sysbuf_map_info = NULL;
+
+#if 0
+static unsigned long fb_offset = 0;
+#endif
+static unsigned long mapped_fb_addr = 0;
+
+static DISPLAY_SURF_ATTRIBUTES dst_surf_attrib;
+static DISPLAY_SURF_ATTRIBUTES src_surf_attrib;
+static void *swap_chain = NULL;
+static unsigned long swap_chain_id = 0;
+
+static void *buffers[NUM_BUFFERS] = {NULL, NULL, NULL};
+static PVRSRV_KERNEL_MEM_INFO *buffers_mem_info[NUM_BUFFERS] = {NULL, NULL, NULL};
+static void *buffers_map_info[NUM_BUFFERS] = {NULL, NULL, NULL};
+
+
+
+
+
+/*!
+ * Initialize PVR services (including the 3DD), and get general info:
+ */
+static void init_pvrsrv(void)
+{
+ int i;
+ unsigned long num = 10;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (!drm_data->rtn) {
+ /* This is similar to PVRSRVConnect(): */
+ EMGD_DEBUG("Calling PVRSRVPerProcessDataConnect()");
+ err = PVRSRVPerProcessDataConnect(/*Use a dummy PID*/ 200);
+ EMGD_DEBUG("Calling PVRSRVPerProcessData()");
+ pp_data = PVRSRVPerProcessData(/*Use a dummy PID*/ 200);
+ EMGD_DEBUG(" TEST: pp_data = 0x%p", pp_data);
+ if ((err != PVRSRV_OK) || (NULL == pp_data)) {
+ TEST_ERROR("[EMGD] can not find per-process data\n");
+ drm_data->rtn = -1;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Enumerate the devices and acquire the SGX device: */
+ PVRSRV_DEVICE_IDENTIFIER dev_id_list[10];
+
+ EMGD_DEBUG("Calling PVRSRVEnumerateDevicesKM()");
+ err = PVRSRVEnumerateDevicesKM(&num, dev_id_list);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumerateDevicesKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG(" PVRSRVEnumerateDevicesKM() found %ld devices", num);
+ for (i = 0 ; i < num ; i++) {
+ PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i;
+ unsigned long cookie = 0;
+ EMGD_DEBUG(" Device %d has type %d, class %d & index %ld", i,
+ id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex);
+ if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) {
+ /* Call PVRSRVAcquireDeviceDataKM(): */
+ EMGD_DEBUG("Calling PVRSRVAcquireDeviceDataKM()");
+ err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
+ PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVAcquireDeviceDataKM() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ break;
+ }
+ if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
+ EMGD_DEBUG(" Found cookie = 0x%lx", cookie);
+ /* Save this away for later: */
+ sgx_cookie = (void *) cookie;
+ }
+ }
+ }
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Enumerate the display class devices to be able to find the 3DD: */
+ EMGD_DEBUG("Calling PVRSRVEnumerateDCKM()");
+EMGD_DEBUG("dev_ids=0x%p", dev_ids);
+ err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY,
+ &num, dev_ids);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ /* Find the 3DD: */
+ EMGD_DEBUG(" PVRSRVEnumerateDCKM() found %ld devices", num);
+ for (i = 0 ; i < num ; i++) {
+ EMGD_DEBUG(" device %d has ID %ld", i, dev_ids[i]);
+ }
+ if (0 == dev_ids[0]) {
+ TEST_ERROR("[EMGD] Did not find 3rd-party display driver ID\n");
+ drm_data->rtn = -1;
+ }
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Call PVRSRVCreateDeviceMemContextKM(): */
+ PVRSRV_HEAP_INFO heap_info[PVRSRV_MAX_CLIENT_HEAPS];
+
+ EMGD_DEBUG("Calling PVRSRVCreateDeviceMemContextKM()");
+ err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, pp_data,
+ &dev_mem_context, &heap_count, heap_info, &mem_created, &dummy);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVCreateDeviceMemContextKM() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* init_pvrsrv() */
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+static void deinit_pvrsrv(void)
+{
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (NULL != dev_mem_context) {
+ EMGD_DEBUG("Calling PVRSRVDestroyDeviceMemContextKM()");
+ err = PVRSRVDestroyDeviceMemContextKM(sgx_cookie, dev_mem_context,
+ &mem_destroyed);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVDestroyDeviceMemContext() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ }
+
+ if (NULL != pp_data) {
+ EMGD_DEBUG("Calling PVRSRVPerProcessDataDisconnect()");
+ PVRSRVPerProcessDataDisconnect(/*Use a dummy PID*/ 200);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* deinit_pvrsrv() */
+
+
+
+
+
+/*!
+ * Initialize PVR services (including the 3DD), and get general info:
+ */
+static void open_device(int which_device)
+{
+ int i;
+ unsigned long num = 10;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (!drm_data->rtn) {
+ /* Finally, open a connection to the 3DD: */
+ EMGD_DEBUG("Calling PVRSRVOpenDCDeviceKM()");
+ err = PVRSRVOpenDCDeviceKM(pp_data, dev_ids[which_device], sgx_cookie,
+ &dev_handle[which_device]);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVOpenDCDeviceKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ if (NULL == dev_handle[which_device]) {
+ TEST_ERROR("[EMGD] PVRSRVOpenDCDeviceKM() returned NULL handle\n");
+ drm_data->rtn = -1;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Get information about the display: */
+ EMGD_DEBUG("Calling PVRSRVGetDCInfoKM()");
+ err = PVRSRVGetDCInfoKM(dev_handle[which_device], &display_info);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVGetDCInfoKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG("PVRSRVGetDCInfoKM() returned the following info:");
+ EMGD_DEBUG(" name = \"%s\"", display_info.szDisplayName);
+ EMGD_DEBUG(" MaxSwapChains = %lu", display_info.ui32MaxSwapChains);
+ EMGD_DEBUG(" MaxSwapChainBuffers = %lu",
+ display_info.ui32MaxSwapChainBuffers);
+ EMGD_DEBUG(" MinSwapInterval = %lu",
+ display_info.ui32MinSwapInterval);
+ EMGD_DEBUG(" MaxSwapInterval = %lu",
+ display_info.ui32MaxSwapInterval);
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Get the the number of pixel formats: */
+ EMGD_DEBUG("Calling PVRSRVEnumDCFormatsKM()");
+ err = PVRSRVEnumDCFormatsKM(dev_handle[which_device], &num, NULL);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() returned %d\n",err);
+ drm_data->rtn = -1;
+ }
+ if (0 == num) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() says that there "
+ "are %lu pixel formats\n", num);
+ drm_data->rtn = -1;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Get the pixel formats: */
+ EMGD_DEBUG("Allocating space for %lu pixel formats", num);
+ pixel_formats = OS_ALLOC(sizeof(DISPLAY_FORMAT) * num);
+ EMGD_DEBUG("Calling PVRSRVEnumDCFormatsKM()");
+ err = PVRSRVEnumDCFormatsKM(dev_handle[which_device], &num,
+ pixel_formats);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ pf = pixel_formats;
+ for (i = 0 ; i < num ; i++) {
+ EMGD_DEBUG(" pixel format %d is %d", i, pf->pixelformat);
+ pf++;
+ }
+ /* Save the first pixel format (the one being used): */
+ pf = pixel_formats;
+ }
+ }
+
+
+ if (!drm_data->rtn) {
+ /* Get the number of display dimensions: */
+ EMGD_DEBUG("Calling PVRSRVEnumDCDimsKM()");
+ err = PVRSRVEnumDCDimsKM(dev_handle[which_device], pf, &num_dims, NULL);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ if (0 == num_dims) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() says that there "
+ "are %lu dimensions\n", num_dims);
+ drm_data->rtn = -1;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Get the display dimensions: */
+ EMGD_DEBUG("Allocating space for %lu dimensions", num_dims);
+ dimensions = OS_ALLOC(sizeof(DISPLAY_DIMS) * num_dims);
+ EMGD_DEBUG("Calling PVRSRVEnumDCDimsKM()");
+ err = PVRSRVEnumDCDimsKM(dev_handle[which_device], pf, &num_dims,
+ dimensions);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ dim = dimensions;
+ for (i = 0 ; i < num_dims ; i++) {
+ EMGD_DEBUG(" dimension %d is width = %lu, height = %lu, "
+ "stride = %lu", i, dim->ui32Width, dim->ui32Height,
+ dim->ui32ByteStride);
+ dim++;
+ }
+ /* Save the first dimension (the one being used): */
+ dim = dimensions;
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* open_device() */
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+static void close_device(int which_device)
+{
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (NULL != sysbuf_mem_info) {
+ EMGD_DEBUG("Calling PVRSRVUnmapDeviceClassMemoryKM()");
+ err = PVRSRVUnmapDeviceClassMemoryKM(sysbuf_mem_info);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVUnmapDeviceClassMemoryKM() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ }
+ if (NULL != dimensions) {
+ OS_FREE(dimensions);
+ }
+ if (NULL != pixel_formats) {
+ OS_FREE(pixel_formats);
+ }
+ if (NULL != dev_handle[which_device]) {
+ EMGD_DEBUG("Calling PVRSRVCloseDCDeviceKM()");
+ err = PVRSRVCloseDCDeviceKM(dev_handle[which_device], dummy);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVCloseDCDeviceKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ }
+
+ if (NULL != dev_mem_context) {
+ EMGD_DEBUG("Calling PVRSRVDestroyDeviceMemContextKM()");
+ err = PVRSRVDestroyDeviceMemContextKM(sgx_cookie, dev_mem_context,
+ &mem_destroyed);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVDestroyDeviceMemContext() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ }
+ }
+
+ if (NULL != pp_data) {
+ EMGD_DEBUG("Calling PVRSRVPerProcessDataDisconnect()");
+ PVRSRVPerProcessDataDisconnect(/*Use a dummy PID*/ 200);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* close_device() */
+
+
+
+
+/*!
+ * Maps the "system buffer" and paints it a solid color.
+ */
+static void map_and_paint_fb(int which_device, unsigned long color)
+{
+ int i;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Get a handle to the primary surface (a.k.a. "system buffer"): */
+ EMGD_DEBUG("Calling PVRSRVGetDCSystemBufferKM()");
+ err = PVRSRVGetDCSystemBufferKM(dev_handle[which_device], &sys_buffer);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVGetDCSystemBufferKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else if (NULL == sys_buffer) {
+ TEST_ERROR("[EMGD] PVRSRVGetDCSystemBufferKM() returned a "
+ "NULL handle to the system buffer\n");
+ drm_data->rtn = -1;
+ }
+
+ if (!drm_data->rtn) {
+ /* Map the memory of the "system buffer": */
+ EMGD_DEBUG("Calling PVRSRVMapDeviceClassMemoryKM()");
+ err = PVRSRVMapDeviceClassMemoryKM(pp_data, dev_mem_context,
+ sys_buffer, &sysbuf_mem_info, &sysbuf_map_info);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ } else if (NULL == sysbuf_mem_info) {
+ TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() returned a "
+ "NULL pointer to the system buffer's PVRSRV_KERNEL_MEM_INFO\n");
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG(" pvLinAddrKM = 0x%p", sysbuf_mem_info->pvLinAddrKM);
+ EMGD_DEBUG(" sDevVAddr = 0x%lx",sysbuf_mem_info->sDevVAddr.uiAddr);
+ EMGD_DEBUG(" ui32Flags = 0x%lx", sysbuf_mem_info->ui32Flags);
+ EMGD_DEBUG(" ui32AllocSize = %lu = 0x%lx",
+ sysbuf_mem_info->ui32AllocSize, sysbuf_mem_info->ui32AllocSize);
+ EMGD_DEBUG(" sMemBlk.sDevVirtAddr = %lu = 0x%lx",
+ sysbuf_mem_info->sMemBlk.sDevVirtAddr.uiAddr,
+ sysbuf_mem_info->sMemBlk.sDevVirtAddr.uiAddr);
+ EMGD_DEBUG(" sMemBlk.psIntSysPAddr = 0x%p",
+ sysbuf_mem_info->sMemBlk.psIntSysPAddr);
+ EMGD_DEBUG(" pvSysBackupBuffer = 0x%p",
+ sysbuf_mem_info->pvSysBackupBuffer);
+ EMGD_DEBUG(" ui32RefCount = %lu", sysbuf_mem_info->ui32RefCount);
+ EMGD_DEBUG(" bPendingFree = 0x%d", sysbuf_mem_info->bPendingFree);
+ EMGD_DEBUG(" psKernelSyncInfo = 0x%p",
+ sysbuf_mem_info->psKernelSyncInfo);
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Draw the "system buffer" the desired color: */
+ mapped_fb_addr = (unsigned long) (sysbuf_mem_info->pvLinAddrKM);
+ if (0 == mapped_fb_addr) {
+ TEST_ERROR("[EMGD] Failed to map the framebuffer\n");
+ drm_data->rtn = -1;
+ } else {
+ unsigned long *fb = (unsigned long *) (mapped_fb_addr);
+ unsigned int pixels = sysbuf_mem_info->ui32AllocSize / 4;
+ EMGD_DEBUG(" Mapped %luMB @ virtual addr= 0x%lx",
+ sysbuf_mem_info->ui32AllocSize/(1024*1024), mapped_fb_addr);
+ EMGD_DEBUG(" About to write to addr = 0x%p", fb);
+ EMGD_DEBUG(" About to write %d (0x%x) pixels",
+ pixels, pixels);
+ for (i = 0 ; i < pixels ; i++) {
+#if 0
+ if (0 == (i % 1024)) {
+ printk("row %3d: fb=0x%p\n", (i / 1024), fb);
+ }
+#endif
+ *fb++ = color;
+ }
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* map_and_paint_fb() */
+
+
+
+
+/*!
+ * Creates a swap chain, maps the buffers, and paints each a solid color.
+ */
+static void create_swap_chain(int which_device, int which_dimension,
+ unsigned long fb_color,
+ unsigned long bb1_color,
+ unsigned long bb2_color)
+{
+ int i, j;
+ unsigned long num = 10;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ /**************************************************************************
+ *
+ * Create a swap chain, draw green to one back buffer and red to the
+ * other; and then flip between the frame buffer and the 2 back buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ /* Create a swap chain: */
+ dst_surf_attrib.pixelformat = pf->pixelformat;
+ dst_surf_attrib.sDims = dimensions[which_dimension];
+ src_surf_attrib.pixelformat = pf->pixelformat;
+ src_surf_attrib.sDims = dimensions[which_dimension];
+ EMGD_DEBUG("Calling PVRSRVCreateDCSwapChainKM()");
+ err = PVRSRVCreateDCSwapChainKM(pp_data, dev_handle[which_device], 0,
+ &dst_surf_attrib, &src_surf_attrib, NUM_BUFFERS, 0, &swap_chain,
+ &swap_chain_id);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVCreateDCSwapChainKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG("PVRSRVCreateDCSwapChainKM() returned swap_chain=0x%p, "
+ "ID=%lu", swap_chain, swap_chain_id);
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Get the DC Buffers: */
+ num = NUM_BUFFERS;
+ EMGD_DEBUG("Calling PVRSRVGetDCBuffersKM()");
+ err = PVRSRVGetDCBuffersKM(dev_handle[which_device], swap_chain, &num,
+ buffers);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVGetDCBuffersKM() returned %d\n", err);
+ drm_data->rtn = -1;
+ } else if (NUM_BUFFERS != num) {
+ TEST_ERROR("[EMGD] PVRSRVGetDCBuffersKM() changed number of "
+ "buffers to %lu\n", num);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG("PVRSRVGetDCBuffersKM() returned buffers: 0x%p, 0x%p and "
+ "0x%p", buffers[0], buffers[1], buffers[2]);
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Map the memory of swap chain buffers: */
+ for (j = 0 ; j < NUM_BUFFERS ; j++) {
+ EMGD_DEBUG("Calling PVRSRVMapDeviceClassMemoryKM(buffers[%d])", j);
+ err = PVRSRVMapDeviceClassMemoryKM(pp_data, dev_mem_context,
+ buffers[j], &buffers_mem_info[j], &buffers_map_info[j]);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+ "returned %d\n", err);
+ drm_data->rtn = -1;
+ } else if (NULL == buffers_mem_info[j]) {
+ TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+ "returned a NULL pointer for buffer %d's "
+ "PVRSRV_KERNEL_MEM_INFO\n", j);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG(" pvLinAddrKM = 0x%p",
+ buffers_mem_info[j]->pvLinAddrKM);
+ EMGD_DEBUG(" sDevVAddr = 0x%lx",
+ buffers_mem_info[j]->sDevVAddr.uiAddr);
+ EMGD_DEBUG(" ui32Flags = 0x%lx",
+ buffers_mem_info[j]->ui32Flags);
+ EMGD_DEBUG(" ui32AllocSize = %lu = 0x%lx",
+ buffers_mem_info[j]->ui32AllocSize,
+ buffers_mem_info[j]->ui32AllocSize);
+ EMGD_DEBUG(" sMemBlk.sDevVirtAddr = %lu = 0x%lx",
+ buffers_mem_info[j]->sMemBlk.sDevVirtAddr.uiAddr,
+ buffers_mem_info[j]->sMemBlk.sDevVirtAddr.uiAddr);
+ EMGD_DEBUG(" sMemBlk.psIntSysPAddr = 0x%p",
+ buffers_mem_info[j]->sMemBlk.psIntSysPAddr);
+ EMGD_DEBUG(" pvSysBackupBuffer = 0x%p",
+ buffers_mem_info[j]->pvSysBackupBuffer);
+ EMGD_DEBUG(" ui32RefCount = %lu",
+ buffers_mem_info[j]->ui32RefCount);
+ EMGD_DEBUG(" bPendingFree = 0x%d",
+ buffers_mem_info[j]->bPendingFree);
+ EMGD_DEBUG(" psKernelSyncInfo = 0x%p",
+ buffers_mem_info[j]->psKernelSyncInfo);
+ }
+ }
+ }
+
+ if (!drm_data->rtn) {
+ /* Draw green in buffer 1 and red in buffer 2: */
+ for (j = 0 ; j < NUM_BUFFERS ; j++) {
+ unsigned long color;
+ unsigned long *fb =
+ (unsigned long *)buffers_mem_info[j]->pvLinAddrKM;
+ unsigned int pixels = buffers_mem_info[j]->ui32AllocSize / 4;
+
+ switch(j) {
+ case 0:
+ color = fb_color;
+ break;
+ case 1:
+ color = bb1_color;
+ break;
+ case 2:
+ color = bb2_color;
+ break;
+ default:
+ color = WHITE;
+ break;
+ }
+
+ EMGD_DEBUG(" Drawing the color 0x%lx to buffer %u", color, j);
+ EMGD_DEBUG(" About to write to addr = 0x%p", fb);
+ EMGD_DEBUG(" About to write %d (0x%x) pixels",
+ pixels, pixels);
+ for (i = 0 ; i < pixels ; i++) {
+#if 0
+ if (0 == (i % 1024)) {
+ printk("row %3d: fb=0x%p\n", (i / 1024), fb);
+ }
+#endif
+ *fb++ = color;
+ }
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* create_swap_chain() */
+
+
+
+
+/*!
+ * Flips each of the swap chain buffers, pausing a specified amount of time in
+ * between, so that the color can be seen.
+ */
+static void flip_swap_chain_buffers(int which_device, int which_dimension,
+ unsigned long sleep_time)
+{
+ int j;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (!drm_data->rtn) {
+ /* Display each of the buffers: */
+#ifndef TURN_ON_INTERRUPTS
+ igd_context_t *context = priv->context;
+ igd_display_h primary = priv->primary;
+ int ret;
+ unsigned long status;
+#endif /* TURN_ON_INTERRUPTS */
+ IMG_RECT clip_rect = {0, 0, dimensions[which_dimension].ui32Width,
+ dimensions[which_dimension].ui32Height};
+
+ /* Sleep for half a second, to give a chance to see the original system
+ * buffer:
+ */
+ OS_SLEEP(sleep_time);
+
+ /* Show each of the swap-chain buffers twice: */
+ for (j = 1 ; j < (NUM_BUFFERS+2) ; j++) {
+#ifndef TURN_ON_INTERRUPTS
+ int bailout;
+#endif /* TURN_ON_INTERRUPTS */
+ int buf = j % NUM_BUFFERS;
+
+ EMGD_DEBUG("Calling PVRSRVSwapToDCBufferKM(%d)", buf);
+ err = PVRSRVSwapToDCBufferKM(dev_handle[which_device], buffers[buf],
+#ifdef TURN_ON_INTERRUPTS
+ /* Note: it is interesting to test with swap interval values of
+ * 0, 63, and 130, which cause (respectively) no queueing,
+ * immediate flipping but queueing to count-down the swap
+ * interval, and the 3DD not getting some flips from PVR
+ * services before the swap chain is destoryed:
+ */
+ 1, NULL, 1, &clip_rect);
+#else /* TURN_ON_INTERRUPTS */
+ 0, NULL, 1, &clip_rect);
+#endif /* TURN_ON_INTERRUPTS */
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVSwapToDCBufferKM() returned %d\n",err);
+ drm_data->rtn = -1;
+ } else {
+ TEST_ERROR("[EMGD] PVRSRVSwapToDCBufferKM() swapped to "
+ "buffer %d\n", buf);
+ }
+
+#ifndef TURN_ON_INTERRUPTS
+ /* Test that we can query whether the flip occured: */
+ for (bailout = 18 ; bailout > 0 ; bailout--) {
+ ret = context->dispatch.query_event(primary,
+ IGD_EVENT_FLIP_PENDING, &status);
+ if (0 == status) {
+ break;
+ } else {
+ OS_SLEEP(1000);
+ }
+ }
+ if (0 == bailout) {
+ TEST_ERROR("Buffer flip didn't complete after 17msec\n");
+ drm_data->rtn = -1;
+ }
+#endif /* TURN_ON_INTERRUPTS */
+
+ /* Sleep for half a second, to give a chance to verify the flip
+ * occured:
+ */
+ OS_SLEEP(sleep_time);
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* flip_swap_chain_buffers() */
+
+
+
+
+/*!
+ * Unmaps each swap chain buffer, and then destroys the swap chain.
+ */
+static void destroy_swap_chain(void)
+{
+ int j;
+ PVRSRV_ERROR err;
+
+ EMGD_TRACE_ENTER;
+
+
+ for (j = 0 ; j < NUM_BUFFERS ; j++) {
+ if (NULL != buffers_mem_info[j]) {
+ EMGD_DEBUG("Calling PVRSRVUnmapDeviceClassMemoryKM(buffers[%d])", j);
+ err = PVRSRVUnmapDeviceClassMemoryKM(buffers_mem_info[j]);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVUnmapDeviceClassMemoryKM(%d) "
+ "returned %d\n", j, err);
+ drm_data->rtn = -1;
+ }
+ }
+ }
+ if (NULL != swap_chain) {
+ EMGD_DEBUG("Calling PVRSRVDestroyDCSwapChainKM()");
+ err = PVRSRVDestroyDCSwapChainKM(swap_chain);
+ if (err != PVRSRV_OK) {
+ TEST_ERROR("[EMGD] PVRSRVDestroyDCSwapChainKM() returned %d\n",err);
+ drm_data->rtn = -1;
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* destroy_swap_chain() */
+
+
+
+
+/*!
+ * Change the mode, via EMGD HAL functions.
+ */
+static void change_mode(struct drm_device *dev, int which_dim)
+{
+ EMGD_TRACE_ENTER;
+
+
+ /**************************************************************************
+ *
+ * Do a mode change (with a new background color of white), external to the
+ * 3DD (which will invalidate the swap chain) and see that the flips are no
+ * longer visible:
+ *
+ **************************************************************************/
+ if ((!drm_data->rtn) && (num_dims != 0)) {
+ igd_context_t *context = priv->context;
+ unsigned long emgd_pf = IGD_PF_ARGB32;
+ igd_display_info_t *mode_list = NULL;
+ igd_display_info_t *mode = NULL;
+ igd_display_info_t *desired_mode = NULL;
+ int mode_flags = IGD_QUERY_LIVE_MODES;
+ unsigned long byte_stride;
+ igd_framebuffer_info_t primary_fb_info;
+ igd_framebuffer_info_t secondary_fb_info;
+ igd_display_h primary;
+ igd_display_h secondary;
+ int err = 0;
+
+ EMGD_DEBUG("Will attempt to do a mode change...");
+ EMGD_DEBUG(" Target width=%lu, height=%lu",
+ dimensions[which_dim].ui32Width,
+ dimensions[which_dim].ui32Height);
+
+ EMGD_DEBUG(" Calling query_mode_list()");
+ err = context->dispatch.query_mode_list(context, priv->dc,
+ &mode_list, mode_flags);
+ if (err) {
+ TEST_ERROR("The query_mode_list() function returned %d.", err);
+ drm_data->rtn = -1;
+ }
+ if (!drm_data->rtn) {
+ EMGD_DEBUG(" Comparing mode list with target width and height");
+ mode = mode_list;
+ while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+ byte_stride = IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
+ EMGD_DEBUG(" Found a mode w/ width=%d, height=%d, refresh=%d;",
+ mode->width, mode->height, mode->refresh);
+ if ((mode->width == dimensions[which_dim].ui32Width) &&
+ (mode->height == dimensions[which_dim].ui32Height)) {
+ EMGD_DEBUG(" This mode is a match!");
+ desired_mode = mode;
+ break;
+ }
+ mode++;
+ }
+ if (NULL == desired_mode) {
+ TEST_ERROR(" No mode matching the desired width (%lu), "
+ "height (%lu) was found.", dimensions[which_dim].ui32Width,
+ dimensions[which_dim].ui32Height);
+ drm_data->rtn = -1;
+ } else {
+ /* Must set this in order to get the timings setup: */
+ desired_mode->flags |= IGD_DISPLAY_ENABLE;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Make the mode change by calling alter_displays(): */
+ primary_fb_info.width = desired_mode->width;
+ primary_fb_info.height = desired_mode->height;
+ primary_fb_info.pixel_format = emgd_pf;
+ primary_fb_info.flags = 0;
+ primary_fb_info.allocated = 0;
+ memcpy(&secondary_fb_info, &primary_fb_info,
+ sizeof(igd_framebuffer_info_t));
+
+ EMGD_DEBUG("Calling alter_displays()");
+ err = context->dispatch.alter_displays(context,
+ &primary, desired_mode, &primary_fb_info,
+ &secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
+ if (err) {
+ TEST_ERROR("The alter_displays() function returned %d.", err);
+ drm_data->rtn = -1;
+ }
+ }
+ if (!drm_data->rtn) {
+ /* Update the private copy, like emgd_alter_displays() would do: */
+ priv->primary = primary;
+ priv->secondary = secondary;
+ priv->primary_port_number = (priv->dc & 0xf0) >> 4;
+ priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
+
+ /* Re-initialize the display values: */
+ err = priv->reinit_3dd(dev);
+ if (err != 0) {
+ TEST_ERROR("The reinit_3dd() function returned %d.", err);
+ drm_data->rtn = -1;
+ } else {
+ EMGD_DEBUG("The MODE CHANGE was SUCCESSFUL");
+ }
+ }
+ }
+
+
+
+ EMGD_TRACE_EXIT;
+
+} /* change_mode() */
+
+
+
+
+
+
+
+
+
+/*!
+ * Test a single/clone DC with lots of buffer flipping and mode changes.
+ */
+static void emgd_test_pvrsrv_single_dc(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ /**************************************************************************
+ *
+ * Initialize PVR services (including the 3DD):
+ *
+ **************************************************************************/
+ init_pvrsrv();
+ if (!drm_data->rtn) {
+ open_device(DEVICE1);
+ }
+
+
+ /**************************************************************************
+ *
+ * Map the frame buffer and paint it blue:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ map_and_paint_fb(DEVICE1, BLUE);
+ }
+
+
+ /**************************************************************************
+ *
+ * Create a swap chain, draw red to one back buffer and green to the
+ * other; and then flip between the frame buffer and the 2 back buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+ }
+
+
+ /**************************************************************************
+ *
+ * Do a mode change, external to the 3DD (which will invalidate the swap
+ * chain) and see that the flips are no longer visible:
+ *
+ **************************************************************************/
+ if ((!drm_data->rtn) && (num_dims != 0)) {
+ change_mode(dev, 1);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+ }
+
+
+ /**************************************************************************
+ *
+ * Destroy the old swap chain, and create a new one that has the new
+ * dimensions; then draw cyan to the frame buffer, yellow to one back
+ * buffer and magenta to the other; and then flip between the frame buffer
+ * and the 2 back buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE1, 1, CYAN, YELLOW, MAGENTA);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 1, 500*1000);
+ }
+
+
+ /**************************************************************************
+ *
+ * Destroy the old swap chain, and create a new one that has different
+ * dimensions (the original dimensions), which will cause the 3DD to do a
+ * mode change; then draw blue to the frame buffer, red to one back
+ * buffer and green to the other; and then flip between the frame buffer
+ * and the 2 back buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+ }
+
+
+ /**************************************************************************
+ *
+ * Clean up to avoid an Oops and/or memory leak:
+ *
+ **************************************************************************/
+ destroy_swap_chain();
+
+ close_device(DEVICE1);
+ deinit_pvrsrv();
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_single_dc() */
+
+
+
+
+/*!
+ * Test a DIH/extended DC by opening/mapping the first device and drawing blue
+ * on it, and then by creating a swap chain, and flipping between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_open_dev1(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ /**************************************************************************
+ *
+ * Initialize PVR services (including the 3DD):
+ *
+ **************************************************************************/
+ init_pvrsrv();
+ if (!drm_data->rtn) {
+ open_device(DEVICE1);
+ }
+
+
+ /**************************************************************************
+ *
+ * Map the frame buffer and paint it blue:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ map_and_paint_fb(DEVICE1, BLUE);
+ }
+ OS_SLEEP(3*1000*1000);
+
+
+ /**************************************************************************
+ *
+ * Create a swap chain and flip between all buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 0, 1000*1000);
+ }
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_open_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having EMGD do a mode change on the
+ * first device.
+ */
+static void emgd_test_pvrsrv_dih_change1_dev1(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ if ((!drm_data->rtn) && (num_dims != 0)) {
+ change_mode(dev, 1);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change1_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having the 3DD (via PVRSRV) do a mode
+ * change, via the creation of a swap chain, on the first device, and then flip
+ * between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_change2_dev1(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+ }
+ OS_SLEEP(3*1000*1000);
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+ }
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change2_dev1() */
+
+
+
+
+/*!
+ * Close the first device and close PVR services to avoid an Oops and/or
+ * memory leak:
+ */
+static void emgd_test_pvrsrv_dih_close_dev1(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ close_device(DEVICE1);
+ deinit_pvrsrv();
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_close_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by opening/mapping the second device and
+ * drawing red on it.
+ */
+static void emgd_test_pvrsrv_dih_open_dev2(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ /**************************************************************************
+ *
+ * Initialize PVR services (including the 3DD):
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ init_pvrsrv();
+ }
+ if (!drm_data->rtn) {
+ open_device(DEVICE2);
+ }
+
+
+ /**************************************************************************
+ *
+ * Map the frame buffer and paint it cyan:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ map_and_paint_fb(DEVICE2, CYAN);
+ }
+ OS_SLEEP(3*1000*1000);
+
+
+ /**************************************************************************
+ *
+ * Create a swap chain and flip between all buffers:
+ *
+ **************************************************************************/
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE2, 0, CYAN, YELLOW, MAGENTA);
+ }
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE2, 0, 1000*1000);
+ }
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_open_dev2() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having EMGD do a mode change on the
+ * second device.
+ */
+static void emgd_test_pvrsrv_dih_change1_dev2(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ if ((!drm_data->rtn) && (num_dims != 0)) {
+ change_mode(dev, 1);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change1_dev2() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having the 3DD (via PVRSRV) do a mode
+ * change, via the creation of a swap chain, on the second device, and then flip
+ * between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_change2_dev2(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ if (!drm_data->rtn) {
+ create_swap_chain(DEVICE2, 0, CYAN, YELLOW, MAGENTA);
+ }
+ OS_SLEEP(3*1000*1000);
+ if (!drm_data->rtn) {
+ flip_swap_chain_buffers(DEVICE2, 0, 500*1000);
+ }
+ if (!drm_data->rtn) {
+ destroy_swap_chain();
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change2_dev2() */
+
+
+
+
+/*!
+ * Close the second device and close PVR services to avoid an Oops and/or
+ * memory leak:
+ */
+static void emgd_test_pvrsrv_dih_close_dev2(struct drm_device *dev)
+{
+ EMGD_TRACE_ENTER;
+
+
+ close_device(DEVICE2);
+ deinit_pvrsrv();
+
+
+ EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_close_dev2() */
+
+
+
+
+
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+int emgd_test_pvrsrv(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ EMGD_TRACE_ENTER;
+
+
+ drm_data = arg;
+ priv = dev->dev_private;
+ drm_data->rtn = 0;
+
+
+ /**************************************************************************
+ *
+ * Depending on the opcode, call the appropriate function that does the
+ * test:
+ *
+ **************************************************************************/
+ switch (drm_data->opcode) {
+ case SINGLE_DC_SWAPING:
+ emgd_test_pvrsrv_single_dc(dev);
+ break;
+ case DIH_DC_DRAW_OPEN_DEV1:
+ emgd_test_pvrsrv_dih_open_dev1(dev);
+ break;
+ case DIH_DC_MODE_CHANGE1_DEV1:
+ emgd_test_pvrsrv_dih_change1_dev1(dev);
+ break;
+ case DIH_DC_MODE_CHANGE2_DEV1:
+ emgd_test_pvrsrv_dih_change2_dev1(dev);
+ break;
+ case DIH_DC_CLOSE_DEV1:
+ emgd_test_pvrsrv_dih_close_dev1(dev);
+ break;
+ case DIH_DC_DRAW_OPEN_DEV2:
+ emgd_test_pvrsrv_dih_open_dev2(dev);
+ break;
+ case DIH_DC_MODE_CHANGE1_DEV2:
+ emgd_test_pvrsrv_dih_change1_dev2(dev);
+ break;
+ case DIH_DC_MODE_CHANGE2_DEV2:
+ emgd_test_pvrsrv_dih_change2_dev2(dev);
+ break;
+ case DIH_DC_CLOSE_DEV2:
+ emgd_test_pvrsrv_dih_close_dev2(dev);
+ break;
+ }
+
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+ return 0;
+} /* emgd_test_pvrsrv() */
diff --git a/drivers/gpu/drm/emgd/emgd/drm/image_data.h b/drivers/gpu/drm/emgd/emgd/drm/image_data.h
new file mode 100755
index 0000000..b48fc0c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/image_data.h
@@ -0,0 +1,33 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: bitmap_data.h
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#define DECODE_PNG
+static unsigned char image_data[] = {
+};
diff --git a/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
new file mode 100755
index 0000000..f429894
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
@@ -0,0 +1,2221 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: splash_screen.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the Intel Embedded Graphics EFI Driver Splash Screen implementation
+ * file. This code shows a splash screen with a customizable icon.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <memory.h>
+#include "sched.h"
+#include "image_data.h"
+#include "splash_screen.h"
+#include "io.h"
+#include "igd_debug.h"
+
+
+/**
+ * Function to display a splash screen to the user. The splash screen must be
+ * accessible to the kernel mode driver as it has to be displayed immediately
+ * after setting the mode (if requested by the user through config options).
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data)
+{
+ if (image_data[0] == 0x89) {
+ display_png_splash_screen(fb_info, fb, ss_data);
+ } else {
+ display_bmp_splash_screen(fb_info, fb, ss_data);
+ }
+}
+
+/*
+ * This is the function to display the bmp splash screen.
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_bmp_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data)
+{
+ unsigned char *fb_addr, *icon_temp;
+ unsigned long *fb_addr_long, icon_long;
+ unsigned long bitmap_pitch;
+ short x, y;
+ unsigned long init_x_shift, init_y_shift;
+ unsigned long row, col, fb_index;
+ unsigned long bytecount, temp;
+ unsigned long limit_width, limit_height;
+
+ EMGD_TRACE_ENTER;
+
+ x = (short) ss_data->x;
+ y = (short) ss_data->y;
+
+ if(x < 0) {
+ init_x_shift = (fb_info->width + x) * 4;
+ init_y_shift = (fb_info->height + y) * fb_info->screen_pitch;
+ } else {
+ init_x_shift = x * 4;
+ init_y_shift = y * fb_info->screen_pitch;
+ }
+
+ fb_addr = fb + init_y_shift;
+ bytecount = (unsigned long) image_data[1];
+ bitmap_pitch = ss_data->width * bytecount;
+
+ limit_width = ss_data->width;
+ limit_height = ss_data->height;
+
+ if (x+ss_data->width > fb_info->width) {
+ limit_width = fb_info->width - x;
+ }
+ if (y+ss_data->height > fb_info->height) {
+ limit_height = fb_info->height - y;
+ }
+
+ for(row = 0; row < limit_height; row++) {
+ fb_addr_long =
+ (unsigned long *) &fb_addr[fb_info->screen_pitch * row +
+ init_x_shift];
+ /*
+ * We are adding 3 bytes here, the first byte indicates BMP or PNG,
+ * the second byte is the bytecount
+ * and the third byte is the palette count
+ */
+ icon_temp = &image_data[3 + (row * bitmap_pitch)];
+ fb_index = 0;
+
+ for(col = 0; col < limit_width; col++) {
+
+ icon_long = *((unsigned long *) &icon_temp[col*bytecount]);
+ switch(bytecount) {
+ case 1:
+ /* 8 bit */
+ temp = (icon_long & 0xFF);
+ icon_long = ((temp & 0xE0)<<16) | ((temp & 0x1C)<<11) |
+ ((temp & 0x3)<<6);
+ break;
+ case 2:
+ /* 16 bit */
+ temp = (icon_long & 0xFFFF);
+ icon_long = CONV_16_TO_32_BIT(temp);
+ break;
+ }
+ /*
+ * For 24 bit we don't really have to do anything as it is
+ * already in RGB 888 format
+ */
+ fb_addr_long[fb_index++] = icon_long & 0x00FFFFFF;
+ }
+ }
+ EMGD_TRACE_EXIT;
+}
+
+
+/*
+ * This is the function to display the png splash screen.
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_png_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data)
+{
+ unsigned long image_size;
+ unsigned long i;
+ unsigned long chunk_size;
+ unsigned long chunk_type;
+ unsigned long iter = PNG_HEADER_SIZE;
+ png_header image_header;
+ png_frame *frames = NULL;
+ png_frame *default_image = NULL;
+ unsigned long gama = 0;
+ unsigned long palette_size = 0;
+ unsigned char *input_data = NULL;
+ unsigned long input_iter = 0;
+ unsigned long apng_num_frames = 0;
+ unsigned long apng_num_plays = 0;
+ unsigned long sequence_number = 0;
+ unsigned long cur_seq_num = 0;
+ unsigned long orig_x = 0;
+ unsigned long orig_y = 0;
+ unsigned long apng_file = 0;
+ unsigned long cur_frame = 0;
+ unsigned char trans_p = 0;
+ unsigned long prev_dispose_op = 0;
+ unsigned short delay_num, delay_den;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Just incase there is no background and we have alpha values, lets
+ * use the background specified in ss_data.
+ */
+ image_header.background = 0xFF000000 | ss_data->bg_color;
+ image_header.background_r = (image_header.background >> 16) & 0xFF;
+ image_header.background_g = (image_header.background >> 8) & 0xFF;
+ image_header.background_b = image_header.background & 0xFF;
+
+ image_size = sizeof(image_data)/sizeof(unsigned char);
+ input_data = (unsigned char *)vmalloc(sizeof(image_data));
+ if (!input_data) {
+ EMGD_ERROR("Out of memory");
+ return;
+ }
+ OS_MEMSET(input_data, 0, sizeof(image_data));
+
+ orig_x = (short) ss_data->x;
+ orig_y = (short) ss_data->y;
+
+ /*
+ * Lets get the information for the first chunk, which should be
+ * the header chunk: IHDR.
+ */
+ read_int_from_stream(image_data, &iter, &chunk_size);
+ read_int_from_stream(image_data, &iter, &chunk_type);
+
+ /*
+ * Initialize image_header
+ */
+ image_header.width = 0;
+ image_header.height = 0;
+ image_header.bit_depth = 0;
+ image_header.colour_type = 0;
+ image_header.compression_method = 0;
+ image_header.filter_method = 0;
+ image_header.interlace_method = 0;
+ image_header.bpp = 0;
+ image_header.bytes_pp = 0;
+ image_header.bytes_pl = 0;
+
+ /* Loop through the PNG chunks */
+ while (iter <= image_size) {
+ switch (chunk_type) {
+ case CHUNK_IHDR:
+ read_int_from_stream(image_data, &iter, &image_header.width);
+ read_int_from_stream(image_data, &iter, &image_header.height);
+ image_header.bit_depth = (unsigned char)image_data[iter++];
+ image_header.colour_type = (unsigned char)image_data[iter++];
+ image_header.compression_method = (unsigned char)image_data[iter++];
+ image_header.filter_method = (unsigned char)image_data[iter++];
+ image_header.interlace_method = (unsigned char)image_data[iter++];
+ image_header.x_offset = orig_x;
+ image_header.y_offset = orig_y;
+
+ /* store bits per pixel based on PNG spec */
+ switch (image_header.colour_type) {
+ case COLOR_GREY:
+ image_header.bpp = image_header.bit_depth;
+ break;
+ case COLOR_TRUE:
+ image_header.bpp = 3 * image_header.bit_depth;
+ break;
+ case COLOR_INDEXED:
+ image_header.bpp = image_header.bit_depth;
+ break;
+ case COLOR_GREY_ALPHA:
+ image_header.bpp = 2 * image_header.bit_depth;
+ break;
+ case COLOR_TRUE_ALPHA:
+ image_header.bpp = 4 * image_header.bit_depth;
+ break;
+ }
+ /*
+ * Adding 7 to the bits per pixel before we divide by 8
+ * gives us the ceiling of bytes per pixel instead of the floor.
+ */
+ image_header.bytes_pp = (image_header.bpp + 7) / 8;
+ image_header.bytes_pl =
+ ((image_header.width * image_header.bpp) + 7) / 8;
+ break;
+
+ case CHUNK_TRNS:
+ image_header.using_transparency = 1;
+ switch (image_header.colour_type) {
+ case COLOR_GREY:
+ read_short_from_stream(image_data, &iter,
+ &image_header.transparency_r);
+ break;
+ case COLOR_TRUE:
+ read_short_from_stream(image_data, &iter,
+ &image_header.transparency_r);
+ read_short_from_stream(image_data, &iter,
+ &image_header.transparency_g);
+ read_short_from_stream(image_data, &iter,
+ &image_header.transparency_b);
+ break;
+ case COLOR_INDEXED:
+ if (image_header.image_palette) {
+ if (chunk_size > palette_size) {
+ EMGD_ERROR("Palette size is smaller than "
+ "transparency values for the palette");
+ }
+ for (i=0; i<chunk_size; i++) {
+ read_char_from_stream(image_data, &iter, &trans_p);
+ image_header.image_palette[i] &= 0xFFFFFF |
+ ((trans_p << 28) | (trans_p << 24));
+ }
+ } else {
+ EMGD_ERROR("Palette has not been initialized yet");
+ }
+ break;
+ }
+ break;
+
+ case CHUNK_BKGD:
+ /* Truecolor */
+ if (image_header.colour_type == COLOR_TRUE_ALPHA ||
+ image_header.colour_type == COLOR_TRUE) {
+
+ switch (image_header.bit_depth) {
+ case 16:
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_g);
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_b);
+ iter++;
+ break;
+ case 8:
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_g);
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_b);
+ break;
+ }
+ }
+
+ /* Grayscale */
+ if (image_header.colour_type == COLOR_GREY_ALPHA ||
+ image_header.colour_type == COLOR_GREY) {
+
+ switch (image_header.bit_depth) {
+ case 16:
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ iter++;
+ break;
+ case 8:
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ break;
+ case 4:
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ image_header.background_r =
+ ((image_header.background_r >> 4) << 4) |
+ (image_header.background_r >> 4);
+ break;
+ case 2:
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ image_header.background_r =
+ ((image_header.background_r >> 2) << 6) |
+ ((image_header.background_r >> 2) << 4) |
+ ((image_header.background_r >> 2) << 2) |
+ (image_header.background_r >> 2);
+ break;
+ case 1:
+ iter++;
+ read_char_from_stream(image_data, &iter,
+ &image_header.background_r);
+ image_header.background_r =
+ (image_header.background_r << 7) |
+ (image_header.background_r << 6) |
+ (image_header.background_r << 5) |
+ (image_header.background_r << 4) |
+ (image_header.background_r << 3) |
+ (image_header.background_r << 2) |
+ (image_header.background_r << 1) |
+ image_header.background_r;
+ break;
+ }
+ image_header.background_g = image_header.background_r;
+ image_header.background_b = image_header.background_r;
+ }
+
+ image_header.background = 0xFF000000 |
+ image_header.background_r<<16 |
+ image_header.background_g<<8 |
+ image_header.background_b;
+ break;
+
+ case CHUNK_GAMA:
+ read_int_from_stream(image_data, &iter, &gama);
+ break;
+
+ case CHUNK_PLTE:
+ palette_size = chunk_size/3;
+ image_header.image_palette =
+ vmalloc(sizeof(unsigned long) * palette_size);
+ if (!image_header.image_palette) {
+ EMGD_ERROR("Out of memory");
+ return;
+ }
+ OS_MEMSET(image_header.image_palette, 0,
+ sizeof(unsigned long) * palette_size);
+
+ for (i=0; i<palette_size; i++) {
+ image_header.image_palette[i] = (
+ 0xFF000000 |
+ ((unsigned char)image_data[iter] << 16) |
+ ((unsigned char)image_data[iter+1] << 8) |
+ (unsigned char)image_data[iter+2]);
+ iter += 3;
+ }
+ break;
+
+ case CHUNK_IDAT:
+ if (!default_image) {
+ default_image = vmalloc(sizeof(png_header));
+ if (!default_image) {
+ EMGD_ERROR("Out of memory");
+ return;
+ }
+ OS_MEMSET(default_image, 0, sizeof(png_header));
+ default_image->width = image_header.width;
+ default_image->height = image_header.height;
+ default_image->x_offset = 0;
+ default_image->y_offset = 0;
+ default_image->bytes_pp = image_header.bytes_pp;
+ default_image->bytes_pl = image_header.bytes_pl;
+ default_image->blend_op = APNG_BLEND_OP_SOURCE;
+ default_image->dispose_op = APNG_DISPOSE_OP_NONE;
+ }
+ for (i=0; i<chunk_size; i++) {
+ input_data[input_iter++] = image_data[iter++];
+ }
+ break;
+
+ case CHUNK_ACTL:
+ apng_file = 1;
+ read_int_from_stream(image_data, &iter, &apng_num_frames);
+ read_int_from_stream(image_data, &iter, &apng_num_plays);
+ frames = vmalloc(apng_num_frames * sizeof(png_frame));
+ if (!frames) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(frames, 0, apng_num_frames * sizeof(png_frame));
+ break;
+
+ case CHUNK_FCTL:
+ if (cur_seq_num > 0) {
+ decode_png_data(&image_header,input_data,&frames[cur_frame-1]);
+ } else {
+ if (default_image) {
+ decode_png_data(&image_header, input_data, default_image);
+ }
+ }
+
+ /* Should we wipe out the input_data buffer? */
+ input_iter = 0;
+
+ read_int_from_stream(image_data, &iter, &sequence_number);
+ read_int_from_stream(image_data, &iter, &frames[cur_frame].width);
+ read_int_from_stream(image_data, &iter, &frames[cur_frame].height);
+ read_int_from_stream(image_data, &iter, &frames[cur_frame].x_offset);
+ read_int_from_stream(image_data, &iter, &frames[cur_frame].y_offset);
+ read_short_from_stream(image_data, &iter, &delay_num);
+ read_short_from_stream(image_data, &iter, &delay_den);
+ read_char_from_stream(image_data, &iter, &frames[cur_frame].dispose_op);
+ read_char_from_stream(image_data, &iter, &frames[cur_frame].blend_op);
+
+ if (delay_num) {
+ if (!delay_den) {
+ frames[cur_frame].delay = 10000 * (unsigned long)delay_num;
+ } else {
+ frames[cur_frame].delay = (1000000 *
+ (unsigned long)delay_num) / (unsigned long)delay_den;
+ }
+ }
+
+ /*
+ * Adding 7 to the bits per pixel before we divide by 8
+ * gives us the ceiling of bytes per pixel instead of the floor.
+ */
+ frames[cur_frame].bytes_pp = (image_header.bpp + 7) / 8;
+ frames[cur_frame].bytes_pl =
+ ((frames[cur_frame].width * image_header.bpp) + 7) / 8;
+
+ cur_frame++;
+
+ if (sequence_number != cur_seq_num++) {
+ EMGD_ERROR("Sequence numbers do not match!");
+ return;
+ }
+ break;
+
+ case CHUNK_FDAT:
+ read_int_from_stream(image_data, &iter, &sequence_number);
+ if (sequence_number != cur_seq_num++) {
+ EMGD_ERROR("Sequence numbers do not match!");
+ return;
+ }
+ for (i=4; i<chunk_size; i++) {
+ input_data[input_iter++] = image_data[iter++];
+ }
+ break;
+
+ case CHUNK_IEND:
+ if (!frames && default_image) {
+ decode_png_data(&image_header, input_data,
+ default_image);
+ } else {
+ decode_png_data(&image_header, input_data,
+ &frames[cur_frame-1]);
+ }
+ break;
+
+ default:
+ iter += chunk_size;
+ break;
+ }
+
+ /*
+ * Skip over the CRC for now, do we actually want to spend
+ * time checking this? Per the spec, unless there is an a corrupted
+ * header, the only possible outcome is a corrupted image. It's
+ * either that, or we don't display any image, maybe in this case we
+ * should display a blue screen. :)
+ */
+ iter += 4;
+
+ /* Get the next chunk */
+ read_int_from_stream(image_data, &iter, &chunk_size);
+ read_int_from_stream(image_data, &iter, &chunk_type);
+ }
+
+ if (input_data) {
+ vfree(input_data);
+ input_data = NULL;
+ }
+
+ if (apng_file && !apng_num_plays) {
+ apng_num_plays = 20;
+ }
+ if (apng_num_frames > 0) {
+ frames[apng_num_frames-1].dispose_op = APNG_DISPOSE_OP_NONE;
+ if (frames[0].dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+ frames[0].dispose_op = APNG_DISPOSE_OP_BACKGROUND;
+ }
+ }
+ for (i=0; i<apng_num_plays; i++) {
+ for (cur_frame=0; cur_frame<apng_num_frames; cur_frame++) {
+ if (cur_frame > 0) {
+ prev_dispose_op = frames[cur_frame-1].dispose_op;
+ }
+ display_png_frame(fb_info, fb, image_header, &frames[cur_frame],
+ prev_dispose_op);
+ }
+ }
+ if (!apng_file) {
+ display_png_frame(fb_info, fb, image_header, default_image,
+ APNG_DISPOSE_OP_NONE);
+ }
+
+ for (cur_frame=0; cur_frame<apng_num_frames; cur_frame++) {
+ if (frames[cur_frame].output) {
+ vfree(frames[cur_frame].output);
+ frames[cur_frame].output = NULL;
+ }
+ }
+ if (frames) {
+ vfree(frames);
+ frames = NULL;
+ }
+
+ if (default_image->output) {
+ vfree(default_image->output);
+ default_image->output = NULL;
+ }
+
+ if (default_image) {
+ vfree(default_image);
+ default_image = NULL;
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+void display_png_frame(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ png_header image_header,
+ png_frame *frame,
+ unsigned long prev_dispose_op)
+{
+ unsigned char *fb_addr = NULL;
+ unsigned long *fb_addr_long = NULL;
+ unsigned long init_x_shift, init_y_shift, row, col, j;
+ unsigned char image_alpha;
+ unsigned char background_alpha;
+ unsigned long *previous = NULL;
+
+ if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+ previous = vmalloc(frame->width*frame->height*sizeof(unsigned long));
+ if (!previous) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ }
+
+ /* Lets position our image at the supplied offsets on the screen */
+ /* TODO: Need to account for negative offset */
+ init_x_shift = (image_header.x_offset + frame->x_offset) *
+ sizeof(unsigned long);
+ init_y_shift = (image_header.y_offset + frame->y_offset) *
+ fb_info->screen_pitch;
+ fb_addr = fb + init_y_shift;
+ fb_addr_long = (unsigned long *) &fb_addr[init_x_shift];
+
+ row = 0;
+ j = 0;
+
+ switch (frame->blend_op) {
+
+ /* Blending against our background color */
+ case APNG_BLEND_OP_SOURCE:
+ while (row < frame->height){
+ col = 0;
+ fb_addr_long = (unsigned long *)
+ &fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+ if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+ /* Save the previous since we need to dispose to it */
+ OS_MEMCPY((void *)&previous[j], (void *)fb_addr_long,
+ frame->width * sizeof(unsigned long));
+ }
+
+ /* Put together the pixel and output to framebuffer */
+ while (col < frame->width) {
+ image_alpha = frame->output[j]>>24;
+ if (image_alpha){
+ if (image_alpha != 0xFF){
+ background_alpha = (0xFF - image_alpha) & 0xFF;
+
+ frame->output[j] = 0xFF000000 |
+ ((((((frame->output[j]&0xFF0000)>>16) *
+ image_alpha)/0xFF) +
+ ((((image_header.background&0xFF0000)>>16) *
+ background_alpha)/0xFF))<<16) |
+ ((((((frame->output[j]&0x00FF00)>>8) *
+ image_alpha)/0xFF) +
+ ((((image_header.background&0x00FF00)>>8) *
+ background_alpha)/0xFF))<<8) |
+ ((((((frame->output[j]&0x0000FF)) *
+ image_alpha)/0xFF) +
+ ((((image_header.background&0x0000FF)) *
+ background_alpha)/0xFF)));
+ }
+ } else {
+ frame->output[j] = image_header.background;
+ }
+ fb_addr_long[col] = frame->output[j];
+ col++;
+ j++;
+ }
+ row++;
+ }
+ break;
+
+ /* Blending against previous frame */
+ case APNG_BLEND_OP_OVER:
+ while (row < frame->height){
+ col = 0;
+ fb_addr_long = (unsigned long *)
+ &fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+ if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+ /* Save the previous isince we need to dispose to it */
+ OS_MEMCPY((void *)&previous[j], (void *)fb_addr_long,
+ frame->width * sizeof(unsigned long));
+ }
+
+ /* Blend the pixel with existing framebuffer pixel */
+ while (col < frame->width) {
+ image_alpha = frame->output[j]>>24;
+
+ if (image_alpha){
+ if (image_alpha != 0xFF){
+ background_alpha = (0xFF - image_alpha) & 0xFF;
+
+ frame->output[j] = 0xFF000000 |
+ ((((((frame->output[j]&0xFF0000)>>16) *
+ image_alpha)/0xFF) +
+ ((((fb_addr_long[col]&0xFF0000)>>16) *
+ background_alpha)/0xFF))<<16) |
+ ((((((frame->output[j]&0x00FF00)>>8) *
+ image_alpha)/0xFF) +
+ ((((fb_addr_long[col]&0x00FF00)>>8) *
+ background_alpha)/0xFF))<<8) |
+ ((((((frame->output[j]&0x0000FF)) *
+ image_alpha)/0xFF) +
+ ((((fb_addr_long[col]&0x0000FF)) *
+ background_alpha)/0xFF)));
+ }
+ fb_addr_long[col] = frame->output[j];
+ }
+ col++;
+ j++;
+ }
+ row++;
+ }
+ break;
+ }
+
+ if (frame->delay) {
+ OS_SLEEP(frame->delay);
+ }
+
+ fb_addr = fb + init_y_shift;
+ fb_addr_long = (unsigned long *) &fb_addr[init_x_shift];
+ row = 0;
+
+ /* TODO: It would be better to only do this to the portions of the
+ * frame that will not get overwritten by the next frame.
+ */
+ switch (frame->dispose_op) {
+ case APNG_DISPOSE_OP_PREVIOUS:
+ j = 0;
+ while (row < frame->height){
+ fb_addr_long = (unsigned long *)
+ &fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+ OS_MEMCPY((void *)fb_addr_long, (void *)&previous[j],
+ frame->width * sizeof(unsigned long));
+
+ j+= frame->width;
+ row++;
+ }
+ if (previous) {
+ vfree(previous);
+ previous = NULL;
+ }
+ break;
+ case APNG_DISPOSE_OP_BACKGROUND:
+ while (row < frame->height){
+ fb_addr_long = (unsigned long *)
+ &fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+ OS_MEMSET((void *)fb_addr_long, image_header.background,
+ frame->width * sizeof(unsigned long));
+
+ row++;
+ }
+ break;
+ }
+}
+
+
+void decode_png_data(
+ png_header *image_header,
+ unsigned char *input_data,
+ png_frame *frame)
+{
+ unsigned char *output;
+ unsigned long output_iter = 0;
+
+ unsigned long iter = 0;
+ unsigned char bit_iter = 0;
+ unsigned long row = 0, col = 0;
+ unsigned long end_of_row;
+ unsigned long j,k,l;
+
+ unsigned char zlib_cmf = 0;
+ unsigned char zlib_flg = 0;
+ unsigned char zlib_cm = 0;
+ unsigned char zlib_cinfo = 0;
+ unsigned char zlib_fcheck = 0;
+ unsigned char zlib_fdict = 0;
+ unsigned char zlib_flevel = 0;
+ unsigned long zlib_dictid = 0;
+
+ huffman_node *length_tree = NULL;
+ huffman_node *distance_tree = NULL;
+
+ unsigned char paeth_a, paeth_b, paeth_c;
+ unsigned long paeth_p, paeth_pa, paeth_pb, paeth_pc;
+
+ unsigned long filter_type = 0;
+ unsigned long bfinal = 0;
+ unsigned long btype = 0;
+ unsigned char compr_len = 0;
+ unsigned char compr_nlen = 0;
+ unsigned int small_color;
+
+ /* Allocate space for out output buffer */
+ output = (unsigned char *)vmalloc(
+ frame->height * frame->bytes_pl + frame->height);
+ if (!output) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(output, 0, frame->height * frame->bytes_pl + frame->height);
+
+ frame->size = frame->height * frame->width * sizeof(unsigned long);
+ frame->output = vmalloc(frame->size);
+ if (!frame->output) {
+ frame->size = 0;
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(frame->output, 0, frame->size);
+
+ /* Data, this needs to be decompressed per zlib spec */
+ if (!zlib_cmf) {
+ zlib_cmf = (unsigned char)input_data[iter++];
+ zlib_flg = (unsigned char)input_data[iter++];
+ zlib_cm = zlib_cmf & 0xF;
+ zlib_cinfo = (zlib_cmf >> 4) & 0xF;
+ zlib_fcheck = zlib_flg & 0x1F;
+ zlib_fdict = (zlib_flg & 0x20) >> 5;
+ zlib_flevel = (zlib_flg >> 6) & 0x3;
+
+ if (zlib_fdict) {
+ read_int_from_stream(input_data, &iter, &zlib_dictid);
+ }
+ }
+
+ /* Here is where we need to process data as a bit stream */
+ bfinal = 0;
+ while (!bfinal) {
+ read_bits_from_stream(input_data, &iter, &bit_iter, 1, &bfinal);
+ read_bits_from_stream(input_data, &iter, &bit_iter, 2, &btype);
+
+ if (btype == 0){
+
+ if (bit_iter) {
+ iter++;
+ bit_iter = 0;
+ }
+
+ /* No Compression */
+ read_char_from_stream(input_data, &iter, &compr_len);
+ read_char_from_stream(input_data, &iter, &compr_nlen);
+
+ for (j = 0;j < compr_len; j++) {
+ read_char_from_stream(input_data, &iter, &output[j]);
+ }
+
+ } else {
+
+ if (btype == 2){
+
+ /* Compressed with dynamnic Huffman codes */
+ build_dynamic_huffman_tree(
+ input_data,
+ &iter,
+ &bit_iter,
+ &length_tree,
+ &distance_tree);
+ } else {
+
+ /* Compressed with static Huffman codes */
+ build_static_huffman_tree(&length_tree, &distance_tree);
+ }
+
+ /* Decompress huffman code */
+ decompress_huffman(
+ input_data,
+ &iter,
+ &bit_iter,
+ &length_tree,
+ &distance_tree,
+ output,
+ &output_iter);
+
+ free_node(length_tree);
+ free_node(distance_tree);
+ }
+ }
+
+ row = 0;
+ j = 0;
+ l = 0;
+
+ /*
+ * Process the scanline filtering
+ * This filtering works by using a difference from a previous pixel
+ * instead of full pixel data.
+ */
+ while (row < frame->height){
+ j = row * frame->bytes_pl + row;
+ end_of_row = j + frame->bytes_pl;
+ filter_type = output[j++];
+
+ switch (filter_type) {
+ case 1:
+ /* Filter type of 1 uses the previous pixel */
+ for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+ output[k] += output[k-frame->bytes_pp];
+ }
+ break;
+ case 2:
+ /* Filter type of 2 uses the previous row's pixel */
+ if (row) {
+ for (k=j; k<=end_of_row; k++) {
+ output[k] += output[k-frame->bytes_pl-1];
+ }
+ }
+ break;
+ case 3:
+ /*
+ * Filter type of 3 uses the average of the
+ * previous pixel and the previous row's pixel
+ */
+ if (row) {
+ for (k=j; k<j+frame->bytes_pp; k++) {
+ output[k] += output[k-frame->bytes_pl-1]/2;
+ }
+ for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+ output[k] += (output[k-frame->bytes_pp] +
+ output[k-frame->bytes_pl-1])/2;
+ }
+ } else {
+ for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+ output[k] = output[k] +
+ output[k-frame->bytes_pp]/2;
+ }
+ }
+ break;
+ case 4:
+ /*
+ * Filter type of 4 uses this algorithm to
+ * determine if it should use the previous pixel,
+ * the previous row's pixel, or the pixel immediately
+ * before the previous row's pixel.
+ */
+ for (k=j; k<=end_of_row; k++) {
+
+ if (k >= j + frame->bytes_pp) {
+ paeth_a = output[k-frame->bytes_pp];
+ } else {
+ paeth_a = 0;
+ }
+
+ if (row) {
+ paeth_b = output[k-frame->bytes_pl-1];
+ } else {
+ paeth_b = 0;
+ }
+
+ if (row && k >= j + frame->bytes_pp) {
+ paeth_c = output[k-frame->bytes_pp-frame->bytes_pl-1];
+ } else {
+ paeth_c = 0;
+ }
+
+ paeth_p = paeth_a + paeth_b - paeth_c;
+ paeth_pa = abs(paeth_p - paeth_a);
+ paeth_pb = abs(paeth_p - paeth_b);
+ paeth_pc = abs(paeth_p - paeth_c);
+
+ if (paeth_pa <= paeth_pb && paeth_pa <= paeth_pc) {
+ output[k] += paeth_a;
+ } else if (paeth_pb <= paeth_pc) {
+ output[k] += paeth_b;
+ } else {
+ output[k] += paeth_c;
+ }
+ }
+ break;
+ }
+
+ col = 0;
+
+ /* Put together the pixel and output to framebuffer */
+ while (col < frame->width) {
+
+ /* Truecolor with alpha, 16 bits per component */
+ if (image_header->colour_type == COLOR_TRUE_ALPHA &&
+ image_header->bit_depth == 16) {
+
+ frame->output[l] = (output[j+6]<<24 | output[j]<<16 |
+ output[j+2]<<8 | output[j+4]);
+ }
+
+
+ /* Truecolor with alpha, 8 bits per component */
+ if (image_header->colour_type == COLOR_TRUE_ALPHA &&
+ image_header->bit_depth == 8) {
+
+ frame->output[l] = (output[j+3]<<24 | output[j]<<16 |
+ output[j+1]<<8 | output[j+2]);
+ }
+
+ /* Grayscale with alpha, 16 bits per component */
+ if (image_header->colour_type == COLOR_GREY_ALPHA &&
+ image_header->bit_depth == 16) {
+
+ frame->output[l] = (output[j+2]<<24 | output[j]<<16 |
+ output[j]<<8 | output[j]);
+ }
+
+ /* Grayscale with alpha, 8 bits per component */
+ if (image_header->colour_type == COLOR_GREY_ALPHA &&
+ image_header->bit_depth == 8) {
+
+ frame->output[l] = (output[j+1]<<24 | output[j]<<16 |
+ output[j]<<8 | output[j]);
+
+ }
+
+ /* Truecolor, 16 bits per component */
+ if (image_header->colour_type == COLOR_TRUE &&
+ image_header->bit_depth == 16) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r !=
+ (output[j] | output[j+1]) ||
+ image_header->transparency_g !=
+ (output[j+2] | output[j+3]) ||
+ image_header->transparency_b !=
+ (output[j+4] | output[j+5])) {
+
+ frame->output[l] = (0xFF000000 | output[j]<<16 |
+ output[j+2]<<8 | output[j+4]);
+ }
+ }
+
+ /* Truecolor, 8 bits per component */
+ if (image_header->colour_type == COLOR_TRUE &&
+ image_header->bit_depth == 8) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != output[j] ||
+ image_header->transparency_g != output[j+1] ||
+ image_header->transparency_b != output[j+2]) {
+
+ frame->output[l] = (0xFF000000 | (output[j]<<16) |
+ (output[j+1]<<8) | (output[j+2]));
+ }
+ }
+
+ /* Grayscale, 16 bits per component */
+ if (image_header->colour_type == COLOR_GREY &&
+ image_header->bit_depth == 16) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r !=
+ (output[j] | output[j+1])) {
+
+ frame->output[l] = (0xFF000000 |(output[j]<<16) |
+ (output[j]<<8) | output[j]);
+ }
+ }
+
+ /* Grayscale, 8 bits per component */
+ if (image_header->colour_type == COLOR_GREY &&
+ image_header->bit_depth == 8) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != output[j]) {
+ frame->output[l] = (0xFF000000 | (output[j]<<16) |
+ (output[j]<<8) | output[j]);
+ }
+ }
+
+ /* Grayscale, 4 bits per component */
+ if (image_header->colour_type == COLOR_GREY &&
+ image_header->bit_depth == 4) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0xF0)>>4)) {
+
+ frame->output[l] =
+ CONV_GS_4_TO_32((output[j] & 0xF0)>>4);
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != (output[j] & 0x0F)) {
+
+ frame->output[l] =
+ CONV_GS_4_TO_32(output[j] & 0x0F);
+ }
+ }
+ }
+
+ /* Grayscale, 2 bits per component */
+ if (image_header->colour_type == COLOR_GREY &&
+ image_header->bit_depth == 2) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0xC0)>>6)) {
+
+ frame->output[l] =
+ CONV_GS_2_TO_32((output[j] & 0xC0) >> 6);
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x30)>>4)) {
+
+ frame->output[l] =
+ CONV_GS_2_TO_32((output[j] & 0x30) >> 4);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x0C)>>2)) {
+
+ frame->output[l] =
+ CONV_GS_2_TO_32((output[j] & 0x0C) >> 2);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != (output[j] & 0x03)) {
+
+ frame->output[l] =
+ CONV_GS_2_TO_32(output[j] & 0x03);
+ }
+ }
+ }
+
+ /* Grayscale, 1 bit per component */
+ if (image_header->colour_type == COLOR_GREY &&
+ image_header->bit_depth == 1) {
+
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x80)>>7)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x80) >> 7);
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x40)>>6)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x40) >> 6);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x20)>>5)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x20) >> 5);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x10)>>4)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x10) >> 4);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x08)>>3)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x08) >> 3);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x04)>>2)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x04) >> 2);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != ((output[j] & 0x02)>>1)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32((output[j] & 0x02) >> 1);
+ }
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ if (!image_header->using_transparency ||
+ image_header->transparency_r != (output[j] & 0x01)) {
+
+ frame->output[l] =
+ CONV_GS_1_TO_32(output[j] & 0x01);
+ }
+ }
+ }
+
+ /* Palette, 8 bit per component */
+ if (image_header->colour_type == COLOR_INDEXED &&
+ image_header->bit_depth == 8) {
+
+ small_color = output[j];
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+
+ /* Palette, 4 bit per component */
+ if (image_header->colour_type == COLOR_INDEXED &&
+ image_header->bit_depth == 4) {
+
+ small_color = (output[j] & 0xF0) >> 4;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = output[j] & 0x0F;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ }
+
+ /* Palette, 2 bit per component */
+ if (image_header->colour_type == COLOR_INDEXED &&
+ image_header->bit_depth == 2) {
+
+ small_color = (output[j] & 0xC0) >> 6;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = output[j] & 0x30 >> 4;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = output[j] & 0x0C >> 2;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = output[j] & 0x03;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ }
+
+ /* Palette, 1 bit per component */
+ if (image_header->colour_type == COLOR_INDEXED &&
+ image_header->bit_depth == 1) {
+
+ small_color = (output[j] & 0x80) >> 7;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x40) >> 6;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x20) >> 5;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x10) >> 4;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x08) >> 3;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x04) >> 2;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x02) >> 1;
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ if (col + 1 < frame->width) {
+ l++;
+ col++;
+ small_color = (output[j] & 0x01);
+ frame->output[l] = 0xFF000000 |
+ image_header->image_palette[small_color];
+ }
+ }
+
+ j += image_header->bytes_pp;
+ l++;
+ col++;
+ if (l > frame->height * frame->width) {
+ EMGD_ERROR("l is larger than frame output size!");
+ return;
+ }
+ }
+ row++;
+ }
+
+ vfree(output);
+}
+
+/*
+ * This is the function to decompress a huffman tree.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ * are reading.
+ * @param length_tree (IN) This is the huffman code's length tree.
+ * @param distance_tree (IN) This is the huffman code's distance tree.
+ * @param output (IN/OUT) This is an output stream to which we write out the
+ * decompressed huffman data.
+ * @param output_iter (IN/OUT) This is the output iterator.
+ */
+void decompress_huffman(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **length_tree,
+ huffman_node **distance_tree,
+ unsigned char *output,
+ unsigned long *output_iter)
+{
+
+ unsigned long j,k;
+ huffman_node *final_node;
+ unsigned long extra_value = 0;
+ unsigned long length_value = 0;
+ unsigned long distance_value = 0;
+
+ /* Start going along the bitstream and traversing the tree
+ * until you get to a leaf
+ */
+ get_huffman_code(stream, iter, bit_iter, length_tree, &final_node);
+
+ while (final_node->value != 256) {
+
+ if (final_node->value < 256){
+ /* literal value */
+ output[*output_iter] = final_node->value;
+ (*output_iter)++;
+ }
+ if (final_node->value > 256){
+ /* We have the initial length value,
+ * now get the extra length bits, if any
+ */
+ extra_value = 0;
+ length_value = 0;
+ for (j=0; j<final_node->extra_bits; j++){
+ extra_value = read_bit_from_stream(stream, iter, bit_iter);
+ length_value += extra_value << j;
+ }
+ length_value += final_node->real;
+
+ /* Now its time to get the distance value */
+ get_huffman_code(stream, iter, bit_iter, distance_tree, &final_node);
+
+ /* Get any extra bits for the distance value */
+ extra_value = 0;
+ distance_value = 0;
+ for (j=0; j<final_node->extra_bits; j++){
+ extra_value = read_bit_from_stream(stream, iter, bit_iter);
+ distance_value += extra_value << j;
+ }
+ distance_value += final_node->real;
+
+ /*
+ * Now we need to use the distance and length values
+ * to copy previously existing values
+ */
+ distance_value = (*output_iter) - distance_value;
+ for (k=0; k<length_value; k++){
+ output[*output_iter] = output[distance_value];
+ (*output_iter)++;
+ distance_value++;
+ }
+ }
+
+ /* Get the next code */
+ get_huffman_code(stream, iter, bit_iter, length_tree, &final_node);
+ }
+}
+
+
+/*
+ * This is the function to build a static huffman tree.
+ *
+ * @param length_tree (OUT) This is the huffman code's length tree.
+ * @param distance_tree (OUT) This is the huffman code's distance tree.
+ */
+void build_static_huffman_tree(
+ huffman_node **length_tree,
+ huffman_node **distance_tree) {
+
+ huffman_node *new_node = NULL;
+ huffman_node *cur_node = NULL;
+ unsigned long j,k;
+ unsigned long running_literal_value = 0;
+ unsigned long running_real_value = 0;
+
+ unsigned long ltree_literal_value[10] =
+ {256,265,269,273,277, 0,280,281,285,144};
+ unsigned long ltree_real_value[10] =
+ { 2, 11, 19, 35, 67, 0,115,131,258,144};
+ unsigned long ltree_literal_length[10] =
+ { 9, 4, 4, 4, 3,144, 1, 4, 3,112};
+ unsigned long ltree_code_start[10] =
+ { 0, 9, 13, 17, 21, 48,192,193,197,400};
+ unsigned long ltree_code_length[10] =
+ { 7, 7, 7, 7, 7, 8, 8, 8, 8, 9};
+ unsigned long ltree_extra_bits[10] =
+ { 0, 1, 2, 3, 4, 0, 4, 5, 0, 0};
+
+ unsigned long dtree_literal_value[15] =
+ {0,4,6, 8,10,12, 14, 16, 18, 20, 22, 24, 26, 28,30};
+ unsigned long dtree_real_value[15] =
+ {1,5,9,17,33,65,129,257,513,1025,2049,4097,8193,16385, 0};
+ unsigned long dtree_literal_length[15] =
+ {4,2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+ unsigned long dtree_code_start[15] =
+ {0,4,6, 8,10,12, 14, 16, 18, 20, 22, 24, 26, 28,30};
+ unsigned long dtree_code_length[15] =
+ {5,5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
+ unsigned long dtree_extra_bits[15] =
+ {0,1,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0};
+
+ /* Build our Huffman length tree using the fixed codes */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+
+ *length_tree = new_node;
+
+ for (k=0; k<10; k++){
+ running_literal_value = ltree_literal_value[k];
+ running_real_value = ltree_real_value[k];
+ for (j=0; j<ltree_literal_length[k]; j++) {
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+
+ new_node->extra_bits = (unsigned char)ltree_extra_bits[k];
+ new_node->value = running_literal_value;
+ new_node->real = running_real_value;
+ cur_node = *length_tree;
+ add_node(&cur_node,
+ new_node,
+ ltree_code_start[k] + j,
+ ltree_code_length[k]);
+ running_literal_value++;
+ if (ltree_extra_bits[k]){
+ running_real_value += (1<<ltree_extra_bits[k]);
+ }else{
+ running_real_value++;
+ }
+ }
+ }
+
+ /* Build our Huffman distance tree using the fixed codes */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ *distance_tree = new_node;
+
+ for (k=0; k<15; k++){
+ running_literal_value = dtree_literal_value[k];
+ running_real_value = dtree_real_value[k];
+ for (j=0; j<dtree_literal_length[k]; j++) {
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ new_node->extra_bits = (unsigned char)dtree_extra_bits[k];
+ new_node->value = running_literal_value;
+ new_node->real = running_real_value;
+ cur_node = *distance_tree;
+ add_node(&cur_node,
+ new_node,
+ dtree_code_start[k] + j,
+ dtree_code_length[k]);
+ running_literal_value++;
+ if (dtree_extra_bits[k]){
+ running_real_value += (1<<dtree_extra_bits[k]);
+ }else{
+ running_real_value++;
+ }
+ }
+ }
+}
+
+
+/*
+ * This is the function to build a dynamic huffman tree.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ * are reading.
+ * @param length_tree (OUT) This is the huffman code's length tree.
+ * @param distance_tree (OUT) This is the huffman code's distance tree.
+ */
+void build_dynamic_huffman_tree(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **length_tree,
+ huffman_node **distance_tree) {
+
+ unsigned long j,k;
+ unsigned long clc_order[19] =
+ {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+ unsigned long clc_lengths[19] =
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ unsigned long clc_extra_bits[19] =
+ {2,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ unsigned long clc_values[19] =
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};
+ huffman_node *code_length_tree = NULL;
+ unsigned long dynamic_hlit = 0;
+ unsigned long dynamic_hdist = 0;
+ unsigned long dynamic_hclen = 0;
+
+ unsigned long lit_extra_bits_num[LEN_NUM_DISTINCT_EXTRA_BITS] =
+ {265,4,4,4,4,4,1};
+ unsigned long lit_extra_bits[LEN_NUM_DISTINCT_EXTRA_BITS] =
+ {0,1,2,3,4,5,0};
+ unsigned long *dynamic_lit_code = NULL;
+ unsigned long *dynamic_lit_length = NULL;
+ unsigned long *dynamic_lit_extra_bits = NULL;
+ unsigned long *dynamic_lit_values = NULL;
+ unsigned long *dynamic_lit_real_values = NULL;
+
+ unsigned long dist_extra_bits_num[DIST_NUM_DISTINCT_EXTRA_BITS] =
+ {4,2,2,2,2,2,2,2,2,2,2,2,2,2};
+ unsigned long dist_extra_bits[DIST_NUM_DISTINCT_EXTRA_BITS] =
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13};
+ unsigned long *dynamic_dist_code = NULL;
+ unsigned long *dynamic_dist_length = NULL;
+ unsigned long *dynamic_dist_extra_bits = NULL;
+ unsigned long *dynamic_dist_values = NULL;
+ unsigned long *dynamic_dist_real_values = NULL;
+
+ unsigned long prev_real = 0;
+ unsigned long code_index;
+ huffman_node *new_node = NULL;
+
+ /* Read some initial information about our dynamic huffman tree */
+ read_bits_from_stream(stream, iter, bit_iter, 5, &dynamic_hlit);
+ read_bits_from_stream(stream, iter, bit_iter, 5, &dynamic_hdist);
+ read_bits_from_stream(stream, iter, bit_iter, 4, &dynamic_hclen);
+
+ dynamic_hlit += 257;
+ dynamic_hdist++;
+ dynamic_hclen += 4;
+
+ /* Build our Huffman length tree using the fixed codes */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ code_length_tree = new_node;
+
+ /* Get the code lengths */
+ for (k=0; k<19 && k<dynamic_hclen; k++){
+ read_bits_from_stream(stream,
+ iter, bit_iter, 3, &clc_lengths[clc_order[k]]);
+ }
+
+ /* build the code_length tree */
+ if (create_tree(CLC_MAX_BITS, CLC_NUM_CODES,
+ &clc_lengths[0],
+ &clc_extra_bits[0],
+ &clc_values[0],
+ &clc_values[0],
+ &code_length_tree) == 1) {
+ EMGD_ERROR("ERROR: create tree failed\n");
+ return;
+ }
+
+ /* Build the literal/length alphabet */
+ dynamic_lit_code = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * LEN_NUM_CODES);
+ if (!dynamic_lit_code) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_lit_code, 0, sizeof(unsigned long) * LEN_NUM_CODES);
+
+ dynamic_lit_length = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * LEN_NUM_CODES);
+ if (!dynamic_lit_length) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_lit_length, 0, sizeof(unsigned long) * LEN_NUM_CODES);
+
+ dynamic_lit_extra_bits = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * LEN_NUM_CODES);
+ if (!dynamic_lit_extra_bits) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_lit_extra_bits, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+ dynamic_lit_values = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * LEN_NUM_CODES);
+ if (!dynamic_lit_values) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_lit_values, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+ dynamic_lit_real_values = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * LEN_NUM_CODES);
+ if (!dynamic_lit_real_values) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_lit_real_values, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+ /* build extra information, such as extra bits, values and real_values */
+ prev_real = 2;
+ code_index = 0;
+ for (k=0; k<LEN_NUM_DISTINCT_EXTRA_BITS; k++) {
+ for (j=0; j<lit_extra_bits_num[k]; j++) {
+ dynamic_lit_extra_bits[code_index] = lit_extra_bits[k];
+ dynamic_lit_values[code_index] = code_index;
+
+ if (code_index >= LEN_START_REAL_VALUES){
+ dynamic_lit_real_values[code_index] =
+ prev_real += (1<<dynamic_lit_extra_bits[code_index-1]);
+ } else {
+ dynamic_lit_real_values[code_index] = code_index;
+ }
+ code_index++;
+ }
+ }
+
+ /* Doesn't seem to follow the pattern? */
+ dynamic_lit_real_values[285] = 258;
+
+ /* get code lengths for the literal/length alphabet */
+ get_code_lengths(stream, iter, bit_iter, &code_length_tree,
+ dynamic_hlit, dynamic_lit_length);
+
+ /* allocate tree for literal/length codes */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ *length_tree = new_node;
+
+ /* build the literal/length tree */
+ if (create_tree(LEN_MAX_BITS, LEN_NUM_CODES,
+ dynamic_lit_length,
+ dynamic_lit_extra_bits,
+ dynamic_lit_values,
+ dynamic_lit_real_values,
+ length_tree) == 1) {
+ EMGD_ERROR("ERROR: create tree failed\n");
+ return;
+ }
+
+ /* free all the literal/length data we are no longer using */
+ vfree(dynamic_lit_code);
+ vfree(dynamic_lit_length);
+ vfree(dynamic_lit_extra_bits);
+ vfree(dynamic_lit_values);
+ vfree(dynamic_lit_real_values);
+
+
+ /* Build the distance alphabet */
+ dynamic_dist_code = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * DIST_NUM_CODES);
+ if (!dynamic_dist_code) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_dist_code, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+ dynamic_dist_length = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * DIST_NUM_CODES);
+ if (!dynamic_dist_length) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_dist_length, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+ dynamic_dist_extra_bits = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * DIST_NUM_CODES);
+ if (!dynamic_dist_extra_bits) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_dist_extra_bits, 0,
+ sizeof(unsigned long) * DIST_NUM_CODES);
+
+ dynamic_dist_values = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * DIST_NUM_CODES);
+ if (!dynamic_dist_values) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_dist_values, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+ dynamic_dist_real_values = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * DIST_NUM_CODES);
+ if (!dynamic_dist_real_values) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ OS_MEMSET(dynamic_dist_real_values, 0,
+ sizeof(unsigned long) * DIST_NUM_CODES);
+
+ /* build extra information, such as extra bits, values and real_values */
+ prev_real = 1;
+ code_index = 0;
+ for (k=0; k<DIST_NUM_DISTINCT_EXTRA_BITS; k++) {
+ for (j=0; j<dist_extra_bits_num[k]; j++) {
+ dynamic_dist_extra_bits[code_index] = dist_extra_bits[k];
+ dynamic_dist_values[code_index] = code_index;
+
+ if (code_index >= DIST_START_REAL_VALUES){
+ dynamic_dist_real_values[code_index] =
+ prev_real += (1<<dynamic_dist_extra_bits[code_index-1]);
+ } else {
+ dynamic_dist_real_values[code_index] = code_index+1;
+ }
+ code_index++;
+ }
+ }
+
+ /* get code lengths for the distance alphabet */
+ get_code_lengths(stream, iter, bit_iter, &code_length_tree,
+ dynamic_hdist, dynamic_dist_length);
+
+ /* allocate tree for distance codes */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return;
+ }
+ *distance_tree = new_node;
+
+ /* build the distance tree */
+ if (create_tree(DIST_MAX_BITS, DIST_NUM_CODES,
+ &dynamic_dist_length[0],
+ &dynamic_dist_extra_bits[0],
+ &dynamic_dist_values[0],
+ &dynamic_dist_real_values[0],
+ distance_tree) == 1) {
+ EMGD_ERROR("ERROR: create tree failed.\n");
+ return;
+ }
+
+ /* free all the distance data we are no longer using */
+ vfree(dynamic_dist_code);
+ vfree(dynamic_dist_length);
+ vfree(dynamic_dist_extra_bits);
+ vfree(dynamic_dist_values);
+ vfree(dynamic_dist_real_values);
+
+ /* All done with the code length tree, lets free this memory */
+ free_node(code_length_tree);
+}
+
+
+/*
+ * This is the function to get the dynamic code lengths for a specified
+ * number of code lenths. There is some overuse of the word code and code
+ * lengths, but thats sort of the way the PNG spec is. This is because
+ * we use codes to decode compressed codes.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ * are reading.
+ * @param code_length_tree (IN) This is the huffman code length tree, which is
+ * used to get the code lengths.
+ * @param num_lengths (IN) The number of code lengths.
+ * @param dynamic_lengths (OUT) Gets the dynamic length for the different
+ * code lengths
+ */
+void get_code_lengths(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **code_length_tree,
+ unsigned long num_lengths,
+ unsigned long *dynamic_lengths) {
+
+ unsigned long j,k;
+ huffman_node *final_node;
+ unsigned long dynamic_repeat_length = 0;
+
+ /* get code lengths for the literal/length alphabet */
+ for (k=0; k<num_lengths; k++) {
+ get_huffman_code(stream, iter, bit_iter,
+ code_length_tree, &final_node);
+
+ if (final_node->value < 16){
+ dynamic_lengths[k] = final_node->value;
+ } else {
+ switch (final_node->value) {
+ case 16:
+ /* get repeat length */
+ read_bits_from_stream(stream,
+ iter, bit_iter, 2, &dynamic_repeat_length);
+ dynamic_repeat_length += 3;
+ for (j=0; j<dynamic_repeat_length; j++){
+ dynamic_lengths[k+j] = dynamic_lengths[k-1];
+ }
+ k += j-1;
+ break;
+ case 17:
+ /* get repeat length */
+ read_bits_from_stream(stream,
+ iter, bit_iter, 3, &dynamic_repeat_length);
+ dynamic_repeat_length += 3;
+ for (j=0; j<dynamic_repeat_length; j++){
+ dynamic_lengths[k+j] = 0;
+ }
+ k += j-1;
+ break;
+ case 18:
+ /* get repeat length */
+ read_bits_from_stream(stream,
+ iter, bit_iter, 7, &dynamic_repeat_length);
+ dynamic_repeat_length += 11;
+ for (j=0; j<dynamic_repeat_length; j++){
+ dynamic_lengths[k+j] = 0;
+ }
+ k += j-1;
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ * This function creates a tree given the necessary tree information.
+ *
+ * @param max_bits (IN) The maximum number of bits for any code
+ * @param num_codes (IN) The number of codes
+ * @param code_lengths (IN) The code lengths
+ * @param extra_bits (IN) The number of extra bits for each huffman code
+ * @param values (IN) The values for the huffman code
+ * @param real_values (IN) The real values for the huffman code
+ * @param tree (OUT) The resulting huffman tree.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int create_tree(
+ unsigned long max_bits,
+ unsigned long num_codes,
+ unsigned long *code_lengths,
+ unsigned long *extra_bits,
+ unsigned long *values,
+ unsigned long *real_values,
+ huffman_node **tree) {
+
+ unsigned long *clc_count;
+ unsigned long *clc_next_code;
+ unsigned long *codes;
+ unsigned long clc_code;
+ unsigned long k;
+ huffman_node *cur_node;
+ huffman_node *new_node;
+
+ if (!tree) {
+ EMGD_ERROR("Bad tree pointer.");
+ return 1;
+ }
+
+ /* Step 1: Count the number of codes for each code length */
+ clc_count = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * (max_bits+1));
+ if (!clc_count) {
+ EMGD_ERROR("Out of memory.");
+ return 1;
+ }
+ OS_MEMSET(clc_count, 0, sizeof(unsigned long) * (max_bits+1));
+
+ for (k=0; k<num_codes; k++){
+ clc_count[code_lengths[k]]++;
+ }
+
+ /* Step 2: Get numerical value of smallest code for each code length */
+ clc_next_code = (unsigned long *)vmalloc(
+ sizeof(unsigned long) * (max_bits+1));
+ if (!clc_next_code) {
+ EMGD_ERROR("Out of memory.");
+ return 1;
+ }
+ OS_MEMSET(clc_next_code, 0, sizeof(unsigned long) * (max_bits+1));
+
+ clc_code = 0;
+ clc_next_code[0] = 2;
+ for (k=1; k<=max_bits; k++){
+ clc_code = (clc_code + clc_count[k-1]) << 1;
+ clc_next_code[k] = clc_code;
+ }
+
+ /* Step 3: Assign numerical values to all codes */
+ codes = (unsigned long *)vmalloc(sizeof(unsigned long) * num_codes);
+ if (!codes) {
+ EMGD_ERROR("Out of memory.");
+ return 1;
+ }
+ OS_MEMSET(codes, 0, sizeof(unsigned long) * num_codes);
+
+ for (k=0; k<num_codes; k++){
+ if (code_lengths[k] > 0){
+ codes[k] = clc_next_code[code_lengths[k]]++;
+
+ /* Add this node to the code length tree */
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory.");
+ return 1;
+ }
+
+ new_node->extra_bits = (unsigned char)extra_bits[k];
+ new_node->value = values[k];
+ new_node->real = real_values[k];
+ cur_node = *tree;
+ add_node(&cur_node, new_node, codes[k], code_lengths[k]);
+ }
+ }
+
+ vfree(clc_count);
+ vfree(clc_next_code);
+ vfree(codes);
+ return 0;
+}
+
+
+/*
+ * This function recursively frees a huffman node and all its sub nodes.
+ * First we free any sub nodes, then we free itself.
+ *
+ * @param node (IN) The huffman node to free.
+ */
+void free_node(huffman_node *node) {
+ if (node->leaf[0]) {
+ free_node((huffman_node *)(node->leaf[0]));
+ }
+ if (node->leaf[1]) {
+ free_node((huffman_node *)(node->leaf[1]));
+ }
+ kfree(node);
+}
+
+
+/*
+ * This function gets a huffman code by traversing through a bit
+ * stream as if those are directions for traversling through
+ * a binary tree. When we hit a leaf node, we have our value.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ * are reading.
+ * @param tree (IN) This is the huffman tree.
+ * @param final_node (OUT) The final leaf node we have reached.
+ */
+void get_huffman_code(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **tree,
+ huffman_node **final_node){
+
+ *final_node = *tree;
+ while ((*final_node)->leaf[0] || (*final_node)->leaf[1]) {
+ (*final_node) = (huffman_node *)(*final_node)->
+ leaf[((stream[*iter] >> *bit_iter) & 1)];
+
+ if (++(*bit_iter) == 8) {
+ (*iter)++;
+ (*bit_iter) = 0;
+ }
+ }
+}
+
+
+/*
+ * This function adds a node into a tree.
+ *
+ * @param tree (IN/OUT) This is the tree's root to which we'll be adding a
+ * node.
+ * @param node (IN) This is the node we'll be adding.
+ * @param code (IN) This is the code which will be used as a map to determine
+ * where the new node goes on the tree.
+ * @param code_length (IN) This is the code length for the code passed in.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int add_node(
+ huffman_node **tree,
+ huffman_node *node,
+ unsigned long code,
+ unsigned long code_length){
+
+ huffman_node *new_node;
+
+ if (!(*tree)) {
+ EMGD_ERROR("Invalid tree pointer.");
+ return 1;
+ }
+
+ if (code_length > 1){
+
+ /* Build a leaf node if it doesn't exist */
+ if (!(*tree)->leaf[(code >> (code_length-1)) & 1]){
+ new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+ if (!new_node) {
+ EMGD_ERROR("Out of memory");
+ return 1;
+ }
+
+ (*tree)->leaf[(code >> (code_length-1)) & 1] =
+ (struct huffman_node *)new_node;
+ (*tree) = new_node;
+ } else {
+ (*tree) =
+ (huffman_node *)(*tree)->leaf[(code >> (code_length-1)) & 1];
+ }
+
+ /* Recursively add the tree node */
+ add_node(&(*tree), node, code, --code_length);
+
+ } else {
+ /* This is where our leaf node belongs */
+ (*tree)->leaf[code & 1] = (struct huffman_node *)node;
+ }
+ return 0;
+}
+
+
+/*
+ * This function reads a 4 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_int_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned long *value){
+
+ *value = stream[*iter] << 24 |
+ stream[(*iter)+1] << 16 |
+ stream[(*iter)+2] << 8 |
+ stream[(*iter)+3];
+ *iter += 4;
+ return 0;
+}
+
+
+/*
+ * This function reads a 2 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_short_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned short *value){
+
+ *value = stream[(*iter)] << 8 |
+ stream[(*iter)+1];
+ *iter += 2;
+ return 0;
+}
+
+
+/*
+ * This function reads a 1 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_char_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *value){
+
+ *value = stream[*iter];
+ (*iter)++;
+
+ return 0;
+}
+
+
+/*
+ * This function reads a given number of bits from a given stream.
+ * This does not assume the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param bit_iter (IN/OUT) The stream's bit iterator.
+ * @param num_bits (IN) The number of bits to read.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_bits_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ unsigned long num_bits,
+ unsigned long *value){
+
+ unsigned long i;
+ *value = 0;
+
+ for (i=0; i<num_bits; i++){
+ *value += read_bit_from_stream(stream, iter, bit_iter) << i;
+ }
+
+ return 0;
+}
+
+
+/*
+ * This function reads a single bit from a given stream.
+ * This does not assume the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param bit_iter (IN/OUT) The stream's bit iterator.
+ *
+ * @return The bit value read.
+ */
+unsigned int read_bit_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter){
+
+ unsigned int result = 0;
+
+ /* get our bit */
+ result = (stream[*iter] >> *bit_iter) & 1;
+
+ /* This is faster than above */
+ if (++(*bit_iter) == 8) {
+ (*iter)++;
+ (*bit_iter) = 0;
+ }
+
+ return result;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
new file mode 100755
index 0000000..5fac725
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
@@ -0,0 +1,280 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: splash_screen.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the Intel Embedded Graphics EFI Driver Splash Screen header file.
+ * This file contains data structures pertinent to showing a splash screen
+ * with a customizable icon.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SPLASH_SCREEN_H
+#define _SPLASH_SCREEN_H
+
+#include <user_config.h>
+
+#define CONV_16_TO_32_BIT(a) (0xFF000000 | ((a & 0xF800)<<8) |\
+ ((a & 0x7E0)<<5) | (a & 0x1F)<<3)
+#define CONV_GS_4_TO_32(a) (0xFF000000 | ((a)<<20) | ((a)<<16) |\
+ ((a)<<12) | ((a)<<8) | ((a)<<4) | ((a)))
+
+#define CONV_GS_2_TO_32(a) (0xFF000000 | ((a)<<22) | ((a)<<20) | ((a)<<18) |\
+ ((a)<<16) | ((a)<<14) | ((a)<<12) | ((a)<<10) |\
+ ((a)<<8) | ((a)<<6) | ((a)<<4) | ((a)<<2) | ((a)))
+
+#define CONV_GS_1_TO_32(a) (0xFF000000 | ((a)<<23) | ((a)<<22) | ((a)<<21) |\
+ ((a)<<20) | ((a)<<19) | ((a)<<18) | ((a)<<17) |\
+ ((a)<<16) | ((a)<<15) | ((a)<<14) | ((a)<<13) |\
+ ((a)<<12) | ((a)<<11) | ((a)<<10) | ((a)<<9) |\
+ ((a)<<8) | ((a)<<7) | ((a)<<6) | ((a)<<5) | ((a)<<4) |\
+ ((a)<<3) | ((a)<<2) | ((a)<<1) | ((a)))
+
+/* Colour_type options */
+#define COLOR_GREY 0
+#define COLOR_TRUE 2
+#define COLOR_INDEXED 3
+#define COLOR_GREY_ALPHA 4
+#define COLOR_TRUE_ALPHA 6
+
+#define CONV_GS_4_TO_32(a) (0xFF000000 | ((a)<<20) | ((a)<<16) | ((a)<<12) |\
+ ((a)<<8) | ((a)<<4) | ((a)))
+
+#define CONV_GS_2_TO_32(a) (0xFF000000 | ((a)<<22) | ((a)<<20) | ((a)<<18) |\
+ ((a)<<16) | ((a)<<14) | ((a)<<12) | ((a)<<10) |\
+ ((a)<<8) | ((a)<<6) | ((a)<<4) | ((a)<<2) | ((a)))
+
+#define CONV_GS_1_TO_32(a) (0xFF000000 | ((a)<<23) | ((a)<<22) | ((a)<<21) |\
+ ((a)<<20) | ((a)<<19) | ((a)<<18) | ((a)<<17) |\
+ ((a)<<16) | ((a)<<15) | ((a)<<14) | ((a)<<13) |\
+ ((a)<<12) | ((a)<<11) | ((a)<<10) | ((a)<<9) |\
+ ((a)<<8) | ((a)<<7) | ((a)<<6) | ((a)<<5) | ((a)<<4) |\
+ ((a)<<3) | ((a)<<2) | ((a)<<1) | ((a)))
+
+#define PNG_HEADER_SIZE 8
+#define PNG_CRC_SIZE 4
+#define CLC_MAX_BITS 7
+#define CLC_NUM_CODES 19
+#define LEN_MAX_BITS 15
+#define LEN_NUM_CODES 288
+#define DIST_MAX_BITS 15
+#define DIST_NUM_CODES 32
+#define LEN_NUM_DISTINCT_EXTRA_BITS 7
+#define DIST_NUM_DISTINCT_EXTRA_BITS 14
+#define LEN_START_REAL_VALUES 257
+#define DIST_START_REAL_VALUES 1
+#define DISPLAY_START 8365
+#define DISPLAY_MAX 8372
+#define DISPLAY_MAX2 8372
+
+/* Chunk types */
+#define CHUNK_IHDR 0x49484452
+#define CHUNK_SRGB 0x73524742
+#define CHUNK_PHYS 0x70485973
+#define CHUNK_TIME 0x74494D45
+#define CHUNK_BKGD 0x624B4744
+#define CHUNK_TRNS 0x74524E53
+#define CHUNK_CHRM 0x6348524D
+#define CHUNK_GAMA 0x67414D41
+#define CHUNK_ICCP 0x69434350
+#define CHUNK_SBIT 0x73424954
+#define CHUNK_TEXT 0x74455874
+#define CHUNK_ZTXT 0x7A545874
+#define CHUNK_ITXT 0x69545874
+#define CHUNK_HIST 0x68495354
+#define CHUNK_SPLT 0x73504C54
+#define CHUNK_PLTE 0x504C5445
+#define CHUNK_IDAT 0x49444154
+#define CHUNK_IEND 0x49454E44
+
+/* APNG Chunks */
+#define CHUNK_ACTL 0x6163544C
+#define CHUNK_FCTL 0x6663544C
+#define CHUNK_FDAT 0x66644154
+
+/* Colour_type options */
+#define COLOR_GREY 0
+#define COLOR_TRUE 2
+#define COLOR_INDEXED 3
+#define COLOR_GREY_ALPHA 4
+#define COLOR_TRUE_ALPHA 6
+
+/* APNG dispose_op codes */
+#define APNG_DISPOSE_OP_NONE 0
+#define APNG_DISPOSE_OP_BACKGROUND 1
+#define APNG_DISPOSE_OP_PREVIOUS 2
+
+/* APNG blend_op codes */
+#define APNG_BLEND_OP_SOURCE 0
+#define APNG_BLEND_OP_OVER 1
+
+typedef struct _bitmap_header {
+ /* What is the widht and height of the bitmap */
+ unsigned short width;
+ unsigned short height;
+ /* If Negative, from bottom right, how much to go left by */
+ /* If Positive, from top left, how much to go right by */
+ short x_coord;
+ /* If Negative, from bottom right, how much to go up by */
+ /* If Positive, from top left, how much to go down by */
+ short y_coord;
+} bitmap_header;
+
+typedef struct _png_header {
+ unsigned long width;
+ unsigned long height;
+ unsigned long x_offset;
+ unsigned long y_offset;
+ unsigned char bit_depth;
+ unsigned char colour_type;
+ unsigned char compression_method;
+ unsigned char filter_method;
+ unsigned char interlace_method;
+ unsigned long bpp;
+ unsigned long bytes_pp;
+ unsigned long bytes_pl;
+ unsigned long background;
+ unsigned char background_r;
+ unsigned char background_g;
+ unsigned char background_b;
+ unsigned long *image_palette;
+ unsigned long using_transparency;
+ unsigned short transparency_r;
+ unsigned short transparency_g;
+ unsigned short transparency_b;
+} png_header;
+
+typedef struct _png_frame {
+ unsigned long *output;
+ unsigned long size;
+ unsigned long width;
+ unsigned long height;
+ unsigned long x_offset;
+ unsigned long y_offset;
+ unsigned long bytes_pp;
+ unsigned long bytes_pl;
+ unsigned long delay;
+ unsigned char dispose_op;
+ unsigned char blend_op;
+} png_frame;
+
+typedef struct _huffman_node {
+ unsigned long value;
+ unsigned long real;
+ unsigned char extra_bits;
+ struct huffman_node *leaf[2];
+} huffman_node;
+
+void display_png_frame(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ png_header image_header,
+ png_frame *frame,
+ unsigned long prev_dispose_op);
+void decode_png_data(
+ png_header *image_header,
+ unsigned char *input_data,
+ png_frame *frame);
+int create_tree(
+ unsigned long max_bits,
+ unsigned long num_codes,
+ unsigned long *code_lengths,
+ unsigned long *extra_bits,
+ unsigned long *values,
+ unsigned long *real_values,
+ huffman_node **tree);
+void free_node(huffman_node *node);
+void display_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data);
+void display_bmp_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data);
+void display_png_splash_screen(
+ igd_framebuffer_info_t *fb_info,
+ unsigned char *fb,
+ emgd_drm_splash_screen_t *ss_data);
+void decompress_huffman(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **length_tree,
+ huffman_node **distance_tree,
+ unsigned char *output,
+ unsigned long *output_iter);
+void build_static_huffman_tree(
+ huffman_node **length_tree,
+ huffman_node **distance_tree);
+void build_dynamic_huffman_tree(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **length_tree,
+ huffman_node **distance_tree);
+void get_code_lengths(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **code_length_tree,
+ unsigned long num_lengths,
+ unsigned long *dynamic_lengths);
+void get_huffman_code(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ huffman_node **tree,
+ huffman_node **final_node);
+int add_node(
+ huffman_node **tree,
+ huffman_node *node,
+ unsigned long code,
+ unsigned long code_length);
+int read_int_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned long *value);
+int read_short_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned short *value);
+int read_char_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *value);
+int read_bits_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter,
+ unsigned long num_bits,
+ unsigned long *value);
+unsigned int read_bit_from_stream(
+ unsigned char *stream,
+ unsigned long *iter,
+ unsigned char *bit_iter);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/user_config.c b/drivers/gpu/drm/emgd/emgd/drm/user_config.c
new file mode 100755
index 0000000..be7c70b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/user_config.c
@@ -0,0 +1,257 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: user_config.c
+ * $Revision: 1.24 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * A file that contains the initial display configuration information of the
+ * EMGD kernel module. A user can edit this file in order to affect the way
+ * that the kernel initially configures the displays. This file is compiled
+ * into the EMGD kernel module.
+ *-----------------------------------------------------------------------------
+ */
+#include "user_config.h"
+
+#warning ****
+#warning **** This driver has NOT been configured for your system. You are
+#warning **** building with a sample user_config.c configuration that may or
+#warning **** may not meet your needs. It is recommended that you run CED to
+#warning **** generate an appropriate configuration or see the User Guide
+#warning **** for more information about driver configuration.
+#warning ****
+
+
+/*
+ * One array of igd_display_info_t structures should exist for each port that
+ * needs to provide a DTD list. Each igd_display_info_t contains the DTD
+ * information for a given resolution/refresh-rate. This is especially needed
+ * for analog/VGA ports.
+ */
+
+#define TUNNELCREEK 1
+#define POULSBO 0
+
+#if TUNNELCREEK
+static igd_display_info_t dtd_config1_port4_dtdlist[] = {
+ {
+ 1366, /* Width */
+ 768, /* Height */
+ 60, /* Refresh Rate */
+ 72300, /* Dot Clock */
+ 1525, /* Horizontal Total (horizontal synch end) */
+ 1365, /* Horizontal Blank Start (h_active-1) */
+ 1525, /* Horizontal Blank End (start + h_blank) */
+ 1413, /* Horizontal Sync Start (h_active+h_synch-1) */
+ 1445, /* Horizontal Sync End (start + h_syncp) */
+ 789, /* Vertical Total (Vertical synch end) */
+ 767, /* Vertical Blank Start (v_active-1) */
+ 789, /* Vertical Blank End (start + v_blank) */
+ 770, /* Vertical Sync Start (v_active+v_synch-1) */
+ 775, /* Vertical Sync End (start + v_synchp) */
+ 0, /* Mode Number */
+ 0x20000, /* Flags */
+ 0, /* X Offset */
+ 0, /* Y Offset */
+ NULL, /* pd extension pointer */
+ 0, 0 /* mode extension pointer */
+ },
+};
+#endif
+
+#if POULSBO
+static igd_display_info_t dtd_config1_port4_dtdlist[] = {
+ {
+ 1024, /* Width */
+ 768, /* Height */
+ 60, /* Refresh Rate */
+ 65000, /* Dot Clock (in KHz) */
+ 1343, /* Horizontal Total (horizontal synch end) */
+ 1023, /* Horizontal Blank Start (h_active-1) */
+ 1343, /* Horizontal Blank End (start + h_blank) */
+ 1047, /* Horizontal Sync Start (h_active+h_synch-1) */
+ 1183, /* Horizontal Sync End (start + h_syncp) */
+ 805, /* Vertical Total (Vertical synch end) */
+ 767, /* Vertical Blank Start (v_active-1) */
+ 805, /* Vertical Blank End (start + v_blank) */
+ 770, /* Vertical Sync Start (v_active+v_synch-1) */
+ 776, /* Vertical Sync End (start + v_synchp) */
+ 0, /* Mode Number */
+ 0x20000, /* Flags */
+ 0, /* X Offset */
+ 0, /* Y Offset */
+ NULL, /* pd extension pointer */
+ 0, 0 /* mode extension pointer */
+ },
+};
+#endif
+
+static igd_param_attr_t attrs_config1_port4[] = {
+ {0x46, 100},
+#if POULSBO
+ {0x1a, 24},
+#endif
+#if TUNNELCREEK
+ {0x47, 20300},
+#endif
+};
+
+static emgd_drm_splash_screen_t splash_screen_data = {
+ 0x000000, /* bg_color */
+ 0, /* x */
+ 0, /* y */
+ 0, /* width */
+ 0, /* height */
+};
+
+static emgd_drm_splash_video_t splash_video_data = {
+ 0, /* offset */
+ 0, /* pixel_format */
+ 0, /* src_width */
+ 0, /* src_height */
+ 0, /* src_pitch */
+ 0, /* dst_x */
+ 0, /* dst_y */
+ 0, /* dst_width */
+ 0, /* dst_height */
+};
+
+static igd_param_t config_params_config1 = {
+ 1*256*1024, /* Page request */
+ 0, /* Max frame buffer size */
+ 1, /* Preserve registers */
+ 0x6, /* Display flags */
+ { 4, 2, 0, 0, 0 }, /* Display port order */
+ { /* Display Params */
+ { /* Port */
+ 4, /* Display port number */
+ 0x180, /* Parameters present */
+ 0x0, /* EDID flag */
+ 0x5, /* Flags when EDID is available */
+ 0x5, /* Flags when EDID is not available */
+ 0, /* DDC GPIO pins */
+ 0, /* DDC speed */
+ 0, /* DDC DAB */
+ 0, /* I2C GPIO pins */
+ 0, /* I2C speed */
+ 0, /* I2C DAB */
+ { /* Flat Panel Info */
+ 0, /* Flat Panel width */
+ 0, /* Flat Panel height */
+ 0, /* Flat Panel power method */
+ 0, /* VDD active & DVO clock/data active */
+ 0, /* DVO clock/data active & backlight enable */
+ 0, /* backlight disable & DVO clock/data inactive */
+ 0, /* DVO clock/data inactive & VDD inactive */
+ 0 /* VDD inactive & VDD active */
+ },
+ { /* DTD Info */
+ sizeof(dtd_config1_port4_dtdlist)/sizeof(igd_display_info_t), /* Number of DTDs */
+ dtd_config1_port4_dtdlist /* DTD name */
+ },
+ { /* Attribute Info */
+ sizeof(attrs_config1_port4)/sizeof(igd_param_attr_t), /* Number of attributes */
+ attrs_config1_port4 /* Attr name */
+ }
+ },
+ { /* Port */
+ 2, /* Display port number */
+ 0x0, /* Parameters present */
+ 0x0, /* EDID flag */
+ 0x5, /* Flags when EDID is available */
+ 0x5, /* Flags when EDID is not available */
+ 0, /* DDC GPIO pins */
+ 0, /* DDC speed */
+ 0, /* DDC DAB */
+ 0, /* I2C GPIO pins */
+ 0, /* I2C speed */
+ 0, /* I2C DAB */
+ { /* Flat Panel Info */
+ 0, /* Flat Panel width */
+ 0, /* Flat Panel height */
+ 0, /* Flat Panel power method */
+ 0, /* VDD active & DVO clock/data active */
+ 0, /* DVO clock/data active & backlight enable */
+ 0, /* backlight disable & DVO clock/data inactive */
+ 0, /* DVO clock/data inactive & VDD inactive */
+ 0 /* VDD inactive & VDD active */
+ },
+ { /* DTD Info */
+ 0, NULL
+ },
+ { /* Attribute Info */
+ 0, NULL
+ }
+ },
+ },
+ 0, /* 24-bit RGB color that framebuffer is cleared to */
+ 1, /* Quickboot (1 = enabled) */
+ 0, /* Quickboot seamless (1 = enabled) */
+ 0, /* Quickboot video input (1 = enabled) */
+ 0 /* Polling (1 = override interrupt support and use polling) */
+};
+
+igd_param_t *config_params = {&config_params_config1};
+
+/*
+ * The emgd_drm_config_t structure is the main configuration structure
+ * for the EMGD kernel module.
+ */
+emgd_drm_config_t config_drm = {
+ 0, /* Whether to initialize the display at EMGD module startup time
+ * (corresponds to the "init" module parameter)
+ */
+ 1, /* The display configuration to use if initializing the display
+ * (corresponds to the "init" module parameter), where:
+ * - 1 = Single port/display
+ * - 2 = Cloned port/display (e.g. LVDS + CRT with different timings)
+ * - 4 = Twin ports/displays (e.g. LVDS + CRT with same timings)
+ * Note: Twin is NOT CURRENTLY SUPPORTED
+ * - 8 = Extended displays (e.g. LVDS + CRT displaying different images)
+ */
+ 1366,/* Display width to use if initializing the display
+ * (corresponds to the "width" module parameter)
+ */
+ 768,/* Display height to use if initializing the display
+ * (corresponds to the "height" module parameter)
+ */
+ 60, /* Display refresh rate to use if initializing the display
+ * (corresponds to the "refresh" module parameter)
+ */
+ 0, /* KMS */
+ 0, /* ovl_brightness */
+ 0, /* ovl_contrast */
+ 0, /* ovl_saturation */
+ 0, /* ovl_hue */
+ 0, /* ovl_gamma_red */
+ 0, /* ovl_gamma_green */
+ 0, /* ovl_gamma_blue */
+ &splash_screen_data,
+ &splash_video_data,
+ &config_params /* driver parameters from above */
+#ifdef SUPPORT_V2G_CAMERA
+ ,
+ 0 /* 1 - Enable v2g camera. 0 - Disable v2g camera*/
+#endif
+};
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/user_config.h b/drivers/gpu/drm/emgd/emgd/drm/user_config.h
new file mode 100755
index 0000000..3ab48bf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/user_config.h
@@ -0,0 +1,119 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: user_config.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Data structure containing the initial display configuration information of
+ * the EMGD kernel module.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _USER_CONFIG_H_
+#define _USER_CONFIG_H_
+
+#include "igd_init.h"
+#include "igd_mode.h"
+
+/*
+ * Splash Screen data provided by the user.
+ */
+typedef struct _emgd_drm_splash_screen {
+ unsigned long bg_color;
+ unsigned long x;
+ unsigned long y;
+ unsigned long width;
+ unsigned long height;
+} emgd_drm_splash_screen_t;
+
+/*
+ * Splash Video data provided by the user.
+ */
+typedef struct _emgd_drm_splash_video {
+ unsigned long offset;
+ unsigned long pixel_format;
+ unsigned long src_width;
+ unsigned long src_height;
+ unsigned long src_pitch;
+ unsigned long dst_x;
+ unsigned long dst_y;
+ unsigned long dst_width;
+ unsigned long dst_height;
+} emgd_drm_splash_video_t;
+
+/**
+ * User-configurable parameters. This structure is the basis for the
+ * user_config.c" file, which allows compile-time customization of the EMGD DRM
+ * module.
+ *
+ * Besides the igd_param_t values, the other options in this structure
+ * correspond to EMGD module parameters of the same name. Most are only
+ * applicable if the init option is non-zero. There is one additional module
+ * parameter ("portorder") that corresponds to the port_order member of the
+ * igd_param_t structure.
+ */
+typedef struct _emgd_drm_config {
+ /**
+ * Whether the EMGD kernel/DRM module should initialize the display at
+ * startup time (1=yes, 0=no).
+ */
+ int init;
+ /** The display configuration to use if initializing the display. */
+ int dc;
+ /** The width to use if initializing the display. */
+ int width;
+ /** The height to use if initializing the display. */
+ int height;
+ /** The refresh rate to use if initializing the display. */
+ int refresh;
+ /** Enable Kernel Mode Set */
+ int kms;
+ /** Overlay Brightness */
+ unsigned long ovl_brightness;
+ /** Overlay Contrast */
+ unsigned long ovl_contrast;
+ /** Overlay Saturation */
+ unsigned long ovl_saturation;
+ /** Overlay Hue */
+ unsigned long ovl_hue;
+ /** Overlay Gamma Correction - Red */
+ unsigned long ovl_gamma_red;
+ /** Overlay Gamma Correction - Green */
+ unsigned long ovl_gamma_green;
+ /** Overlay Gamma Correction - Blue */
+ unsigned long ovl_gamma_blue;
+ /** The splash screen data if specified by the user. */
+ emgd_drm_splash_screen_t *ss_data;
+ /** The splash video data if specified by the user. */
+ emgd_drm_splash_video_t *sv_data;
+ /** Array of other parameters (one per configid), used by the hardware
+ * abstraction layer code.
+ */
+ igd_param_t **hal_params;
+ /** Enable V2G Camera Module **/
+#ifdef SUPPORT_V2G_CAMERA
+ int v2g;
+#endif
+} emgd_drm_config_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/gmm/gmm.c b/drivers/gpu/drm/emgd/emgd/gmm/gmm.c
new file mode 100755
index 0000000..04e4ed1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/gmm/gmm.c
@@ -0,0 +1,1421 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gmm.c
+ * $Revision: 1.53 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Very basic video memory managment functions required by HAL.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.gmm
+
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memlist.h>
+#include <io.h>
+#include <memory.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/agp.h>
+#include "igd_gmm.h"
+
+#define AGP_PHYS_MEMORY 2 /* Physical contigous memory */
+struct emgd_ci_surface_t{
+ unsigned int used;
+ unsigned int v4l2_offset;
+ unsigned int virt;
+ unsigned long size;
+ unsigned long gtt_offset;
+ unsigned long vbufqueue_handle;
+ };
+#define MAX_CI_LIST_SIZE 25
+struct emgd_ci_surface_t ci_surfaces[MAX_CI_LIST_SIZE];
+
+
+gmm_context_t gmm_context;
+
+gmm_chunk_t *gmm_get_chunk(igd_context_t *context, unsigned long offset);
+static int gmm_flush_cache(void);
+static int gmm_alloc_linear_surface(unsigned long *offset,
+ unsigned long pixel_format,
+ unsigned int *width,
+ unsigned int *height,
+ unsigned int *pitch,
+ unsigned long *size,
+ unsigned long type,
+ unsigned long flags,
+ unsigned long phys);
+
+static int gmm_alloc_chunk_space(gmm_context_t *gmm_context,
+ unsigned long *offset,
+ unsigned long size,
+ unsigned long phys,
+ unsigned long flags);
+
+static int gmm_import_pages(void **pagelist,
+ unsigned long *gtt_offset,
+ unsigned long numpages);
+
+static int gmm_get_page_list(unsigned long offset,
+ unsigned long **pages,
+ unsigned long *page_cnt);
+
+gmm_mem_buffer_t *emgd_alloc_pages(unsigned long num_pages, int type);
+void emgd_free_pages(gmm_mem_buffer_t *mem);
+void emgd_gtt_remove(igd_context_t *context, gmm_mem_buffer_t *mem,
+ unsigned long offset);
+void emgd_gtt_insert(igd_context_t *context, gmm_mem_buffer_t *mem,
+ unsigned long offset);
+
+
+static int gmm_map_ci(unsigned long *gtt_offset,
+ unsigned long ci_param,
+ unsigned long *virt_addr,
+ unsigned int map_method,
+ unsigned long size);
+
+
+static int gmm_unmap_ci(unsigned long virt_addr);
+
+static void gmm_free(unsigned long offset)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_DEBUG("Enter gmm_free(0x%lx)", offset);
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if (chunk->offset == offset) {
+ switch (chunk->usage) {
+ case FREE_ALLOCATED:
+ EMGD_DEBUG("WARNING: The chunk 0x%lx is already freed", offset);
+ break;
+ case INUSE_IMPORTED:
+ case FREE_IMPORTED:
+ EMGD_DEBUG("WARNING: The chunk 0x%lx was allocated externally", offset);
+ return;
+ case INUSE_ALLOCATED:
+ EMGD_DEBUG("Freeing the chunk 0x%lx", offset);
+ break;
+ default:
+ EMGD_DEBUG("Unknown usage %d for chunk 0x%lx. Memory manager corrupt?",
+ chunk->usage, offset);
+ break;
+ }
+
+ /*
+ * What to do if the ref count is > 0? Unmapping is
+ * probably the right thing since nothing should try
+ * to use this. If something does, it should probably
+ * fail.
+ */
+ if (chunk->ref_cnt > 0 && chunk->addr) {
+ EMGD_DEBUG("WARNING: The chunk 0x%lx is mapped", offset);
+ /* chunk->addr will be freed by gmm_shutdown */
+ }
+
+
+ /* Free the array of page address, if applicable: */
+ if (chunk->page_addresses != NULL) {
+ EMGD_DEBUG("About to free chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ OS_FREE(chunk->page_addresses);
+ chunk->page_addresses = NULL;
+ }
+
+ chunk->usage = FREE_ALLOCATED; /* mark as free */
+ return;
+ }
+ chunk = chunk->next;
+ }
+
+ EMGD_ERROR("gmm_free() did not find the chunk 0x%lx to free", offset);
+ return;
+}
+
+static void gmm_release_import(unsigned long offset)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_DEBUG("Enter gmm_release_import(0x%lx)", offset);
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if (chunk->offset == offset) {
+ switch (chunk->usage) {
+ case FREE_ALLOCATED:
+ case INUSE_ALLOCATED:
+ EMGD_DEBUG("WARNING: The chunk 0x%lx was not an imported chunk", offset);
+ break;
+ case INUSE_IMPORTED:
+ EMGD_DEBUG("Releasing the chunk 0x%lx", offset);
+ break;
+ case FREE_IMPORTED:
+ EMGD_DEBUG("WARNING: The chunk 0x%lx has already been released", offset);
+ return;
+ default:
+ EMGD_DEBUG("Unknown usage %d for chunk 0x%lx. Memory manager corrupt?",
+ chunk->usage, offset);
+ break;
+ }
+
+ /*
+ * What to do if the ref count is > 0? Unmapping is
+ * probably the right thing since nothing should try
+ * to use this. If something does, it should probably
+ * fail.
+ */
+ if (chunk->ref_cnt > 0) {
+ EMGD_DEBUG("WARNING: The chunk 0x%lx is mapped", offset);
+ chunk->ref_cnt = 0;
+ vunmap(chunk->addr);
+ chunk->addr = NULL;
+ }
+ /* Free the array of page address, if applicable: */
+ if (chunk->page_addresses != NULL) {
+ EMGD_DEBUG("About to free chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ OS_FREE(chunk->page_addresses);
+ chunk->page_addresses = NULL;
+ }
+
+ /* Zero out the gmm_mem_buffer_t */
+ OS_MEMSET(chunk->gtt_mem, 0, sizeof(gmm_mem_buffer_t));
+
+ /* Mark address space as free */
+ chunk->usage = FREE_IMPORTED;
+ return;
+ }
+ chunk = chunk->next;
+ }
+
+ EMGD_ERROR("gmm_free() did not find the chunk 0x%lx to free", offset);
+ return;
+}
+
+static int gmm_alloc_region(unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long flags)
+{
+ int ret;
+ unsigned long aligned_size;
+ unsigned long phys = 0;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: size=%lu, type=%d, flags=0x%lx", *size, type, flags);
+
+ *offset = 0;
+
+ switch(type) {
+ case IGD_GMM_REGION_TYPE_OVLREG:
+ flags |= IGD_GMM_REGION_ALIGN_MMAP;
+ phys = 1;
+ break;
+ case IGD_GMM_REGION_TYPE_OVLREG64:
+ flags |= IGD_GMM_REGION_ALIGN_64K;
+ phys = 1;
+ break;
+ case IGD_GMM_REGION_TYPE_HWSTATUS:
+ flags |= IGD_GMM_REGION_ALIGN_MMAP;
+ *size = 4096;
+ phys = 1;
+ break;
+ case IGD_GMM_REGION_TYPE_DMA:
+ flags |= IGD_GMM_REGION_ALIGN_MMAP;
+ break;
+ case IGD_GMM_REGION_TYPE_PERSISTENT:
+ flags |= IGD_GMM_REGION_ALIGN_MMAP;
+ break;
+ case IGD_GMM_REGION_TYPE_BPL:
+ flags |= IGD_GMM_REGION_ALIGN_MMAP;
+ phys = 1;
+ break;
+ case IGD_GMM_REGION_TYPE_CONTEXT:
+ flags |= IGD_GMM_REGION_ALIGN_CONTEXT | IGD_GMM_REGION_ALIGN_MMAP;
+ *size = 4096;
+ phys = 1;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid Region type requested: 0x%8.8x", type);
+ return -IGD_INVAL;
+ }
+
+ aligned_size = (*size + 4095) & ~4095;
+ EMGD_DEBUG("aligned_size=%lu", aligned_size);
+
+ do {
+ ret = gmm_alloc_chunk_space(&gmm_context, offset, aligned_size, phys,
+ flags);
+ } while ((ret == -IGD_ERROR_NOMEM) && gmm_flush_cache());
+
+ EMGD_DEBUG("EXIT Returning %d", ret);
+ return ret;
+}
+
+static int gmm_get_num_surface(unsigned long *count)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_TRACE_ENTER;
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ *count = 0;
+ while (chunk) {
+ (*count)++;
+ chunk = chunk->next;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+static int gmm_get_surface_list(unsigned long allocated_size,
+ unsigned long *list_size,
+ igd_surface_list_t **surface_list)
+{
+ gmm_chunk_t *chunk;
+ igd_surface_list_t *tmp_list;
+
+ EMGD_TRACE_ENTER;
+ gmm_get_num_surface(list_size);
+
+ if (*list_size > 0){
+ *surface_list = vmalloc(*list_size * sizeof(igd_surface_list_t));
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ tmp_list = *surface_list;
+
+ while (chunk){
+ tmp_list->offset = chunk->offset;
+ tmp_list->size = chunk->size;
+
+ chunk = chunk->next;
+ tmp_list++;
+ }
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+static int gmm_alloc_surface(unsigned long *offset,
+ unsigned long pixel_format,
+ unsigned int *width,
+ unsigned int *height,
+ unsigned int *pitch,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long *flags)
+{
+ int ret;
+ unsigned long phys;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: pixel_format=0x%08lx,", pixel_format);
+ EMGD_DEBUG(" width=%u, height=%u", *width, *height);
+ EMGD_DEBUG(" pitch=%u, type=%d, flags=0x%08lx", *pitch, type, *flags);
+
+ *offset = 0;
+ *size = 0;
+ if (! (*flags & IGD_MIN_PITCH)) {
+ *pitch = 0;
+ }
+
+ if (*flags & IGD_SURFACE_CURSOR) {
+ phys = 1;
+ } else {
+ phys = 0;
+ }
+
+ ret = gmm_alloc_linear_surface(offset, pixel_format, width, height, pitch,
+ size, type, *flags, phys);
+
+ EMGD_DEBUG("EXIT Returning %d", ret);
+ return ret;
+}
+
+
+/*
+ * Given an offset, find the chunk and return the physical address.
+ */
+static int gmm_virt_to_phys(unsigned long offset,
+ unsigned long *physical)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Looking for offset=0x%lx", offset);
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if (chunk->offset == offset) {
+ *physical = chunk->gtt_mem->physical;
+ EMGD_DEBUG("Physical address = 0x%08lx", *physical);
+ EMGD_TRACE_EXIT;
+ return 0;
+ }
+ chunk = chunk->next;
+ }
+
+ /* offset not found */
+ EMGD_ERROR_EXIT("Did not find offset (0x%lx); returning %d",
+ offset, -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+}
+
+
+static int gmm_flush_cache(void)
+{
+ EMGD_DEBUG("Enter gmm_flush_cache(), which is stubbed");
+ return 0;
+}
+
+static void gmm_save(igd_context_t *context, void **state)
+{
+ EMGD_DEBUG("Enter gmm_save(), which is stubbed");
+ return;
+}
+
+static void gmm_restore(igd_context_t *context, void *state)
+{
+ EMGD_DEBUG("Enter gmm_restore(), which is stubbed");
+ return;
+}
+
+/*
+ * Create a virtual address mapping for a block of video memory.
+ */
+static void *gmm_map(unsigned long offset)
+{
+ gmm_chunk_t *chunk;
+ struct page **page_map;
+ int i;
+ void *addr = NULL;
+ unsigned long num_pages;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: offset=0x%lx", offset);
+
+ chunk = gmm_get_chunk(gmm_context.context, offset);
+
+ if (chunk == NULL) {
+ printk(KERN_ERR"[EMGD] gmm_map: Failed to find chunk: 0x%lx\n", offset);
+ return NULL;
+ }
+
+ /*
+ * Check if this as been mapped already and return that map instead
+ * of remapping it.
+ */
+ chunk->ref_cnt++;
+ if (chunk->addr) {
+ EMGD_DEBUG("This chunk is already mapped!");
+ return chunk->addr;
+ }
+
+ /*
+ * Read the physical addresses of the allocation from the GTT
+ * and convert that to a page list.
+ */
+
+ num_pages = chunk->gtt_mem->page_count;
+ page_map = vmalloc(num_pages * sizeof(struct page *));
+ if (page_map == NULL) {
+ printk(KERN_ERR"[EMGD] gmm_map: vmalloc failed.\n");
+ return NULL;
+ }
+
+ for (i = 0; i < num_pages; i++) {
+ page_map[i] = chunk->gtt_mem->pages[i];
+ }
+
+ addr = vmap(page_map, num_pages, VM_MAP, PAGE_KERNEL_UC_MINUS);
+
+ vfree(page_map);
+ chunk->addr = addr;
+
+ EMGD_DEBUG("Mapped address = 0x%p", addr);
+ EMGD_TRACE_EXIT;
+
+ return addr;
+}
+
+
+static void gmm_unmap(void *addr)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameter: addr=0x%p", addr);
+
+ /* Look up the chunk that was mapped to this address */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if (chunk->addr == addr) {
+ EMGD_DEBUG("The chunk with addr=0x%p has the offset = 0x%08lx", addr,
+ chunk->offset);
+ chunk->ref_cnt--;
+ if (chunk->ref_cnt == 0) {
+ EMGD_DEBUG("About to call vunmap(0x%p)", addr);
+ vunmap(addr);
+ chunk->addr = NULL;
+ }
+ return;
+ }
+ chunk = chunk->next;
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+int gmm_init(igd_context_t *context,
+ unsigned long scratch_mem,
+ unsigned long max_fb_mem)
+{
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: scratch_mem=0x%lx, max_fb_mem=%lu",
+ scratch_mem, max_fb_mem);
+
+ context->dispatch.gmm_alloc_surface = gmm_alloc_surface;
+ context->dispatch.gmm_alloc_region = gmm_alloc_region;
+ context->dispatch.gmm_import_pages = gmm_import_pages;
+ context->dispatch.gmm_virt_to_phys = gmm_virt_to_phys;
+ context->dispatch.gmm_free = gmm_free;
+ context->dispatch.gmm_release_import = gmm_release_import;
+ context->dispatch.gmm_memstat = NULL;
+ context->dispatch.gmm_alloc_cached = NULL;
+ context->dispatch.gmm_free_cached = NULL;
+ context->dispatch.gmm_alloc_cached_region = NULL;
+ context->dispatch.gmm_free_cached_region = NULL;
+ context->dispatch.gmm_flush_cache = gmm_flush_cache;
+ context->dispatch.gmm_alloc_reservation = NULL;
+ context->dispatch.gmm_alloc_heap = NULL;
+ context->dispatch.gmm_alloc_heap_block = NULL;
+ context->dispatch.gmm_free_heap_block = NULL;
+ context->dispatch.gmm_get_heap_from_block = NULL;
+ context->dispatch.gmm_get_pvtheap_size = NULL;
+ context->dispatch.gmm_get_cache_mem = NULL;
+ context->dispatch.gmm_alloc_persistent_region = NULL;
+ context->dispatch.gmm_free_persistent_region = NULL;
+ context->dispatch.gmm_map = gmm_map;
+ context->dispatch.gmm_unmap = gmm_unmap;
+ context->dispatch.gmm_get_page_list = gmm_get_page_list;
+ context->dispatch.gmm_get_num_surface = gmm_get_num_surface;
+ context->dispatch.gmm_get_surface_list = gmm_get_surface_list;
+ context->dispatch.gmm_map_ci = gmm_map_ci;
+ context->dispatch.gmm_unmap_ci = gmm_unmap_ci;
+
+ context->mod_dispatch.gmm_save = gmm_save;
+ context->mod_dispatch.gmm_restore = gmm_restore;
+
+ gmm_context.context = context;
+ gmm_context.head_chunk = NULL;
+ gmm_context.tail_chunk = NULL;
+
+ /* Reserve memory for framebuffer ??? */
+
+ EMGD_DEBUG("EXIT Returning %d", 0);
+ return 0;
+}
+
+
+void gmm_shutdown(igd_context_t *context)
+{
+ gmm_chunk_t *chunk, *del;
+ struct drm_device *dev;
+
+ EMGD_TRACE_ENTER;
+
+ dev = (struct drm_device *)context->drm_dev;
+
+ /* Walk the chunk list */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ EMGD_DEBUG("process chunk at 0x%lx", chunk->offset);
+ if (chunk->usage == INUSE_ALLOCATED || chunk->usage == INUSE_IMPORTED) {
+ EMGD_ERROR("Chunk at 0x%lx not properly freed", chunk->offset);
+ }
+
+ if (chunk->addr != NULL) {
+ vunmap(chunk->addr);
+ }
+
+ if (chunk->bound) {
+ emgd_gtt_remove(context, chunk->gtt_mem, chunk->offset);
+ }
+
+ if (chunk->usage == INUSE_ALLOCATED || chunk->usage == FREE_ALLOCATED) {
+ emgd_free_pages(chunk->gtt_mem);
+ }
+
+ /* Free the array of page address, if applicable: */
+ if (chunk->page_addresses != NULL) {
+ EMGD_DEBUG("About to free chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ OS_FREE(chunk->page_addresses);
+ }
+
+ /* Free the chunk */
+ del = chunk;
+ chunk = chunk->next;
+ OS_FREE(del);
+ }
+
+ EMGD_TRACE_EXIT;
+ return;
+}
+
+gmm_chunk_t *gmm_get_chunk(igd_context_t *context, unsigned long offset)
+{
+ gmm_chunk_t *chunk;
+
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if (chunk->offset == offset) {
+ return chunk;
+ }
+ chunk = chunk->next;
+ }
+
+ printk(KERN_ERR "[EMGD] gmm_get_chunk: Failed to find chunk 0x%lx\n",
+ offset);
+ return NULL;
+}
+
+
+
+static int gmm_alloc_linear_surface(unsigned long *offset,
+ unsigned long pixel_format,
+ unsigned int *width,
+ unsigned int *height,
+ unsigned int *pitch,
+ unsigned long *size,
+ unsigned long type,
+ unsigned long flags,
+ unsigned long phys)
+{
+ int ret;
+ unsigned long align;
+ unsigned long min_pitch;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: pixel_format=0x%08lx,", pixel_format);
+ EMGD_DEBUG(" width=%u, height=%u", *width, *height);
+ EMGD_DEBUG(" pitch=%u, size=%lu, type=%lu", *pitch, *size, type);
+ EMGD_DEBUG(" flags=0x%08lx; phys=%lu", flags, phys);
+
+ /* Validate surface */
+ if (! *width) {
+ *width = 1;
+ }
+
+ if (! *height) {
+ *height = 1;
+ }
+
+ /* Set the minimum surface pitch */
+ min_pitch = (IGD_PF_DEPTH(pixel_format) * *width) >> 3;
+ if (min_pitch < *pitch) {
+ min_pitch = *pitch;
+ }
+
+ /* Pitch for both PLB and TNC requires 64-byte alignment */
+ min_pitch = ALIGN(min_pitch, 64);
+
+ /*
+ * Size should be based on pixel format and pitch, not just pitch.
+ * For YUV surfaces, it is smaller than RGB surfaces.
+ */
+ switch (IGD_PF_TYPE(pixel_format)) {
+ case PF_TYPE_YUV_PLANAR:
+ *size = min_pitch * (*height + (*height>>1));
+ break;
+ case PF_TYPE_YUV_PACKED:
+ /* FIXME: What should this really be? */
+ *size = min_pitch * *height;
+ break;
+ default:
+ *size = min_pitch * *height;
+ break;
+ }
+
+ *pitch = min_pitch;
+
+ /* Page align size */
+ align = (*size + 4095) & ~4095;
+
+ /*
+ * Flags provide information on the type of surface being requested
+ * 0x04 = cursor surface
+ * 0x08 = overlay surface
+ * 0x10 = display surface
+ * 0x40 = video surface
+ */
+ do {
+ ret = gmm_alloc_chunk_space(&gmm_context, offset, *size, phys, flags);
+ } while ((ret == -IGD_ERROR_NOMEM) && gmm_flush_cache());
+
+ EMGD_DEBUG("EXIT Returning %d", ret);
+ return ret;
+}
+
+
+
+
+/*
+ * gmm_contig_page_list(): Create the page list for a previously-allocated
+ * block of contiguous memory. (This is needed for GTT insertion, and normally
+ * created by the emgd_alloc_pages() function.)
+ */
+static gmm_mem_buffer_t *gmm_contig_page_list(unsigned long num_pages,
+ unsigned long phys_addr)
+{
+ gmm_mem_buffer_t *mem;
+ size_t list_size;
+ int i;
+ void *virt_addr = phys_to_virt(phys_addr);
+
+ mem = (gmm_mem_buffer_t *)kzalloc(sizeof(gmm_mem_buffer_t), GFP_KERNEL);
+ if (mem == NULL) {
+ printk(KERN_ERR "[EMGD] Cannot allocate gmm_mem_buffer_t ");
+ EMGD_ERROR_EXIT("Returning NULL\n");
+ return NULL;
+ }
+
+ /* First allocate page array */
+ list_size = num_pages * sizeof(struct page *);
+ mem->vmalloc_flag = false;
+
+ if (list_size <= (2 * PAGE_SIZE)) {
+ mem->pages = kmalloc(list_size, GFP_KERNEL | __GFP_NORETRY);
+ }
+
+ if (mem->pages == NULL) {
+ mem->pages = vmalloc(list_size);
+ mem->vmalloc_flag = true;
+ }
+
+ if (mem->pages == NULL) {
+ kfree(mem);
+ printk(KERN_ERR "Failed to allocate memory info struct.\n");
+ EMGD_ERROR_EXIT("Returning NULL\n");
+ return NULL;
+ }
+
+ mem->pages[0] = virt_to_page(virt_addr);
+ if (num_pages > 1) {
+ for (i = 1; i < num_pages; i++) {
+ mem->pages[i] = mem->pages[i-1] + 1;
+ }
+ }
+ mem->physical = page_to_phys(mem->pages[0]);
+ mem->page_count = num_pages;
+
+ return mem;
+}
+
+/*
+ * gmm_map_contig_buffer(): Map a previously-allocated contiguous SDRAM memory
+ * block into a graphics-accessible memory.
+ */
+
+static int gmm_map_contig_buffer(gmm_context_t *gmm_context,
+ unsigned long phys_addr,
+ unsigned long size,
+ unsigned long *offset)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Check for a free contiguous chunk of sufficent size */
+ chunk = gmm_context->head_chunk;
+ while (chunk) {
+ if ((chunk->usage== FREE_ALLOCATED) && (chunk->size >= size)
+ && (chunk->type == AGP_PHYS_MEMORY)) {
+ /* Re-use this chunk */
+ chunk->usage = INUSE_ALLOCATED;
+ EMGD_DEBUG("Re-using old chunk with offset=0x%lx",
+ chunk->offset);
+ EMGD_DEBUG("EXIT Returning %d", 0);
+ break;
+ }
+ chunk = chunk->next;
+ }
+ /* Allocate a new chunk list element */
+ if(chunk == NULL){
+ chunk = (gmm_chunk_t *)OS_ALLOC(sizeof(gmm_chunk_t));
+ if (!chunk) {
+ printk(KERN_ERR "[EMGD] Cannot allocate gmm_chunk_t element");
+ EMGD_ERROR_EXIT("Returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /*if want to reuse the chunk, no need memset it here.
+ * we need the previous gtt offset of chunk.
+ */
+ OS_MEMSET(chunk, 0, sizeof(gmm_chunk_t));
+
+ chunk->size = size;
+
+ /* Determine the offset value for this chunk
+ * if this chunk is new allocated, then we set tailk_chunk->offset+size to chunk->offset
+ * if this chunk is reused, then no need to assign the chunk->offset again.
+ * also no need to insert this chunk into list again, because this chunk is already in the list.
+ */
+
+
+ if (gmm_context->tail_chunk == NULL) {
+
+ chunk->offset = 0;
+
+ } else {
+ chunk->offset = gmm_context->tail_chunk->offset +
+ gmm_context->tail_chunk->size;
+
+
+ }
+ /* Adjust the offset since display surfaces require 256KB alignment */
+ chunk->offset = (chunk->offset + 0x3ffff) & ~0x3ffff;
+
+ /* Insert this chunk in the list */
+ chunk->next = NULL;
+ if (gmm_context->head_chunk == NULL) {
+
+ gmm_context->head_chunk = chunk;
+ } else {
+ gmm_context->tail_chunk->next = chunk;
+ }
+ gmm_context->tail_chunk = chunk;
+ chunk->usage = INUSE_ALLOCATED;
+ }
+
+
+
+ /* Contiguous memory is needed, so set the type to AGP_PHYS_MEMORY */
+
+ chunk->pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ chunk->type = AGP_PHYS_MEMORY;
+
+ /* Create the GTT page list for this contiguous memory block */
+ chunk->gtt_mem = gmm_contig_page_list(chunk->pages, phys_addr);
+ if (chunk->gtt_mem == NULL) {
+ printk(KERN_ERR "[EMGD] Cannot allocate gmm_chunk_t element");
+ EMGD_ERROR_EXIT("Returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /* Assign the specified memory block to this chunk */
+ chunk->ref_cnt = 0;
+ chunk->page_addresses = NULL;
+
+
+
+
+ /* Now update the GTT so the display HW can access this memory */
+ emgd_gtt_insert(gmm_context->context, chunk->gtt_mem, chunk->offset);
+
+ /* Bind the gart memory to the offset */
+ chunk->bound = 1;
+
+ /* For contiguous pages, physical is the address of the first allocated page */
+ if (chunk->gtt_mem->physical == 0x0) {
+ chunk->gtt_mem->physical = page_to_phys(chunk->gtt_mem->pages[0]);
+ }
+
+ /* Return the offset associated with this contiguous block */
+ *offset = chunk->offset;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+/*
+ * gmm_map_to_graphics(): Facilitates direct display of contiguous video input
+ * buffers by mapping the specified block into the "graphics aperture" via the
+ * GTT.
+ */
+int gmm_map_to_graphics(unsigned long phys_addr,
+ unsigned long size,
+ unsigned long *offset)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ if (phys_addr && size) {
+ ret = gmm_map_contig_buffer(&gmm_context, phys_addr, size,
+ offset);
+
+ } else {
+ printk(KERN_ERR "Invalid address (0x%lx) and/or size (0x%lx) !",
+ phys_addr, size);
+ printk(KERN_ERR "EXIT Returning %d", -EINVAL);
+ ret = -EINVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+EXPORT_SYMBOL(gmm_map_to_graphics);
+
+
+
+
+/*
+ * find gtt_offset and virtual address from ci_surface list according to the same v4l2_offset
+ */
+
+static int gmm_map_ci(unsigned long *gtt_offset,
+ unsigned long ci_param, /* cast to (struct emgd_ci_meminfo_t *) */
+ unsigned long *virt_addr,
+ unsigned int map_method,
+ unsigned long size)
+
+{
+ unsigned char i;
+ int ret;
+ struct emgd_ci_meminfo_t * ci_meminfo;
+ unsigned long virt;
+
+ ci_meminfo = (struct emgd_ci_meminfo_t *)ci_param;
+ virt = ci_meminfo->virt;
+
+ if(map_method){
+ ret = gmm_map_to_graphics(virt_to_phys((unsigned long *)virt),size,gtt_offset);
+ if(ret)
+ return ret;
+ else{
+ for(i=0;i<MAX_CI_LIST_SIZE;i++){
+
+ if(!ci_surfaces[i].used){
+
+ ci_surfaces[i].used = 1;
+ ci_surfaces[i].virt = virt;
+ ci_surfaces[i].size = size;
+ ci_surfaces[i].gtt_offset = *gtt_offset;
+ *virt_addr = virt;
+ break;
+ }
+ }
+ }
+ }
+ else{
+
+ for(i=0;i<MAX_CI_LIST_SIZE;i++){
+ if(ci_surfaces[i].used && (ci_surfaces[i].vbufqueue_handle == ci_meminfo->vbufqueue_handle)
+ && (ci_surfaces[i].v4l2_offset ==ci_meminfo->v4l2_offset)){
+
+ *gtt_offset = ci_surfaces[i].gtt_offset;
+ *virt_addr = ci_surfaces[i].virt;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * gmm_unmap_contig_buffer(): Un-map a previously-allocated contiguous SDRAM
+ * memory block into graphics memory.
+ */
+
+static int gmm_unmap_contig_buffer(gmm_context_t *gmm_context,
+ unsigned long offset,
+ unsigned long size)
+{
+
+ gmm_chunk_t *chunk;
+ EMGD_TRACE_ENTER;
+
+ /* Locate the specified chunk and mark it as unused */
+ chunk = gmm_context->head_chunk;
+ while (chunk) {
+ if ((chunk->usage == INUSE_ALLOCATED) && (chunk->size >= size) &&
+ (chunk->type == AGP_PHYS_MEMORY) &&
+ chunk->offset == offset) {
+
+ emgd_gtt_remove(gmm_context->context, chunk->gtt_mem, chunk->offset);
+
+ chunk->usage = FREE_ALLOCATED;
+
+ /* no need release the chunk from chunk list.
+ * Because need reuse the offset in gtt table of this chunk
+ */
+ if(chunk->gtt_mem !=NULL)
+ kfree(chunk->gtt_mem);
+
+ /* Free the array of page address, if applicable: */
+ if (chunk->page_addresses != NULL) {
+ EMGD_DEBUG("About to free chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ OS_FREE(chunk->page_addresses);
+ }
+
+ return 0;
+ }
+ chunk = chunk->next;
+ }
+ printk(KERN_ERR "Buffer @ 0x%lx (size 0x%lu) not found !", offset, size);
+ printk(KERN_ERR "EXIT Returning %d", -EINVAL);
+ EMGD_TRACE_EXIT;
+ return -EINVAL;
+}
+
+
+/*
+ * gmm_unmap_from_graphics(): Disables direct display of DMA video input buffers
+ * by unmapping the specified block from the "graphics aperture" via the GTT.
+ */
+int gmm_unmap_from_graphics(unsigned long offset, unsigned long size)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ if (offset && size) {
+ /* Mark the GTT chunk as currently unused */
+ ret = gmm_unmap_contig_buffer(&gmm_context, offset, size);
+ } else {
+ printk(KERN_ERR "Invalid offset (0x%lx) and/or size (0x%lx) !",
+ offset, size);
+ printk(KERN_ERR "EXIT Returning %d", -EINVAL);
+ ret = -EINVAL;
+ }
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+EXPORT_SYMBOL(gmm_unmap_from_graphics);
+
+
+/*
+ * Maintain a very simple linear linked list of memory allocations. Try
+ * to re-use freed blocks. No error checking is done and alignment is
+ * hard codeded.
+ */
+
+static int gmm_alloc_chunk_space(gmm_context_t *gmm_context,
+ unsigned long *offset,
+ unsigned long size,
+ unsigned long phys,
+ unsigned long flags)
+{
+ gmm_chunk_t *chunk;
+ struct drm_device *dev;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: size=%lu; phys=%lu", size, phys);
+ EMGD_DEBUG(" flags=0x%08lx", flags);
+
+ /* Check for a free chunk of sufficent size */
+ chunk = gmm_context->head_chunk;
+ while (chunk) {
+ if ((chunk->usage == FREE_ALLOCATED) && (chunk->size >= size) &&
+ (chunk->type == (phys ? AGP_PHYS_MEMORY : AGP_NORMAL_MEMORY))) {
+ chunk->usage = INUSE_ALLOCATED;
+ *offset = chunk->offset;
+ EMGD_DEBUG("Re-using old chunk with offset=0x%lx", chunk->offset);
+ EMGD_DEBUG("EXIT Returning %d", 0);
+ return 0;
+ }
+ chunk = chunk->next;
+ }
+
+ /* Allocate a new chunk */
+ chunk = (gmm_chunk_t *)OS_ALLOC(sizeof(gmm_chunk_t));
+ if (!chunk) {
+ printk(KERN_ALERT "[EMGD] Cannot allocate gmm_chunk_t");
+ EMGD_ERROR_EXIT("Returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+ OS_MEMSET(chunk, 0, sizeof(gmm_chunk_t));
+
+ /*
+ * First allocate the memory from the gart driver. If this failes,
+ * don't bother allocating a new chunk.
+ */
+ dev = (struct drm_device *)gmm_context->context->drm_dev;
+ chunk->size = size;
+ chunk->pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ /*
+ * If we need phyical contiguous memory, then we need to
+ * set the type to AGP_PHYS_MEMORY, otherwise use AGP_NORMAL_MEMORY
+ */
+ if (phys) {
+ chunk->type = AGP_PHYS_MEMORY;
+ EMGD_DEBUG("Allocate AGP_PHYS; size = 0x%08lx", chunk->size);
+ } else {
+ chunk->type = AGP_NORMAL_MEMORY;
+ EMGD_DEBUG("Allocate AGP_NORMAL; size = 0x%08lx", chunk->size);
+ }
+
+ if (dev == NULL) {
+ OS_FREE(chunk);
+ EMGD_ERROR_EXIT("drm device is NULL; Returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+
+
+ /* Allocate memory from the AGPGART */
+ chunk->gtt_mem = emgd_alloc_pages(chunk->pages, chunk->type);
+ if (!chunk->gtt_mem) {
+ OS_FREE(chunk);
+ printk(KERN_ALERT "[EMGD] Failed to allocated AGP memory.\n");
+ EMGD_DEBUG("gmm_alloc_chunk_space() returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+
+
+ chunk->usage = INUSE_ALLOCATED;
+ chunk->ref_cnt = 0;
+ chunk->page_addresses = NULL;
+
+ /*
+ * Get the next available offset that works for this allocation.
+ * Currently this just uses the next linear offset available. No
+ * attempt is made to keep track of or utilize gaps introduced
+ * because of alignments.
+ *
+ * Eventually, this should mainting different "heaps" of offsets
+ * for different types of allocations. For example, display vs.
+ * video.
+ *
+ * See igd_gmm.h for the different surface types supported. Below
+ * are the ones of interest
+ *
+ * #define IGD_SURFACE_RENDER 0x00000001
+ * #define IGD_SURFACE_CURSOR 0x00000004
+ * #define IGD_SURFACE_OVERLAY 0x00000008
+ * #define IGD_SURFACE_DISPLAY 0x00000010
+ * #define IGD_SURFACE_VIDEO 0x00000040
+ * #define IGD_SURFACE_VIDEO_ENCODE 0x00000080
+ * #define IGD_SURFACE_SYS_MEM 0x00008000
+ * #define IGD_SURFACE_PHYS_PTR 0x00010000
+ *
+ */
+ if (gmm_context->tail_chunk == NULL) {
+ /* 1st ever chunk */
+ if(gmm_context->context->mod_dispatch.init_params->qb_seamless) {
+ chunk->offset = (gmm_context->context->device_context.stolen_pages) * PAGE_SIZE;
+ } else {
+ chunk->offset = 0;
+ }
+ } else {
+ chunk->offset = gmm_context->tail_chunk->offset +
+ gmm_context->tail_chunk->size;
+ }
+ EMGD_DEBUG("- Before alignment: offset=0x%lx", chunk->offset);
+
+ /*
+ * Alignment varies depending on the type of surface being allocated.
+ */
+ if (flags & IGD_SURFACE_DISPLAY) {
+ /* 256KB aligned */
+ chunk->offset = (chunk->offset + 0x3ffff) & ~0x3ffff;
+ } else {
+ /* 4KB aligned */
+ chunk->offset = (chunk->offset + 0x0fff) & ~0x0fff;
+ }
+
+ EMGD_DEBUG("- After alignment: offset=0x%lx", chunk->offset);
+ chunk->next = NULL;
+
+ if (gmm_context->head_chunk == NULL) {
+ gmm_context->head_chunk = chunk;
+ } else {
+ gmm_context->tail_chunk->next = chunk;
+ }
+ gmm_context->tail_chunk = chunk;
+
+ /* Bind the gart memory to the offset */
+ /*
+ * This updates the GTT table with the actual allocated pages
+ * so the display hardware can access the memory.
+ *
+ * TODO: Add ability to use other MMU's depending on the
+ * type of memory requested.
+ */
+ emgd_gtt_insert(gmm_context->context, chunk->gtt_mem, chunk->offset);
+ chunk->bound = 1;
+
+ /*
+ * Physical is only meaningfull for single page or contiguous pages.
+ * It represents the physical address of the first allocated page.
+ */
+ if (chunk->gtt_mem->physical == 0x0) {
+ chunk->gtt_mem->physical = page_to_phys(chunk->gtt_mem->pages[0]);
+ }
+
+ *offset = chunk->offset;
+
+ EMGD_DEBUG("Allocated chunk @ 0x%lx (0x%lx)", chunk->offset,
+ (unsigned long)chunk->gtt_mem->physical);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+/*
+ * Imports a list of pages allocated by an external source (i.e., the PVR
+ * services) into the GMM and maps the pages into the GTT. Note that
+ * this function is as dumb as gmm_alloc_chunk_space about reusing
+ * previous allocations that have been freed; it will happily use a large
+ * hole in the GTT for a tiny allocation if it's the first hole it finds.
+ *
+ * pagelist is a live page list; it should not be modified or freed by
+ * the GMM.
+ * gtt_offset is an output only; this is the offset of the beginning of
+ * the first page from the start of the GTT. If the actual surface
+ * data starts partway through a page, the caller may need to add an
+ * addition offset to where the surface data starts.
+ */
+static int gmm_import_pages(void **pagelist,
+ unsigned long *gtt_offset,
+ unsigned long numpages)
+{
+ gmm_chunk_t *chunk;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Importing %lu pages into GTT\n", numpages);
+
+ /*
+ * Check for a free chunk of sufficent size that does not have allocated
+ * pages attached to it (i.e., a chunk from a previous import region that's
+ * been freed.
+ */
+ chunk = gmm_context.head_chunk;
+ while (chunk) {
+ if ((chunk->usage == FREE_IMPORTED) && (chunk->pages >= numpages))
+ {
+ chunk->usage = INUSE_ALLOCATED;
+ EMGD_DEBUG("Re-using old chunk with offset=0x%lx", chunk->offset);
+ break;
+ }
+ chunk = chunk->next;
+ }
+
+ /* Allocate a new chunk if we didn't find any that we could reuse */
+ if (!chunk) {
+ chunk = (gmm_chunk_t *)OS_ALLOC(sizeof(gmm_chunk_t));
+ if (!chunk) {
+ printk(KERN_ALERT "[EMGD] Cannot allocate gmm_chunk_t");
+ EMGD_ERROR_EXIT("Returning %d", -IGD_ERROR_NOMEM);
+ return -IGD_ERROR_NOMEM;
+ }
+ OS_MEMSET(chunk, 0, sizeof(gmm_chunk_t));
+
+ chunk->pages = numpages;
+ chunk->size = numpages * PAGE_SIZE;
+ chunk->next = NULL;
+
+ /* Create a gmm_mem_buffer_t for the imported memory */
+ chunk->gtt_mem = OS_ALLOC(sizeof(gmm_mem_buffer_t));
+ if (chunk->gtt_mem == NULL) {
+ OS_FREE(chunk);
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /* Stick this chunk after all other GTT chunks */
+ if (gmm_context.tail_chunk == NULL) {
+ /* First chunk ever! */
+ gmm_context.head_chunk = chunk;
+ if(gmm_context.context->mod_dispatch.init_params->qb_seamless) {
+ chunk->offset = (gmm_context.context->device_context.stolen_pages) * PAGE_SIZE;
+ } else {
+ chunk->offset = 0;
+ }
+ } else {
+ chunk->offset = gmm_context.tail_chunk->offset +
+ gmm_context.tail_chunk->size;
+ gmm_context.tail_chunk->next = chunk;
+ }
+ gmm_context.tail_chunk = chunk;
+
+ /*
+ * Since we're making this a displayable surface, we need to make sure
+ * it's 256k-aligned.
+ */
+ chunk->offset = (chunk->offset + 0x3ffff) & ~0x3ffff;
+
+ EMGD_DEBUG("Setting up a new GMM chunk for imported pages");
+ }
+
+ *gtt_offset = chunk->offset;
+
+ chunk->usage = INUSE_IMPORTED;
+ chunk->ref_cnt = 0;
+ chunk->page_addresses = NULL;
+
+ /*
+ * Note that the underlying gmm_mem_buffer may have a smaller size and
+ * number of pages if we're reusing a larger chunk than we really needed.
+ */
+ chunk->gtt_mem->size = numpages * PAGE_SIZE;
+ chunk->gtt_mem->pages = (struct page**)pagelist;
+ chunk->gtt_mem->page_count = numpages;
+
+ /*
+ * These fields should never be needed since responsibility for actually
+ * freeing these pages and the page list itself lies with the external
+ * code that allocated the pages.
+ */
+ chunk->type = AGP_NORMAL_MEMORY;
+ chunk->gtt_mem->type = AGP_NORMAL_MEMORY;
+ chunk->gtt_mem->vmalloc_flag = 0;
+
+ /*
+ * This updates the GTT table with the actual imported pages
+ * so the display hardware can access the memory.
+ */
+ emgd_gtt_insert(gmm_context.context, chunk->gtt_mem, chunk->offset);
+ chunk->bound = 1;
+
+ /*
+ * Physical is only meaningfull for single page or contiguous pages.
+ * It represents the physical address of the first allocated page.
+ */
+ if (chunk->gtt_mem->physical == 0x0) {
+ chunk->gtt_mem->physical = page_to_phys(chunk->gtt_mem->pages[0]);
+ }
+
+ EMGD_DEBUG("Imported chunk @ 0x%lx (0x%lx)", chunk->offset,
+ (unsigned long)chunk->gtt_mem->physical);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+static int gmm_get_page_list(unsigned long offset,
+ unsigned long **pages,
+ unsigned long *page_cnt)
+{
+ gmm_chunk_t *chunk;
+ int i;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: offset=0x%08lx", offset);
+ EMGD_DEBUG(" pages=0x%p, *pages=0x%p", pages, *pages);
+ chunk = gmm_get_chunk(gmm_context.context, offset);
+
+ if (chunk == NULL) {
+ printk(KERN_ERR"[EMGD] gmm_get_page_list: Failed to find chunk: "
+ "0x%lx\n", offset);
+ return -IGD_ERROR_NOMEM;
+ }
+
+ *page_cnt = chunk->gtt_mem->page_count;
+
+ /* Allocate an array of page addresses: */
+ if (chunk->page_addresses == NULL) {
+ chunk->page_addresses = OS_ALLOC(sizeof(unsigned long) * *page_cnt);
+ EMGD_DEBUG("Allocated chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ if (chunk->page_addresses == NULL) {
+ printk(KERN_ERR "[EMGD] gmm_get_page_list: failed to allocate the "
+ "array of page addresses for chunk: 0x%lx\n", offset);
+ return -IGD_ERROR_NOMEM;
+ }
+ } else {
+ EMGD_DEBUG("Re-using chunk->page_addresses = 0x%p",
+ chunk->page_addresses);
+ }
+
+ /* Populate the array with the starting addresses of the pages: */
+ for (i = 0; i < *page_cnt; i++) {
+ chunk->page_addresses[i] = page_to_phys(chunk->gtt_mem->pages[i]);
+ }
+
+ *pages = chunk->page_addresses;
+
+ EMGD_DEBUG("*pages=0x%p", *pages);
+ EMGD_DEBUG("page_count=%lu", *page_cnt);
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int emgd_map_ci_buf(struct emgd_ci_meminfo_t * ci_meminfo)
+{
+ int ret;
+ unsigned long gtt_offset;
+ unsigned char i;
+ ret = gmm_map_to_graphics(virt_to_phys((unsigned long *)ci_meminfo->virt), ci_meminfo->size, >t_offset);
+ if(ret)
+ {
+ return ret;/*error handling*/
+ }
+ /* save meminfo into our context */
+ for(i=0;i<MAX_CI_LIST_SIZE;i++){
+ if(!ci_surfaces[i].used){
+ ci_surfaces[i].used = 1;
+ ci_surfaces[i].virt = ci_meminfo->virt;
+ ci_surfaces[i].size = ci_meminfo->size;
+ ci_surfaces[i].gtt_offset = gtt_offset;
+ ci_surfaces[i].vbufqueue_handle = ci_meminfo->vbufqueue_handle;
+ ci_surfaces[i].v4l2_offset = ci_meminfo->v4l2_offset;
+ return 0;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(emgd_map_ci_buf);
+int emgd_unmap_ci_buf(unsigned long virt_addr)
+{
+ unsigned char i;
+ int ret;
+ for(i=0;i<MAX_CI_LIST_SIZE;i++)
+ {
+ if(ci_surfaces[i].used && (ci_surfaces[i].virt == virt_addr))
+ {
+ ret = gmm_unmap_from_graphics(ci_surfaces[i].gtt_offset, ci_surfaces[i].size);
+ ci_surfaces[i].used = 0;
+ ci_surfaces[i].gtt_offset = 0;
+ return 0;
+ }
+ }
+ printk(KERN_ERR"[gmm]ci unmap failed\n");
+ return 1;
+}
+
+EXPORT_SYMBOL(emgd_unmap_ci_buf);
+
+
+static int gmm_unmap_ci(unsigned long virt_addr)
+{
+ int ret;
+ ret =emgd_unmap_ci_buf(virt_addr);
+ return ret;
+}
+
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/gmm/gtt.c b/drivers/gpu/drm/emgd/emgd/gmm/gtt.c
new file mode 100644
index 0000000..f530ca6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/gmm/gtt.c
@@ -0,0 +1,436 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gtt.c
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Manage the GTT.
+ *-----------------------------------------------------------------------------
+ */
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memlist.h>
+#include <io.h>
+#include <memory.h>
+#include <asm/cacheflush.h>
+#include <linux/version.h>
+
+#define PFX "EMGD: "
+
+#define SCR1 0x71410 /* scratch register set by vbios indicating status*/
+#define SCR2 0x71418 /* scratch register set by vbios indicating amount of stolen memory */
+#define FW_ID 0xE1DF0000 /* firmware identifier */
+#define ST_BIT 0x00000004 /* bit2- stolen memory bit */
+#define PSB_PTE_VALID 0x0001
+
+void emgd_free_pages(gmm_mem_buffer_t *mem);
+
+static DEFINE_MUTEX(client_sem);
+static DEFINE_MUTEX(gtt_sem);
+
+struct client_list_struct {
+ struct list_head list;
+ struct vm_area_struct *vma;
+ pid_t pid;
+};
+
+static LIST_HEAD(client_list);
+
+static void ipi_handler(void *null) {
+ //flush_agp_cache(); /* from agp.h */
+ wbinvd();
+}
+
+static void emgd_cache_flush(void) {
+ if (on_each_cpu(ipi_handler, NULL, 1) != 0)
+ panic(PFX "timed out waiting for the other CPUs!\n");
+}
+
+static void tlb_flush(void) {
+ /* If needed, this would flush the SGX/MSVDX mmu TLB's */
+}
+
+/* FIXME - TURNS OUT THAT THIS FUNCTION IS CURRENTLY A NOOP, BECAUSE
+ * client_list NEVER HAS ANYTHING ADDED TO IT.
+ */
+static void invalidate_vma(unsigned long pg_offset, unsigned long bus_addr) {
+ int zap;
+ struct list_head *tmp;
+ struct client_list_struct *entry;
+ unsigned long addr_start=0;
+ unsigned long addr_end=0;
+ unsigned long addr_offset=0;
+ unsigned long vaddr;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ mutex_lock(&client_sem);
+ list_for_each(tmp, &client_list) {
+ entry = list_entry(tmp, struct client_list_struct, list);
+
+ /*
+ * We need to handle invalidating VMA's that are only mapping
+ * a portion of the virtual aperture. Calculate what if
+ * any invalidated pages need to be zapped
+ */
+ addr_start = (entry->vma->vm_pgoff << PAGE_SHIFT)
+ - bus_addr;
+ addr_end = addr_start + (entry->vma->vm_end - entry->vma->vm_start);
+ addr_offset = pg_offset << PAGE_SHIFT;
+
+ vaddr = entry->vma->vm_start + (addr_offset - addr_start);
+
+ zap=0;
+ pgd=NULL;
+ pud=NULL;
+ pmd=NULL;
+ pte=NULL;
+
+ /*
+ * Look up page table entries for all VMAs that currently
+ * have the virtual aperture mapped -- to see if the page
+ * has ever faulted
+ */
+ pgd = pgd_offset(entry->vma->vm_mm, vaddr);
+ if (!pgd_none(*pgd)) {
+ pud = pud_offset(pgd, vaddr);
+ if (!pud_none(*pud)) {
+ pmd = pmd_offset(pud, vaddr);
+ if (!pmd_none(*pmd)) {
+ pte = pte_offset_map(pmd, vaddr);
+ if (!pte_none(*pte)) {
+ zap=1;
+ }
+ }
+ }
+ }
+ /*
+ * Only zap a page if it falls within the mapped region
+ * and it has previously faulted
+ */
+ if (zap && (addr_offset >= addr_start) &&
+ (addr_offset < addr_end)) {
+
+
+ if (!page_mapcount(pte_page(*pte))) {
+ printk(KERN_ERR "[EMGD] ERROR No mapcount\n");
+ printk(KERN_ALERT "[EMGD] ZR %p %08lX %d %d %p\n",
+ pte_page(*pte),
+ pte_page(*pte)->flags, page_count(pte_page(*pte)),
+ page_mapcount(pte_page(*pte)), pte_page(*pte)->mapping);
+ } else {
+ atomic_add_negative(-1, &pte_page(*pte)->_mapcount);
+ put_page(pte_page(*pte));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ dec_mm_counter(entry->vma->vm_mm, file_rss);
+#else
+ dec_mm_counter(entry->vma->vm_mm, MM_FILEPAGES);
+#endif
+ }
+
+ pte_clear(entry->vma->vm_mm, vaddr, pte);
+ }
+
+ if(pte) {
+ pte_unmap(pte);
+ }
+ }
+ mutex_unlock(&client_sem);
+}
+
+
+
+/*
+ * Allocate pages from the kernel and store in a page list.
+ */
+gmm_mem_buffer_t *emgd_alloc_pages(unsigned long num_pages, int type) {
+ gmm_mem_buffer_t *mem;
+ size_t list_size;
+ struct page *page;
+ int i;
+ int order;
+
+ mem = (gmm_mem_buffer_t *)kzalloc(sizeof(gmm_mem_buffer_t), GFP_KERNEL);
+ if (mem == NULL) {
+ return NULL;
+ }
+
+ /* First allocate page array */
+ list_size = num_pages * sizeof(struct page *);
+ mem->vmalloc_flag = false;
+
+ if (list_size <= (2 * PAGE_SIZE)) {
+ mem->pages = kmalloc(list_size, GFP_KERNEL | __GFP_NORETRY);
+ }
+
+ if (mem->pages == NULL) {
+ mem->pages = vmalloc(list_size);
+ mem->vmalloc_flag = true;
+ }
+
+ if (mem->pages == NULL) {
+ printk(KERN_ERR "[EMGD] Failed to allocate memory info struct.\n");
+ kfree(mem);
+ return NULL;
+ }
+
+ /*
+ * If we need phyical contiguous memory, then do things differently.
+ * Call alloc_pages(GFP_KERNEL, pages) to allocate all the pages.
+ * The page structure returned is just the first page of the group.
+ * ? is it a virtual address ?
+ *
+ * mem->pages[0] = virt_to_phys(page)
+ * mem->pages[1] = mem->pages[0] + PAGE_SIZE
+ */
+
+ if ((type == 1) || (type == 0)) {
+ /* Next allocate the pages */
+ for (i = 0; i < num_pages; i++) {
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+ if (page == NULL) {
+ /* Error! */
+ printk(KERN_ERR "[EMGD] Memory allocation failure!\n");
+ if (mem->vmalloc_flag) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+ kfree(mem);
+ return NULL;
+ }
+
+ /* Make sure this page isn't cached */
+ if (set_memory_uc((unsigned long) page_address(page), 1) < 0) {
+ printk(KERN_ERR "[EMGD] Unable to set page attributes for newly"
+ " allocated graphics memory.\n");
+ /* Rely on the fact that we've kept up the data structures: */
+ emgd_free_pages(mem);
+ /* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+ set_memory_wb((unsigned long) page_address(page), 1);
+ __free_page(page);
+ return NULL;
+ }
+
+ get_page(page);
+ mem->pages[i] = page;
+ mem->page_count++;
+ }
+ } else {
+ if (num_pages == 1) {
+ order = 0;
+ } else if (num_pages == 4) {
+ order = 2;
+ } else if (num_pages == 8) {
+ order = 3;
+ } else {
+ printk(KERN_ERR "[EMGD] Page count is not valid for physical "
+ "allocation.\n");
+ if (mem->vmalloc_flag) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+ kfree(mem);
+ return NULL;
+ }
+
+ page = alloc_pages(GFP_KERNEL, order);
+ if (page == NULL) {
+ /* Error! */
+ printk(KERN_ERR "[EMGD] Memory allocation failure!\n");
+ if (mem->vmalloc_flag) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+ kfree(mem);
+ return NULL;
+ } else {
+ /* Make sure these pages aren't cached */
+ if (set_memory_uc((unsigned long) page_address(page),
+ num_pages) < 0) {
+ printk(KERN_ERR "[EMGD] Unable to set page attributes for newly"
+ " allocated physical graphics memory.\n");
+ /* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+ set_memory_wb((unsigned long) page_address(page), num_pages);
+ __free_pages(page, num_pages);
+ if (mem->vmalloc_flag) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+ kfree(mem);
+ return NULL;
+ }
+
+ get_page(page);
+ mem->pages[0] = page;
+ if (num_pages > 1) {
+ for (i = 1; i < num_pages; i++) {
+ mem->pages[i] = mem->pages[i-1] + 1;
+ }
+ }
+ mem->physical = page_to_phys(mem->pages[0]);
+ mem->page_count = num_pages;
+ }
+ }
+
+ return mem;
+}
+
+/*
+ * Free memory pages.
+ */
+void emgd_free_pages(gmm_mem_buffer_t *mem) {
+ int i;
+ struct page *page;
+
+ for (i = 0; i < mem->page_count; i++) {
+ page = mem->pages[i];
+ /* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+ set_memory_wb((unsigned long) page_address(page), 1);
+ put_page(page);
+ __free_page(page);
+ mem->pages[i] = NULL;
+ }
+
+ if (mem->vmalloc_flag) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+
+ kfree(mem);
+}
+
+
+/*
+ * Need a function to populate the GTT with the pages.
+ *
+ * The caller provides the offset into the GTT where the memory needs
+ * to go. This simply needs to allocate the pages and insert them
+ * into the GTT.
+ */
+void emgd_gtt_insert(igd_context_t *context,
+ gmm_mem_buffer_t *mem,
+ unsigned long offset)
+{
+ struct page *page;
+ unsigned long pte;
+ unsigned long pg_off;
+ int i, j;
+
+ pg_off = offset >> PAGE_SHIFT;
+
+ /* Check that the offset is within the gtt's range */
+ if ((pg_off + mem->page_count) > context->device_context.gatt_pages) {
+ printk(KERN_ERR "[EMGD] Attempt to insert a offset beyond of GTT range.\n");
+ return;
+ }
+
+ /* Flush before inserting pages into the GTT */
+ emgd_cache_flush();
+ tlb_flush();
+
+
+ /* Insert the pages into the GTT */
+ mutex_lock(>t_sem);
+ for (i = 0, j = pg_off; i < mem->page_count; i++, j++) {
+ page = mem->pages[i];
+
+ /* Mark the page as valid */
+ pte = page_to_phys(page) | PSB_PTE_VALID;
+ writel(pte, (context->device_context.virt_gttadr + j));
+ readl(context->device_context.virt_gttadr + j);
+
+ }
+
+ mutex_unlock(>t_sem);
+
+ (void)readl(context->device_context.virt_gttadr + j - 1);
+
+ /* Invalidate VMA's */
+ invalidate_vma(j,
+ (context->device_context.gmch_ctl | PCI_BASE_ADDRESS_MEM_MASK));
+
+ /* Flush */
+ emgd_cache_flush();
+ tlb_flush();
+
+ return;
+}
+
+/*
+ * Need a function to remove pages from the GTT (and replace with the
+ * scratch page?) and free the pages.
+ */
+
+void emgd_gtt_remove(igd_context_t *context,
+ gmm_mem_buffer_t *mem,
+ unsigned long offset)
+{
+ struct page *page;
+ unsigned long pte;
+ int i;
+ unsigned long pg_start;
+
+ pg_start = offset >> PAGE_SHIFT;
+
+ /* Flush before inserting pages into the GTT */
+ emgd_cache_flush();
+ tlb_flush();
+
+ mutex_lock(>t_sem);
+
+ page = context->device_context.scratch_page;
+ pte = page_to_phys(page) | PSB_PTE_VALID;
+
+ /* Insert the scratch page into the GTT */
+ for (i = pg_start; i < (mem->page_count + pg_start); i++) {
+ /* FIXME: Apparently we don't really need to copy stolen memory pages.
+ * If so, what should we do about the following code? Is it correct to
+ * do nothing?
+ */
+ if (i < context->device_context.stolen_pages) {
+ /* This is stolen memory.... */
+ } else {
+ writel(pte, context->device_context.virt_gttadr + i);
+ (void)readl(context->device_context.virt_gttadr + i);
+ }
+
+ }
+
+ mutex_unlock(>t_sem);
+
+ /* Invaidate VMA's */
+ invalidate_vma(i,
+ (context->device_context.gmch_ctl | PCI_BASE_ADDRESS_MEM_MASK));
+
+ /* Flush */
+ emgd_cache_flush();
+ tlb_flush();
+}
diff --git a/drivers/gpu/drm/emgd/emgd/include/cmd.h b/drivers/gpu/drm/emgd/emgd/include/cmd.h
new file mode 100644
index 0000000..e1787ec
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/cmd.h
@@ -0,0 +1,47 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _CMD_H
+#define _CMD_H
+
+
+typedef struct _cmd_queue cmd_queue_t;
+
+int cmd_init(igd_context_t *context);
+
+
+#define CMD_CONTROL_ON 0x1
+#define CMD_CONTROL_OFF 0x2
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/context.h b/drivers/gpu/drm/emgd/emgd/include/context.h
new file mode 100644
index 0000000..254aa32
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/context.h
@@ -0,0 +1,256 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: context.h
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_CONTEXT_H
+#define _HAL_CONTEXT_H
+
+#include <pci.h>
+
+#include <igd.h>
+#include <igd_init.h>
+
+#define GET_DEVICE_POWER_STATE(d_h) \
+(((igd_display_context_t *)(d_h))->context->device_context.power_state)
+
+typedef void * platform_context_t;
+
+typedef struct _igd_context igd_context_t;
+
+struct _pd_reg;
+struct _igd_display_context;
+struct _igd_display_port;
+struct _pd_timing;
+struct _cmd_queue;
+
+/*
+ * Flags for reg_set_mod_state and reg_get_mode_state
+ */
+typedef enum _reg_state_id {
+ REG_MODE_STATE_REG = 1,
+ REG_MODE_STATE_CON = 2
+} reg_state_id_t;
+
+/* module_state handle */
+typedef struct _module_state *module_state_h;
+
+/*
+ * Intermodule-dispatch is for calling from one module to another. All
+ * functions should be considered optional and the caller should check
+ * for null before using.
+ */
+typedef struct _inter_module_dispatch {
+ struct _igd_param *init_params;
+
+ void (*gmm_save)(igd_context_t *context, void **state);
+ void (*gmm_restore)(igd_context_t *context, void *state);
+
+ void (*mode_reset_plane_pipe_ports)(igd_context_t *context);
+ void (*filter_modes)(igd_context_t *context,
+ struct _igd_display_port *port,
+ struct _pd_timing *in_list);
+
+ unsigned long (*get_port_control)(unsigned long port_num, unsigned long port_reg);
+ /* FIXME: This should be a dsp function */
+ unsigned long (*mode_get_gpio_sets)(unsigned long **gpio);
+
+ /* For Poulsbo, there is no flip pending hardware, so the
+ * mode module and command module need to communicate */
+ int (*set_flip_pending)(unsigned char *mmio,
+ unsigned long pipe_status_reg);
+ int (*check_flip_pending)(unsigned char *mmio,
+ unsigned long pipe_status_reg);
+
+ int (*dsp_get_config_info)(igd_context_t *context,
+ igd_config_info_t *config_info);
+ int (*pi_get_config_info)(igd_context_t *context,
+ igd_config_info_t *config_info);
+
+ /* Widely used DSP interfaces */
+ struct _igd_display_port *(*dsp_get_next_port)(igd_context_t *context,
+ struct _igd_display_port *port, int reverse);
+ struct _igd_plane *(*dsp_get_next_plane)(igd_context_t *context,
+ struct _igd_plane *plane, int reverse);
+ struct _igd_display_pipe *(*dsp_get_next_pipe)(igd_context_t *context,
+ struct _igd_display_pipe *pipe, int reverse);
+ void (*dsp_get_display)(unsigned short port_number,
+ struct _igd_display_context **display,
+ struct _igd_display_port **port, int display_detect);
+ void (*dsp_get_dc)(unsigned long *dc,
+ struct _igd_display_context **primary,
+ struct _igd_display_context **secondary);
+ void (*dsp_get_planes_pipes)(struct _igd_plane **primary_display_plane,
+ struct _igd_plane **secondary_display_plane,
+ struct _igd_display_pipe **primary_pipe,
+ struct _igd_display_pipe **secondary_pipe);
+ int (*dsp_alloc)(igd_context_t *context, unsigned long dc,
+ unsigned long flags);
+ void (*dsp_control_plane_format)(int enable, int display_plane, struct _igd_plane *plane_override);
+
+ /* Flag to indicate FB Blend + Overlay override */
+ unsigned int fb_blend_ovl_override;
+
+ unsigned long *dsp_current_dc;
+ /* Firmware programmed DC. This information needs to be
+ * accessible by the mode module.
+ */
+ unsigned long dsp_fw_dc;
+
+ /* flag to tell if in dih_clone mode */
+ unsigned long in_dih_clone_mode;
+ unsigned long dih_clone_display;
+
+ struct _igd_display_port **dsp_port_list;
+ struct _igd_display_context **dsp_display_list;
+
+ /* i2c and GMBus interfaces */
+ int (*i2c_read_regs)(igd_context_t *context, unsigned long i2c_bus,
+ unsigned long i2c_speed, unsigned long dab, unsigned char reg,
+ unsigned char FAR *buffer, unsigned long num_bytes,
+ unsigned long flags);
+ int (*i2c_write_reg_list)(igd_context_t *context,
+ unsigned long i2c_bus, unsigned long i2c_speed, unsigned long dab,
+ struct _pd_reg *reg_list, unsigned long flags);
+ int (*gpio_write_regs)(igd_context_t *context,
+ struct _igd_display_port *port, unsigned long gpio_pin_pair,
+ unsigned long power_state);
+ int (*gpio_read_regs)(igd_context_t *context, unsigned long gpio_pin_pair,
+ unsigned long *data);
+
+ int (*reg_get_mod_state)(reg_state_id_t id, module_state_h **state,
+ unsigned long **flags);
+
+ /* Power Module Calls to Reg module */
+ void *(*reg_alloc)(igd_context_t *context, unsigned long flags);
+ void (*reg_free)(igd_context_t *context, void *reg_set);
+ int (*reg_save)(igd_context_t *context, void *reg_set);
+ int (*reg_restore)(igd_context_t *context, void *reg_set);
+ void (*reg_crtc_lut_get)(igd_context_t *context, void *emgd_crtc);
+ void (*reg_crtc_lut_set)(igd_context_t *context, void *emgd_crtc);
+
+ /* Reg Module callbacks */
+ int (*mode_save)(igd_context_t *context, module_state_h *state,
+ unsigned long *flags);
+ int (*mode_restore)(igd_context_t *context, module_state_h *state,
+ unsigned long *flags);
+
+ /* Power Module Callbacks */
+ int (*mode_pwr)(igd_context_t *context, unsigned long powerstate);
+ int (*overlay_pwr)(igd_context_t *context, unsigned long powerstate);
+ int (*msvdx_pwr)(igd_context_t *context, unsigned long powerstate);
+ int (*msvdx_status)(igd_context_t *context, unsigned long *queue_status, unsigned long *mtx_msg_status);
+
+ /* Shutdown functions for use by init module only */
+ void (*mode_shutdown)(igd_context_t *context);
+ void (*dsp_shutdown)(igd_context_t *context);
+ void (*pi_shutdown)(igd_context_t *context);
+ void (*shutdown_2d)(igd_context_t *context);
+ void (*blend_shutdown)(igd_context_t *context);
+ void (*interrupt_shutdown)(igd_context_t *context);
+ void (*appcontext_shutdown)(igd_context_t *context);
+ void (*reset_shutdown)(igd_context_t *context);
+ void (*pwr_shutdown)(igd_context_t *context);
+ void (*overlay_shutdown)(igd_context_t *context);
+ void (*cmd_shutdown)(igd_context_t *context);
+ void (*reg_shutdown)(igd_context_t *context);
+
+ /* Mode module Callbacks */
+ int (*get_dd_timing)(struct _igd_display_context *display,
+ struct _pd_timing *in_list);
+ int (*check_port_supported)(void *port_tmp);
+ int (*get_refresh_in_border)(struct _pd_timing *in_list);
+
+} inter_module_dispatch_t;
+
+/*
+ * IGD device context contains device information that should exist in
+ * some form across all supported platforms.
+ *
+ * Device information that is specific to any individual platform/core
+ * etc should be in the "platform_context" which is hardware specific.
+ *
+ * In the event that any given core has a large number of marketing
+ * SKUs that change the PCI device ID, the device ID in this structure
+ * may be overwritten with a single common ID and not truly reflect
+ * the actual ID. This prevents polluting the function tables with
+ * dozens of logically identical chipsets.
+ *
+ */
+typedef struct _device_context {
+ unsigned long power_state;
+ unsigned long mmadr; /* Primary mmio address */
+ unsigned long mmadr_sdvo; /* sdvo mmio address */
+ unsigned long mmadr_sdvo_st; /* STMicro sdvo mmio address */
+ unsigned long mmadr_sdvo_st_gpio; /* STMicro sdvo mmio address */
+ unsigned long gpio_bar; /* LPC GPIO address */
+ unsigned char *virt_mmadr;
+ unsigned char *virt_mmadr_sdvo;
+ unsigned char *virt_mmadr_sdvo_st;
+ unsigned char *virt_mmadr_sdvo_st_gpio;
+ unsigned char *virt_gpio_bar;
+ unsigned long *virt_gttadr; /* was gtt_mmap */
+ unsigned long gatt_pages; /* Number of pages addressable by GTT */
+ unsigned long stolen_pages; /* Number of pages of stolen memory */
+ unsigned long gmch_ctl; /* GMCH control value */
+ void *scratch_page; /* Empty page to fill unused GTT entries */
+ unsigned long fb_adr; /* Video Memory address */
+ unsigned short did; /* Device ID for main video device */
+ unsigned long rid; /* Device revision ID for main video device */
+ unsigned short bid; /* Device ID for Bridge */
+ unsigned long max_dclk; /* maximum dotclock of all the chipset */
+ unsigned long mem_size; /* Total memory space managed by GMM */
+ unsigned long reserved_mem; /* Size in pages of firmware populated mem */
+ unsigned long hw_config; /* HW Config parameter bits (see igd_init.h) */
+ unsigned long hw_status_offset; /* Hw status page offset */
+ unsigned short gfx_freq; /* Graphics Frequency, used to calculate PWM */
+ unsigned short core_freq; /* Core Frequency, used to calculate DPLL freq */
+} device_context_t;
+
+struct _igd_context {
+ int igd_device_error_no; /* Values are already negative */
+ igd_dispatch_t dispatch;
+ inter_module_dispatch_t mod_dispatch;
+ device_context_t device_context; /* Hardware independent */
+ platform_context_t platform_context; /* Hardware dependent */
+ void *drm_dev;
+};
+
+typedef struct _igd_display_context {
+ igd_context_t *context;
+ void *plane;
+ void *pipe;
+ void *port[IGD_MAX_PORTS];
+ void *cursor;
+ unsigned long port_number;
+ unsigned long allocated;
+} igd_display_context_t;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/debug.h b/drivers/gpu/drm/emgd/emgd/include/debug.h
new file mode 100644
index 0000000..3a12fc1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/debug.h
@@ -0,0 +1,169 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: debug.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contains debug macros
+ *-----------------------------------------------------------------------------
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+
+
+#define IGD_PRINTK_PALETTE(p) \
+{ \
+ EMGD_DEBUG("Palette Struct:"); \
+ EMGD_DEBUG_S(" [%4d].id", (unsigned int) p->palette_id); \
+ EMGD_DEBUG_S(" [%4d].type", (unsigned int) p->palette_type); \
+ EMGD_DEBUG_S(" [%4d].size", (unsigned int) p->size); \
+}
+
+#define IGD_PRINTK_3DSTRETCH(p, s, d, f) \
+{ \
+ EMGD_DEBUG("Ring Buffer Struct:"); \
+ EMGD_DEBUG_S(" Priority = [%8d]", (unsigned int) p); \
+ EMGD_DEBUG_S(" Flags = [%08x]", (unsigned int) f); \
+ EMGD_DEBUG_S(" --------------"); \
+ EMGD_DEBUG_S(" Source surface"); \
+ EMGD_DEBUG_S(" --------------"); \
+ EMGD_DEBUG_S(" [%08x].addr", (unsigned int) s->addr); \
+ EMGD_DEBUG_S(" [%8d].height", (unsigned int) s->height); \
+ EMGD_DEBUG_S(" [%8d].width", (unsigned int) s->width); \
+ EMGD_DEBUG_S(" [%8d].pitch", (unsigned int) s->pitch); \
+ EMGD_DEBUG_S(" [%08x].pixel_format", (unsigned int) s->pixel_format); \
+ EMGD_DEBUG_S(" -------------------"); \
+ EMGD_DEBUG_S(" Destination surface"); \
+ EMGD_DEBUG_S(" -------------------"); \
+ EMGD_DEBUG_S(" [%8d].offset", (unsigned int) d->offset); \
+ EMGD_DEBUG_S(" [%8d].pitch", (unsigned int) d->pitch); \
+ EMGD_DEBUG_S(" [%8d].x1", (unsigned int) d->x1); \
+ EMGD_DEBUG_S(" [%8d].y1", (unsigned int) d->y1); \
+ EMGD_DEBUG_S(" [%8d].x2", (unsigned int) d->x2); \
+ EMGD_DEBUG_S(" [%8d].y2", (unsigned int) d->y2); \
+ EMGD_DEBUG_S(" [%08x].pixel_format", (unsigned int) d->pixel_format); \
+ EMGD_DEBUG_S(" [%08x].byte_mask", (unsigned int) d->byte_mask); \
+}
+
+#define IGD_PRINT_RB_BUFFER(a) \
+{ \
+ EMGD_DEBUG("Ring Buffer Struct:"); \
+ EMGD_DEBUG_S(" [%08x].id", (unsigned int) a->id); \
+ EMGD_DEBUG_S(" [%08x].size", (unsigned int) a->size); \
+ EMGD_DEBUG_S(" [%08x].addr", (unsigned int) a->addr); \
+ EMGD_DEBUG_S(" [%p].virt", a->virt); \
+ EMGD_DEBUG_S(" [%p].start = [%08x]", a->start, (unsigned int) EMGD_READ32(a->start)); \
+ EMGD_DEBUG_S(" [%p].head = [%08x]", a->head, (0x001ffffc & ((unsigned int) EMGD_READ32(a->head)))); \
+ EMGD_DEBUG_S(" [%p].tail = [%08x]", a->tail, (0x001ffff8 & (unsigned int) EMGD_READ32(a->tail))); \
+ EMGD_DEBUG_S(" [%p].ctrl = [%08x]", a->ctrl, (unsigned int) EMGD_READ32(a->ctrl)); \
+ EMGD_DEBUG_S(" [%08x].res", (unsigned int) a->reservation); \
+}
+
+#define IGD_PRINTK_DISPLAY(display_context) \
+{ \
+ EMGD_DEBUG("Display Context:"); \
+ EMGD_DEBUG_S(" [%8d].plane", (int) display_context->plane); \
+ EMGD_DEBUG_S(" [%8d].blend", (int) display_context->blend_operation); \
+ EMGD_DEBUG_S(" [%8d].pipe", (int) display_context->pipe); \
+ EMGD_DEBUG_S(" [%8d].port", (int) display_context->port); \
+ EMGD_DEBUG_S(" [%8d].graph", (int) display_context->alloc_type); \
+ EMGD_DEBUG_S(" [%8d].mode_n", (int) display_context->mode_number); \
+ EMGD_DEBUG_S(" [%8d].ref", (int) display_context->refresh); \
+ EMGD_DEBUG_S(" [%8d].enable", (int) display_context->enable); \
+ EMGD_DEBUG_S(" [%8d].ulPipe", (int) display_context->ulPipe); \
+ EMGD_DEBUG_S(" [%8d].ulMode", (int) display_context->ulModeNumber); \
+ EMGD_DEBUG_S(" [%8d].ulRef", (int) display_context->ulRefresh); \
+}
+
+#define IGD_PRINTK_FBINFO(fb_info) \
+{ \
+ EMGD_DEBUG("FrameBuffer Info:"); \
+ EMGD_DEBUG_S(" [%8d].width", (int) fb_info->width); \
+ EMGD_DEBUG_S(" [%8d].height", (int) fb_info->height); \
+ EMGD_DEBUG_S(" [%8d].screen_pitch", (int) fb_info->screen_pitch); \
+ EMGD_DEBUG_S(" [%8x].fb_base_offset", (unsigned int) fb_info->fb_base_offset); \
+ EMGD_DEBUG_S(" [%8x].pixel_format", (unsigned int) fb_info->pixel_format); \
+}
+
+#define IGD_PRINTK_PTINFO(pt_info) \
+{ \
+ EMGD_DEBUG("Port Info:"); \
+ EMGD_DEBUG_S(" [%8d].width", (int) pt_info->width); \
+ EMGD_DEBUG_S(" [%8d].height", (int) pt_info->height); \
+ EMGD_DEBUG_S(" [%8d].x_offset", (int) pt_info->x_offset); \
+ EMGD_DEBUG_S(" [%8d].y_offset", (int) pt_info->y_offset); \
+ EMGD_DEBUG_S(" [%8d].refresh", (int) pt_info->refresh); \
+ EMGD_DEBUG_S(" [%8d].hsync_start", (unsigned int) pt_info->hsync_start); \
+ EMGD_DEBUG_S(" [%8d].hsync_end", (unsigned int) pt_info->hsync_end); \
+ EMGD_DEBUG_S(" [%8d].hblank_start", (unsigned int) pt_info->hblank_start); \
+ EMGD_DEBUG_S(" [%8d].hblank_end", (unsigned int) pt_info->hblank_end); \
+ EMGD_DEBUG_S(" [%8d].vsync_start", (unsigned int) pt_info->vsync_start); \
+ EMGD_DEBUG_S(" [%8d].vsync_end", (unsigned int) pt_info->vsync_end); \
+ EMGD_DEBUG_S(" [%8d].vblank_start", (unsigned int) pt_info->vblank_start); \
+ EMGD_DEBUG_S(" [%8d].vblank_end", (unsigned int) pt_info->vblank_end); \
+ EMGD_DEBUG_S(" [%8x].flags", (unsigned int) pt_info->flags); \
+}
+
+#define IGD_PRINTK_FBINFO_2(a,b) \
+{ \
+ EMGD_DEBUG("FrameBuffer Info:"); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].width", (int) (a)->width, (int) (b)->width); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].height", (int) (a)->height, (int) (b)->height); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].screen_pitch", (int) (a)->screen_pitch, (int) (b)->screen_pitch); \
+ EMGD_DEBUG_S(" a=[%8x] b=[%8x].fb_base_offset", (unsigned int) (a)->fb_base_offset, (unsigned int) (b)->fb_base_offset); \
+ EMGD_DEBUG_S(" a=[%8x] b=[%8x].pixel_format", (unsigned int) (a)->pixel_format, (unsigned int) (b)->pixel_format); \
+}
+
+#define IGD_PRINTK_PTINFO_2(a,b) \
+{ \
+ EMGD_DEBUG("Port Info:"); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].width", (int) a->width, (int) b->width); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].height", (int) a->height, (int) b->height); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].x_offset", (int) a->x_offset, (int) b->x_offset); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].y_offset", (int) a->y_offset, (int) b->y_offset); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].refresh", (int) a->refresh, (int) b->refresh); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].hsync_start", (unsigned int) a->hsync_start, (unsigned int) b->hsync_start); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].hsync_end", (unsigned int) a->hsync_end, (unsigned int) b->hsync_end); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].hblank_start", (unsigned int) a->hblank_start, (unsigned int) b->hblank_start); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].hblank_end", (unsigned int) a->hblank_end, (unsigned int) b->hblank_end); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].vsync_start", (unsigned int) a->vsync_start, (unsigned int) b->vsync_start); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].vsync_end", (unsigned int) a->vsync_end, (unsigned int) b->vsync_end); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].vblank_start", (unsigned int) a->vblank_start, (unsigned int) b->vblank_start); \
+ EMGD_DEBUG_S(" a=[%8d] b=[%8d].vblank_end", (unsigned int) a->vblank_end, (unsigned int) b->vblank_end); \
+ EMGD_DEBUG_S(" a=[%8x] b=[%8x].flags", (unsigned int) a->flags, (unsigned int) b->flags); \
+}
+
+#define IGD_PRINT_ICH_GPIO(ich_gpio_base) \
+{ \
+ EMGD_DEBUG("GPIO_USE_SEL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x0)); \
+ EMGD_DEBUG("GPIO_IO_SEL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x4)); \
+ EMGD_DEBUG("GPIO_LVL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0xc)); \
+ EMGD_DEBUG("GPIO_INV = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x2c)); \
+ EMGD_DEBUG("GPIO_USE_SEL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x30));\
+ EMGD_DEBUG("GPIO_IO_SEL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x34)); \
+ EMGD_DEBUG("GPIO_LVL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x38)); \
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/decode.h b/drivers/gpu/drm/emgd/emgd/include/decode.h
new file mode 100644
index 0000000..ac2415a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/decode.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: decode.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for the video decode module.
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_DECODE_H
+#define _IGD_DECODE_H
+
+#include <igd_render.h> /* For surface definition */
+
+#define IGD_VD_MAX_SURFACES 2048
+
+#define VID_SURFACE(ctx, id) \
+ (((ctx->context_info.surfmap == NULL) ? &surface_list[id] : &surface_list[ctx->context_info.surfmap->slist_index[id]]))
+
+typedef struct _igd_vd_surfmap_table {
+ int active_entries;
+ int total_surfaces;
+ int *slist_index;
+} igd_vd_surfmap_table_t;
+
+typedef struct _igd_vd_surface_list {
+ int allocated;
+ igd_surface_t *surface;
+ int chroma_offset;
+ int stride_mode;
+ /* Used to store driver private data, e.g. decoder specific intermediate status data
+ * extra_info[0-3]: used for decode
+ * extra_info[4]: surface fourcc
+ * extra_info[5]: surface skippeded or not for encode
+ */
+ int extra_info[6];
+ igd_region_t buf;
+ igd_vd_surfmap_table_t* surfmap;
+} igd_vd_surface_list_t;
+
+struct _igd_video_context {
+ igd_vp_name_t profile;
+ igd_ve_name_t entrypoint;
+ igd_vd_surface_list_t *current_render_target;
+ igd_vd_surfmap_table_t *surfmap;
+
+ /*
+ * The actual hardware/profile context is much larger. The above
+ * members are device indpendent.
+ */
+};
+
+#endif /*_IGD_DECODE_H*/
diff --git a/drivers/gpu/drm/emgd/emgd/include/dispatch.h b/drivers/gpu/drm/emgd/emgd/include/dispatch.h
new file mode 100644
index 0000000..c5a371f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dispatch.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dispatch.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains helper functions for creating a dispatch table
+ * for IGD modules.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_DISPATCH_H
+#define _HAL_DISPATCH_H
+
+#include <context.h>
+
+typedef struct _dispatch_table {
+ unsigned long did;
+ void *table;
+}dispatch_table_t;
+
+static __inline void *dispatch_acquire(
+ igd_context_t *context,
+ dispatch_table_t *list)
+{
+ dispatch_table_t *curr = list;
+ unsigned long did = context->device_context.did;
+
+ while(curr->did != 0) {
+ if(curr->did == did) {
+ return curr->table;
+ }
+ curr++;
+ }
+ return curr->table;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h b/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
new file mode 100644
index 0000000..b6e4f73
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dispatch_utils.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file implements common macros that are used throughout the HAL
+ * for Device Dependent dispatching. This file is used in both the HAL and
+ * HAL helper libraries, as such it cannot include any HAL data structures
+ * that are not available to the helper libraries.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DISPATCH_UTILS_H_
+#define _DISPATCH_UTILS_H_
+
+#include <config.h>
+#include <intelpci.h>
+
+typedef struct _dispatch_table {
+ unsigned long did;
+ void *table;
+}dispatch_table_t;
+
+static __inline void *dispatch_acquire(
+ unsigned long did,
+ dispatch_table_t *list)
+{
+ dispatch_table_t *curr = list;
+
+ while(curr->did != 0) {
+ if(curr->did == did) {
+ return curr->table;
+ }
+ curr++;
+ }
+ return curr->table;
+}
+
+
+#ifdef CONFIG_PLB
+#define DISPATCH_PLB(p) {PCI_DEVICE_ID_VGA_PLB, p},
+#else
+#define DISPATCH_PLB(p)
+#endif
+#ifdef CONFIG_TNC
+#define DISPATCH_TNC(p) {PCI_DEVICE_ID_VGA_TNC, p},
+#define DISPATCH_TNC_A0(p) {PCI_DEVICE_ID_VGA_TNC_A0, p},
+#define DISPATCH_LNC(p) {PCI_DEVICE_ID_VGA_LNC, p},
+#else
+#define DISPATCH_TNC(p)
+#define DISPATCH_TNC_A0(p)
+#define DISPATCH_LNC(p)
+#endif
+#define DISPATCH_END {0, NULL}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/displayid.h b/drivers/gpu/drm/emgd/emgd/include/displayid.h
new file mode 100644
index 0000000..82a995f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/displayid.h
@@ -0,0 +1,663 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: displayid.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Header file for DisplayID.
+ * Supported DisplayID versions:
+ * VESA DisplayID Standard Verion 1 12/13/2007
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DISPLAYID_H
+#define _DISPLAYID_H
+
+#include <pd.h>
+
+/* Max limits for DisplayID structure members */
+#define DISPLAYID_MAX_RANGES 5
+#define DISPLAYID_MAX_NUM_TIMINGS 5
+/* Possible attributes from DisplayID:
+ * T1, T2, T3, T4, T5
+ * dual_channel
+ * panel_depth
+ * panel_type */
+#define DISPLAYID_MAX_ATTRS 10
+
+/* DisplayID return values */
+#define DISPLAYID_ERROR_PARSE 1
+#define DISPLAYID_READ_AGAIN 2
+#define DISPLAYID_NOT_SUPPORTED 3
+
+/* Print line macro */
+#define DISPLAYID_PRINT_LINE() \
+ EMGD_DEBUG("----------------------------------------------------------")
+
+/* DisplayID Product Type Identifiers */
+#define PRODUCTID_EXTENSION 0x00
+#define PRODUCTID_TEST 0x01
+#define PRODUCTID_PANEL 0x02
+#define PRODUCTID_STANDALONE 0x03
+#define PRODUCTID_TV_RECEIVER 0x04
+#define PRODUCTID_REPEATER 0x05
+
+/* DisplayID Data Block Tags */
+#define DATABLOCK_PRODUCTID 0x00
+#define DATABLOCK_DISPLAY_PARAMS 0x01
+#define DATABLOCK_COLOR_CHARS 0x02
+#define DATABLOCK_TIMING_1_DETAIL 0x03
+#define DATABLOCK_TIMING_2_DETAIL 0x04
+#define DATABLOCK_TIMING_3_SHORT 0x05
+#define DATABLOCK_TIMING_4_DMTID 0x06
+#define DATABLOCK_VESA_TIMING_STD 0x07
+#define DATABLOCK_CEA_TIMING_STD 0x08
+#define DATABLOCK_VIDEO_RANGE 0x09
+#define DATABLOCK_SERIAL_NUMBER 0x0A
+#define DATABLOCK_ASCII_STRING 0x0B
+#define DATABLOCK_DISPLAY_DEVICE 0x0C
+#define DATABLOCK_LVDS_INTERFACE 0x0D
+#define DATABLOCK_TRANSFER_CHAR 0x0E
+#define DATABLOCK_DISPLAY_INTF 0x0F
+#define DATABLOCK_STEREO_INTF 0x10
+#define DATABLOCK_VENDOR_SPECIFIC 0x7F
+#define DATABLOCK_RESERVED 0x80
+
+/*
+ * typedef struct __attribute__((packed)) {
+ * } foo_t;
+ * This isn't available with Microsoft C compiler
+ * So use pragma to enable bytewise packing and at the end
+ * put it back to default.
+ */
+#pragma pack(1)
+/* General Data Block header - Max 251 bytes */
+typedef struct _datablock {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+ unsigned char payload_data[248];
+} datablock_t;
+
+/* Video Timing Range Limits Data Block.
+ * Note:
+ * It is used to convey to a source the supported range of vertical and
+ * horizontal frequencies along with the maximum supported pixel clock.
+ * For a continuous frequency device any timing that lies within the
+ * specified range will ensure a displayable image. The picture may not
+ * be properly sized or centered, as guaranteed with explicitly reported
+ * timing, but however the display should synchronize to the timing.
+ */
+
+typedef struct _timing_range {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ struct {
+ unsigned short lsb_min_dclk;
+ unsigned char msb_min_dclk;
+ } mindclk;
+ struct {
+ unsigned short lsb_max_dclk;
+ unsigned char msb_max_dclk;
+ } maxdclk;
+ unsigned char min_hrate; /* KHz */
+ unsigned char max_hrate; /* KHz */
+ unsigned short min_hblank; /* Pixels */
+ unsigned char min_vrate; /* Hz */
+ unsigned char max_vrate; /* Hz */
+ unsigned short min_vblank; /* Lines */
+
+ /* Timing support flags */
+ unsigned char reserved1:4;
+ unsigned char discrete_display:1;
+ unsigned char vesa_cvt_rb:1;
+ unsigned char vesa_cvt_std:1;
+ unsigned char interlaced:1;
+
+ /* Because there is no way to define a 3-byte quantity it is not possible
+ * to directly read the dclks into member variables automatically.
+ * Therefore 1st read into above dclk bytes and then copy values into
+ * below fields at the time of parsing. */
+ /* Below members are outside Data Block definition */
+ unsigned long min_dclk; /* KHz */
+ unsigned long max_dclk; /* KHz */
+} timing_range_t;
+
+/* Data Block Display params - Video input id */
+#define VIDEO_INPUT_LVDS 0x01
+#define VIDEO_INPUT_TMDS 0x02
+#define VIDEO_INPUT_RSDS 0x03
+#define VIDEO_INPUT_DVID 0x04
+#define VIDEO_INPUT_DVII 0x05
+#define VIDEO_INPUT_VESA_M1 0x06
+#define VIDEO_INPUT_HDMI_A 0x07
+#define VIDEO_INPUT_HDMI_B 0x08
+#define VIDEO_INPUT_MDDI 0x09
+#define VIDEO_INPUT_PORT 0x0A
+#define VIDEO_INPUT_1394 0x0B
+#define VIDEO_INPUT_USB 0x0C
+
+/* Aspect Ratios */
+#define TIMING_AR_1_1 0x0 /* 3-bits */
+#define TIMING_AR_5_4 0x1
+#define TIMING_AR_4_3 0x2
+#define TIMING_AR_15_9 0x3
+#define TIMING_AR_16_9 0x4
+#define TIMING_AR_16_10 0x5
+
+/* Data Block Display params - feature support flags */
+typedef struct _display_params {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned short horz_image_size; /* horizontal image size in 0.1 mm */
+ unsigned short vert_image_size; /* vertical image size in 0.1 mm */
+ unsigned short horz_pixels; /* horizontal pixels */
+ unsigned short vert_pixels; /* vertical pixels */
+
+ /* Display feature support flags */
+ unsigned char deinterlacing:1; /* de-interlacing capable display */
+ unsigned char reserved1:1;
+ unsigned char fixed_res:1; /* fixed resolution display */
+ unsigned char fixed_timing:1; /* fixed timing display */
+ unsigned char dpm_capable:1; /* VESA DPM capable display */
+ unsigned char audio_override:1; /* override audio on video interface */
+ unsigned char seperate_audio:1; /* seperate audio input is available */
+ unsigned char audio_on_video:1; /* audio available on video interface */
+
+ unsigned char transfer_gamma; /* transfer characteristic gamma */
+ unsigned char aspect_ratio; /* aspect ratio */
+ unsigned char native_color_depth:4; /* color bit depth */
+ unsigned char overall_color_depth:4;/* color bit depth */
+} display_params_t;
+
+
+/* Product Identification Data Block */
+typedef struct _productid {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ char vendor[3]; /* vendor name code, no NULL char */
+ unsigned short product_code; /* product code */
+ unsigned long serial_number; /* 32-bit serial number */
+ unsigned char manf_week; /* manufactured week number */
+ unsigned char manf_year; /* # of years after 2000 */
+ unsigned char string_size; /* product id string size */
+ char string[237]; /* product id string max 236 + NULL */
+} productid_t;
+
+/* Color Characteristices Data Block */
+typedef struct _color_char {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char white_points:4;
+ unsigned char primaries:3;
+ unsigned char temporal_color:1;
+
+ unsigned short color_x_value:12; /* 1.5 bytes */
+ unsigned short color_y_value:12; /* 1.5 bytes: 0.5 from above */
+} color_char_t;
+
+/* Type 1 - DTD - 20 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 12DTDs x 20bytes = 240bytes can fit.
+ * 2. As part of parsing, DTD data will be read into type1_dtd_t then
+ * converted into pd_timing_t for IEGD consumption.
+ * 3. There is no limit on maximum number of type 1 timings.
+ * They can be present not only in basic section but also in the
+ * extension section as well.
+ */
+typedef struct _type1_dtd {
+ struct {
+ unsigned short lsb_dclk;
+ unsigned char msb_dclk;
+ } dclk; /* 02-00 [07:00] */
+
+ /* timing options - 1 byte */
+ unsigned char aspect_ratio:3;
+ unsigned char reserved:1;
+ unsigned char interlaced:1;
+ unsigned char stereo_3d_support:2;
+ unsigned char preferred:1;
+
+ unsigned short hactive;
+ unsigned short hblank;
+ unsigned short hsync_offset:15;
+ unsigned short hsync_polarity:1;
+ unsigned short hsync_width;
+ unsigned short vactive;
+ unsigned short vblank;
+ unsigned short vsync_offset:15;
+ unsigned short vsync_polarity:1;
+ unsigned short vsync_width;
+} type1_dtd_t;
+
+/* Type 2 - DTD - 11 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 22DTDs x 11bytes = 242bytes can fit.
+ * 2. As part of parsing, DTD data will be read into type2_dtd_t then
+ * converted into pd_timing_t for IEGD consumption.
+ * 3. There is no limit on maximum number of type 2 timings.
+ * They can be present not only in basic section but also in the
+ * extension section as well.
+ */
+typedef struct _type2_dtd { /* bytes: [bits] */
+ struct {
+ unsigned short lsb_dclk;
+ unsigned char msb_dclk;
+ } dclk; /* 02-00 [07:00] */
+
+ /* timing options - 1 byte */
+ unsigned char reserved:4; /* 03 [03:00] */
+ unsigned char interlaced:1; /* 03 [04:04] */
+ unsigned char stereo_3d_support:2; /* 03 [06:05] */
+ unsigned char preferred:1; /* 03 [07:07] */
+
+ unsigned short hactive:9; /* 05-04 [08:00] */
+ unsigned short hblank:7; /* 05-04 [15:09] */
+ unsigned char hsync_width:4; /* 06 [03:00] */
+ unsigned char hsync_offset:4; /* 06 [07:04] */
+ unsigned short vactive:12; /* 08-07 [11:00] */
+ unsigned short reserved1:4; /* 08 [15:12] */
+
+ unsigned char vblank; /* 09 [07:00] */
+ unsigned char vsync_width:4; /* 10 [03:00] */
+ unsigned char vsync_offset:4; /* 10 [07:04] */
+} type2_dtd_t;
+
+
+/* Type 3 - DTD - CVT - 3 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 82timings x 3bytes = 246bytes can fit.
+ * 2. As part of parsing, data will be read into type3_cvt_t then
+ * it will be made available for IEGD consumption
+ * either
+ * by marking in standard timing table
+ * or
+ * creating and inserting in pd_timing_t
+ * based on CVT formula.
+ * 3. There is no limit on maximum number of type 3 timings.
+ * They can be present not only in basic section but also in the
+ * extension section as well.
+ */
+typedef struct _type3_cvt { /* bytes: [bits] */
+ /* byte 0 - timing options */
+ unsigned char aspect_ratio:4;
+ unsigned char cvt_formula:3;
+ unsigned char preferred:1;
+
+ /* byte 1 - horizontal active */
+ unsigned char hactive;
+
+ /* byte 2 - other info */
+ unsigned char refresh:7;
+ unsigned char interlaced:1;
+} type3_cvt_t;
+
+/* Structure to emulate bit fields for Type1 Std or Type2 CEA timings */
+typedef struct _type_std {
+ unsigned short width;
+ unsigned short height;
+ unsigned short refresh;
+ unsigned long flags; /* currently interlaced, rb, aspect ratio */
+} type_std_t;
+
+/* Display Device Data Block */
+/* Analog interface subtype codes */
+#define ANALOG_15HD_VGA 0x0
+#define ANALOG_VESA_NAVI_V 0x1
+#define ANALOG_VESA_NAVI_D 0x2
+
+/* Device technology types */
+#define TECH_CRT 0x0
+#define TECH_LVDS 0x1
+#define TECH_PLASMA 0x2
+#define TECH_EL 0x3 /* Electroluminescent */
+#define TECH_INORG 0x4
+#define TECH_ORG 0x5
+#define TECH_FED 0x6 /* FED or sim. "cold cathode" */
+#define TECH_EP 0x7 /* Electrophoretic */
+#define TECH_EC 0x8 /* Electrochromic */
+#define TECH_EM 0x9 /* Electromechanical */
+#define TECH_EW 0xA /* Electrowetting */
+#define TECH_OTHER 0xF /* Othertype not defined here */
+
+/* Device technoloty sub-types */
+#define TECH_CRT_MONO 0x0 /* Mono chrome CRT */
+#define TECH_CRT_STD 0x1 /* Standard tricolor CRT */
+#define TECH_CRT_OTHER 0x2 /* other or undefined */
+
+#define TECH_LVDS_PASSIVE_TN 0x0 /* Passive matrix TN */
+#define TECH_LVDS_PASSIVE_CL 0x1 /* Passive matrix cholesteric LC */
+#define TECH_LVDS_PASSIVE_FE 0x2 /* Passive matrix ferroelectric LC */
+#define TECH_LVDS_PASSIVE_OT 0x3 /* Passive matrix other LC */
+#define TECH_LVDS_ACTIVE_TN 0x4 /* Active matrix TN */
+#define TECH_LVDS_ACTIVE_IPS 0x5 /* Active matrix IPS */
+#define TECH_LVDS_ACTIVE_VA 0x6 /* Active matrix VA */
+#define TECH_LVDS_ACTIVE_OCB 0x7 /* Active matrix OCB */
+#define TECH_LVDS_ACTIVE_FL 0x8 /* Active matrix ferroelectric */
+#define TECH_LVDS_OTHER 0xF /* Other LVDS technology not defined above */
+
+#define TECH_PLASMA_DC 0x0 /* DC plasma */
+#define TECH_PLASMA_AC 0x1 /* AC plasma */
+
+/* Content protection support */
+#define CP_NOCP 0x0
+#define CP_DTCP 0x2
+#define CP_DPCP 0x3 /* Display port content protection */
+
+/* Display physical orientation information */
+#define DEFAULT_ORIENTATION(a) ((a & 0xC0) >> 6)
+#define ZERO_PIXEL(a) ((a & 0x0C) >> 2)
+#define SCAN_DIRECTION(a) (a & 0x03)
+
+#define SCAN_DIRECTION_LONG 0x1 /* Display scan direction (2 bits) */
+#define SCAN_DIRECTION_SHORT 0x2
+
+#define ZP_UPPER_LEFT 0x0 /* Zero pixel position (2 bits) */
+#define ZP_UPPER_RIGHT 0x1
+#define ZP_LOWER_LEFT 0x2
+#define ZP_LOWER_RIGHT 0x3
+
+#define DEF_ORIENTATION_LANDSCAPE 0x0 /* Default orientation (2 bits) */
+#define DEF_ORIENTATION_PORTRAIT 0x1
+#define DEF_ORIENTATION_UNKNOWN 0x2
+
+
+typedef struct _display_device {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char tech_subtype:4;
+ unsigned char tech_type:4;
+ unsigned char reserved1:2;
+ unsigned char can_on_off_bklt:1; /* This bit tells backlight can be
+ * switched on or off using the control
+ * method defined */
+ unsigned char can_change_bklt:1; /* This bit tells backlight intensity
+ * can be changed using the control
+ * method defined */
+ unsigned char op_mode:4;
+
+ unsigned short horz_pixel_count;
+ unsigned short vert_pixel_count;
+ unsigned char aspect_ratio;
+ unsigned char orientation;
+ unsigned char subpixel_info;
+ unsigned char horz_pitch;
+ unsigned char vert_pitch;
+
+ unsigned char display_color_depth:4;
+ unsigned char reserved2:4;
+ unsigned char response_time;
+} display_dev_t;
+
+/* LVDS Interface Timing and Power Sequencing */
+typedef struct _lvds_display {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char max_t1:4;
+ unsigned char min_t1:4;
+
+ unsigned char max_t2:6;
+ unsigned char reserved2:2;
+
+ unsigned char max_t3:6;
+ unsigned char reserved3:2;
+
+ unsigned char min_t4:7;
+ unsigned char reserved4:1;
+
+ unsigned char min_t5:6;
+ unsigned char reserved5:2;
+
+ unsigned char min_t6:6;
+ unsigned char reserved6:2;
+} lvds_display_t;
+
+/* Transfer Characteristics Data Block */
+typedef struct _transfer_char {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+ unsigned char luminance;
+} transfer_char_t;
+
+/* Vendor specific Data Block */
+typedef struct _vendor {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+ unsigned char vendor_id[3]; /* no NULL char */
+ unsigned char vendor_specific_data[246]; /* 245 + NULL */
+} vendor_t;
+
+/* Stereo methods */
+#define STEREO_FIELD_SEQUENTIAL 0x00
+#define STEREO_SIDE_BY_SIDE 0x01
+#define STEREO_PIXEL_INTERLEAVED 0x02
+#define STEREO_DUAL_INTERFACE 0x03
+#define STEREO_MULTIVIEW 0x04
+#define STEREO_PROPRIETARY 0xFF
+
+/* Stereo Display Interface Data Block */
+typedef struct _stereo_intf {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char stereo_intf_payload;
+ unsigned char stereo_intf_method;
+ union {
+ unsigned char stereo_polarity; /* Field Sequential Stereo */
+ unsigned char view_identity; /* Side-by-side Stereo */
+ unsigned char pattern8x8[8]; /* Pixel Interleaved Stereo */
+ unsigned char polarity_mirroring; /* Dual Interface Stereo */
+ struct { /* Multiview stereo */
+ unsigned char num_views;
+ unsigned char interleaving_method;
+ } multiview;
+ /* Note: In case of proprietary stereo method, the parameters can be
+ * somewhere in the Vendor Specific Block */
+ unsigned char stereo_params[8];
+ };
+} stereo_intf_t;
+
+/* Display Interface Data Block */
+#define INTERFACE_ANALOG 0x0
+#define INTERFACE_LVDS 0x1
+#define INTERFACE_TMDS 0x2
+#define INTERFACE_RSDS 0x3
+#define INTERFACE_DVID 0x4
+#define INTERFACE_DVII_A 0x5
+#define INTERFACE_DVII_D 0x6
+#define INTERFACE_HDMI_A 0x7
+#define INTERFACE_HDMI_B 0x8
+#define INTERFACE_MDDI 0x9
+#define INTERFACE_DISP_PORT 0xA
+#define INTERFACE_PROP_DIG 0xB
+
+/* Interface color depth */
+#define INTERFACE_6BPPC 0x01 /* 6 bits per primary color */
+#define INTERFACE_8BPPC 0x02 /* 8 bits per primary color */
+#define INTERFACE_10BPPC 0x04 /* 10 bits per primary color */
+#define INTERFACE_12BPPC 0x08 /* 12 bits per primary color */
+#define INTERFACE_14BPPC 0x10 /* 14 bits per primary color */
+#define INTERFACE_16BPPC 0x20 /* 16 bits per primary color */
+
+typedef struct _display_intf {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char num_channels:4;
+ unsigned char intf_type:4;
+
+ unsigned char intf_revision:4;
+ unsigned char intf_version:4;
+
+ unsigned char rgb_color_depth:6;
+ unsigned char reserved2:2;
+
+ unsigned char ycbcr_444_color_depth:6;
+ unsigned char reserved3:2;
+
+ unsigned char ycbcr_422_color_depth:6;
+ unsigned char reserved4:2;
+
+ unsigned char cp_type:3;
+ unsigned char reserved5:2;
+ unsigned char color_encoding:3;
+
+ unsigned char cp_revision:4;
+ unsigned char cp_version:4;
+
+ unsigned char ss_percent:4;
+ unsigned char reserved6:2;
+ unsigned char ss_type:2;
+
+ union {
+ struct {
+ /* Interface type: LVDS */
+ unsigned char support_3_3v:1;
+ unsigned char support_5v:1;
+ unsigned char support_12v:1;
+ unsigned char support_2_8v:1;
+ unsigned char openldi:1;
+ unsigned char reserved5:3;
+
+ unsigned char data_strobe:1;
+ unsigned char de_polarity:1;
+ unsigned char de_mode:1;
+ unsigned char reserved6:5;
+ } lvds;
+ struct {
+ /* Interface type: Proprietary Digital Interface */
+ unsigned char data_strobe:1;
+ unsigned char de_polarity:1;
+ unsigned char de_mode:1;
+ unsigned char reserved7:5;
+
+ unsigned char reserved8;
+ } pdi;
+ unsigned short bytes9_10;
+ };
+} display_intf_t;
+
+/* Serial Number String */
+typedef struct _serial_number {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char serial_num[249]; /* 248 + NULL */
+} serial_number_t;
+
+/* General Purpose ASCII String */
+typedef struct _general_string {
+ unsigned char tag; /* data block type */
+ unsigned char revision:3;
+ unsigned char reserved:5;
+ unsigned char payload;
+
+ unsigned char string[249]; /* 248 + NULL */
+} general_string_t;
+
+/* This structure holds all of the parsed DisplayID information.*/
+/* 5-required bytes:
+ * 1-byte - version, revision
+ * 1-byte - payload
+ * 1-byte - number of extensions
+ * 1-byte - product type identifier
+ * 1-byte - checksum
+ */
+typedef struct _displayid {
+ unsigned char revision:4; /* HEADER: revision */
+ unsigned char version:4; /* version */
+ unsigned char payload; /* payload excluding 5 required bytes*/
+ unsigned char ptype_id; /* DisplayID product type identifier */
+ unsigned char num_extensions; /* number of extension sections */
+ unsigned char check_sum; /* FOOTER: last byte of the section */
+
+ display_params_t display_params; /* display params block */
+ timing_range_t timing_range; /* timing range block */
+ lvds_display_t lvds; /* LVDS interface & display block */
+ display_dev_t display_dev; /* display device block */
+ display_intf_t display_intf; /* display interface block */
+ unsigned char dummy_db[256]; /* dummy datablock */
+
+ /* Video Timing Modes Type I, II DTDs into pd_timing_t */
+ unsigned char num_timings;
+ pd_timing_t timings[DISPLAYID_MAX_NUM_TIMINGS];
+
+ /* DisplayID attributes */
+ unsigned char num_attrs;
+ pd_attr_t attr_list[DISPLAYID_MAX_ATTRS];
+
+#ifndef CONFIG_MICRO
+ productid_t productid; /* product id block */
+ color_char_t color_char; /* color characteristics block */
+ serial_number_t serial_num; /* serial number ASCII string */
+ general_string_t general_string; /* general purpose ASCII string */
+ transfer_char_t transfer_char; /* transfer characteristics block */
+ stereo_intf_t stereo_intf; /* stereo display interface */
+ vendor_t vendor; /* vendor specific data */
+ igd_DID_rotation_info_t rotation_info; /* display orientation data */
+#endif
+} displayid_t;
+
+/* Pack back to default */
+#pragma pack()
+
+/* Functions */
+void displayid_filter_range_timings(pd_timing_t *tt, timing_range_t *range,
+ unsigned char firmware_type);
+int displayid_parse(unsigned char *buffer, displayid_t *displayid,
+ pd_timing_t *timings, int count, unsigned char upscale);
+
+void displayid_dump(unsigned char *buffer, unsigned short size);
+void displayid_print(unsigned char *buffer, displayid_t *displayid);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/dsp.h b/drivers/gpu/drm/emgd/emgd/include/dsp.h
new file mode 100644
index 0000000..8a803bf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dsp.h
@@ -0,0 +1,46 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DSP_H_
+#define _DSP_H_
+
+#include <mode.h>
+
+/* FIXME: Illegal exports */
+void dsp_dc_init(igd_context_t *context);
+int dsp_alloc(igd_context_t *context, unsigned long dc, unsigned long flags);
+int dsp_wait_rb(igd_context_t *context);
+unsigned long dsp_valid_dc(unsigned long dc, unsigned long flags);
+int dsp_display_connected(igd_context_t *context, igd_display_port_t *port);
+
+
+#endif /* _DSP_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/edid.h b/drivers/gpu/drm/emgd/emgd/include/edid.h
new file mode 100644
index 0000000..829e272
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/edid.h
@@ -0,0 +1,130 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: edid.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Header file for EDID.
+ * Supported EDID versions:
+ * EDID 1.3 (backward compatible with 1.1, 1.2)
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * This is a basic EDID parser. It only parses the parts of the EDID that
+ * are useful for developing timings and identifying the monitor. Items
+ * like monitor serial numbers, chromaticity settings etc. are not useful
+ * in the display drivers. There should be a simple interface to provide
+ * the complete unparsed EDID to IAL, so that such information can be
+ * used by a IAL driver if need be.
+ *
+ * timings_t: This is a structure that contains one set of display timings.
+ * It is complete in that it contains all 12 timings fields instead of
+ * the popular 8. Some of the "Established" EDID timings require all 12
+ * fields. It also allows for both established flags and driver specific
+ * flags to make it flexible enough to work for most drivers. The
+ * EDID parser will mark the flags with FB_TIMINGS_PREFERRED if they are
+ * found to be listed in the EDID. This does not include modes within
+ * the the sync ranges (if provided), only "Established" "Standard" and
+ * "Detailed" timings.
+ *
+ * edid_t: This structure will be populated by the EDID parser. There
+ * are three important areas of information that impact display timings.
+ * The h_max,h_min,v_max,v_min represent the range of timings that the
+ * display is capable of accepting. No timings outside this range should
+ * be used by the driver if a range is provided.
+ *
+ * Any "Detailed" timings will be fully parsed and returned in
+ * the timings array (only the first 12 are parsed, it is very unlikely
+ * that any EDID exist that contain this many).
+ *
+ * Suggested driver behavior when setting display timings would be to
+ * first attempt to use "Detailed" timings provided by the monitor. Then
+ * attempt to use the "Standard" timings that were marked as PREFERRED,
+ * then as a last alternative, use a nonstandard set of timings within
+ * the provided range.
+ *
+ */
+
+#ifndef _EDID_H
+#define _EDID_H
+
+#include <displayid.h>
+#include <pd.h>
+
+/* This structure holds all of the parsed EDID information.*/
+#define NUM_TIMINGS 12
+
+/* EDID return values */
+#define EDID_ERROR_PARSE 1
+#define EDID_READ_AGAIN 2
+
+typedef struct _established_timing {
+ unsigned long width;
+ unsigned long height;
+ unsigned long refresh;
+} established_timing_t;
+
+typedef struct _edid {
+ unsigned char version; /* Edid Version */
+ unsigned char revision; /* Edid Revision */
+ char vendor[4]; /* Vendor Name code */
+ unsigned long product_code; /* Vendor assigned code */
+ unsigned long serial_number; /* 32-bit serial number */
+ unsigned char manf_week; /* Manufactored week number */
+ unsigned long manf_year; /* Manufactored year */
+ unsigned char standard_color;
+ unsigned char preferred_timing; /* Use first timing Provided */
+ unsigned char dpms;
+ unsigned char display_type;
+ unsigned char gtf;
+ unsigned char range_set; /* EDID Contains Valid Range Data */
+ timing_range_t range;
+ unsigned char num_timings;
+ pd_timing_t timings[NUM_TIMINGS];
+ char name[14];
+ cea_extension_t *cea; /* CEA extension based on 861-B */
+} edid_t;
+
+/* Functions */
+int edid_parse(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timings,
+ int count,
+ unsigned char upscale);
+
+void enable_disable_timings(pd_timing_t *timing, unsigned char enable);
+void enable_scaled_timings(pd_timing_t *timing, pd_timing_t *dtd,
+ unsigned char upscale);
+void firmware_dump(unsigned char *buffer, unsigned short size);
+void edid_print(edid_t *edid);
+
+int edid_ext_parse(
+ unsigned char *buffer,
+ edid_t *edid,
+ pd_timing_t *timings,
+ int count,
+ unsigned char upscale);
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/general.h b/drivers/gpu/drm/emgd/emgd/include/general.h
new file mode 100644
index 0000000..159bf23
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/general.h
@@ -0,0 +1,84 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: general.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file includes general equates.
+ * Compiler:
+ * This file contains general constants, structures and should be included
+ * in all noninclude files.
+ *-----------------------------------------------------------------------------
+ */
+
+/*===========================================================================
+; General Constants
+;--------------------------------------------------------------------------*/
+
+#ifndef _GENERAL_H_
+#define _GENERAL_H_
+
+#define BIT0 0x00000001L
+#define BIT1 0x00000002L
+#define BIT2 0x00000004L
+#define BIT3 0x00000008L
+
+#define BIT4 0x00000010L
+#define BIT5 0x00000020L
+#define BIT6 0x00000040L
+#define BIT7 0x00000080L
+
+#define BIT8 0x00000100L
+#define BIT9 0x00000200L
+#define BIT10 0x00000400L
+#define BIT11 0x00000800L
+
+#define BIT12 0x00001000L
+#define BIT13 0x00002000L
+#define BIT14 0x00004000L
+#define BIT15 0x00008000L
+
+#define BIT16 0x00010000L
+#define BIT17 0x00020000L
+#define BIT18 0x00040000L
+#define BIT19 0x00080000L
+
+#define BIT20 0x00100000L
+#define BIT21 0x00200000L
+#define BIT22 0x00400000L
+#define BIT23 0x00800000L
+
+#define BIT24 0x01000000L
+#define BIT25 0x02000000L
+#define BIT26 0x04000000L
+#define BIT27 0x08000000L
+
+#define BIT28 0x10000000L
+#define BIT29 0x20000000L
+#define BIT30 0x40000000L
+#define BIT31 0x80000000L
+
+
+#endif // _GENERAL_H_
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/instr_common.h b/drivers/gpu/drm/emgd/emgd/include/instr_common.h
new file mode 100644
index 0000000..95c7e38
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/instr_common.h
@@ -0,0 +1,54 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr_common.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Common tools for hardware that uses instruction engines.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INSTR_COMMON_H
+#define _IGD_INSTR_COMMON_H
+
+/* Write instructions macro. */
+#ifdef DEBUG_BUILD_TYPE
+#define INSTR_WRITE(data, addr) \
+ if(igd_debug->hal.instr) { \
+ EMGD_DEBUG_S(" addr:%p data:0x%8.8x", ((void *)(addr)), \
+ (unsigned int)(data)); \
+ } \
+ EMGD_WRITE32 (data, (addr)); \
+ addr++;
+
+#define IGD_PRINT_INSTR(name) \
+ if(igd_debug->hal.instr) { \
+ EMGD_DEBUG_S("GMCH Instruction: %s", name); \
+ }
+#else
+#define INSTR_WRITE(data, addr) EMGD_WRITE32(data, (addr)++);
+#define IGD_PRINT_INSTR(name)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/intelpci.h b/drivers/gpu/drm/emgd/emgd/include/intelpci.h
new file mode 100644
index 0000000..b389cc7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/intelpci.h
@@ -0,0 +1,98 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: intelpci.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contains PCI bus transaction definitions
+ *-----------------------------------------------------------------------------
+ */
+
+/* PCI */
+#define PCI_VENDOR_ID_INTEL 0x8086
+#ifndef PCI_VENDOR_ID_STMICRO
+#define PCI_VENDOR_ID_STMICRO 0x104A
+#endif
+
+/* PLB Family Chips */
+#define PCI_DEVICE_ID_BRIDGE_PLB 0x8100
+#define PCI_DEVICE_ID_VGA_PLB 0x8108
+
+/* Atom E6xx */
+#define PCI_DEVICE_ID_BRIDGE_TNC 0x4114
+#define PCI_DEVICE_ID_VGA_TNC 0x4108
+
+/* Atom E6xx ULP */
+#define PCI_DEVICE_ID_BRIDGE_TNC_ULP 0x4115
+
+/* Atom E6xx Device 3 */
+#define PCI_DEVICE_ID_SDVO_TNC 0x8182
+
+/* Atom E6xx Device 31 (LPC) */
+#define PCI_DEVICE_ID_LPC_TNC 0x8186
+
+/* Atom E6xx ST Micro SDVO PCI device */
+#define PCI_DEVICE_ID_SDVO_TNC_ST 0xcc13
+
+/* Atom E6xx ST Micro GPIO SDVO PCI device */
+#define PCI_DEVICE_ID_SDVO_TNC_ST_GPIO 0xcc0c
+
+/* Support for MSRT and Pre-Release PCI ID for Atom E6xx
+ * Can be removed in future */
+#if 0
+/* Atom E6xx A0 Stepping */
+#define PCI_DEVICE_ID_BRIDGE_TNC_A0 0x4110
+#define PCI_DEVICE_ID_VGA_TNC_A0 0x4100
+
+/* Moorestown */
+#define PCI_DEVICE_ID_BRIDGE_LNC 0x4110
+#define PCI_DEVICE_ID_VGA_LNC 0x4102
+#endif
+
+/* Start: Southbridge specific */
+#define PCI_DEVICE_ID_LPC_82801AA 0x2410
+#define PCI_DEVICE_ID_LPC_82801AB 0x2420
+#define PCI_DEVICE_ID_LPC_82801BA 0x2440
+#define PCI_DEVICE_ID_LPC_82801BAM 0x244c
+#define PCI_DEVICE_ID_LPC_82801E 0x2450
+#define PCI_DEVICE_ID_LPC_82801CA 0x2480
+#define PCI_DEVICE_ID_LPC_82801DB 0x24c0
+#define PCI_DEVICE_ID_LPC_82801DBM 0x24cc
+#define PCI_DEVICE_ID_LPC_82801EB 0x24d0
+#define PCI_DEVICE_ID_LPC_82801EBM 0x24dc
+#define PCI_DEVICE_ID_LPC_80001ESB 0x25a1 /* LPC on HanceRapids ICH */
+#define PCI_DEVICE_ID_LPC_82801FB 0x2640 /* ICH6/ICH6R */
+#define PCI_DEVICE_ID_LPC_82801FBM 0x2641 /* ICH6M/ICH6MR */
+#define PCI_DEVICE_ID_LPC_82801FW 0x2642 /* ICH6W/ICH6WR */
+#define PCI_DEVICE_ID_LPC_82801FWM 0x2643 /* ICH6MW/ICH6MWR */
+#define PCI_DEVICE_ID_LPC_Q35DES 0x2910 /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35DHES 0x2912 /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35DOES 0x2914 /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35RES 0x2916 /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35BES 0x2918 /* ICH9 */
+
+
+
+#define INTEL_PTE_ALLIGNMENT 0xFFFFF000
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/math_fix.h b/drivers/gpu/drm/emgd/emgd/include/math_fix.h
new file mode 100644
index 0000000..91306fe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/math_fix.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains OS abstracted interfaces to fixed point math functions
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_MATH_FIX_H
+#define _OAL_MATH_FIX_H
+
+
+#define OS_POW_FIX(b, p) os_pow_fix(b, p)
+
+
+#define OS_MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define OS_MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+/*****************************************************************************
+ * Function: os_pow_fix
+ *
+ * Parameters:
+ * [IN] base: the base, should be between 0 and 255.
+ * [IN] power: this must be in 24i.8f format.
+ *
+ * Description:
+ * This function uses the Taylor Series to approximate the power function
+ * using fixed-point math.
+ *
+ ****************************************************************************/
+
+unsigned int os_pow_fix( const int base, const int power );
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/memlist.h b/drivers/gpu/drm/emgd/emgd/include/memlist.h
new file mode 100644
index 0000000..5801fef
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/memlist.h
@@ -0,0 +1,153 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memlist.h
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the header information for the chunk layer of gmm.
+ * It should not be included outside gmm.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MEMLIST_H
+#define _MEMLIST_H
+
+#include <gart.h>
+#include <igd_gmm.h>
+#include <context.h>
+#include <drmP.h>
+
+#define GMM_NODE_FREE 0x0
+#define GMM_NODE_USED 0x1
+#define GMM_NODE_FIXED 0x2
+
+/****************************************************************************
+ * gmm_node_t
+ * This structure is an individual node representing an range of memory.
+ * It may be allocated or free.
+ ****************************************************************************/
+typedef struct _gmm_node {
+ struct _gmm_node *next;
+ struct _gmm_node *previous;
+ unsigned long start;
+ unsigned long end;
+ unsigned long size;
+ unsigned long status;
+ os_gart_allocation_t gart_handle;
+ unsigned long phys;
+#ifdef DEBUG_BUILD_TYPE
+ char desc[GMM_DEBUG_DESC_SIZE];
+ unsigned long pixel_format; /* Pixel Format == 0 for Regions */
+ unsigned int width;
+ unsigned int height;
+ unsigned int pitch;
+ unsigned int type;
+ unsigned long flags;
+#endif
+}gmm_node_t;
+
+#ifdef DEBUG_BUILD_TYPE
+extern unsigned long _gmm_debug_pixel_format;
+extern unsigned int _gmm_debug_width;
+extern unsigned int _gmm_debug_height;
+extern unsigned int _gmm_debug_pitch;
+extern unsigned int _gmm_debug_type;
+extern unsigned long _gmm_debug_flags;
+
+#define GMM_SET_DEBUG_INFO(pf, w, h, p, t, f) \
+ _gmm_debug_pixel_format = pf; \
+ _gmm_debug_width = w; \
+ _gmm_debug_height = h; \
+ _gmm_debug_pitch = p; \
+ _gmm_debug_type = t; \
+ _gmm_debug_flags = f;
+
+#else
+#define GMM_SET_DEBUG_INFO(pf, w, h, p, t, f)
+#endif
+
+/*
+ * Flags used when creating chunks or when requesting space from existing
+ * chunks.
+ */
+#define GMM_CHUNK_FREE 0x0
+#define GMM_CHUNK_LINEAR 0x1
+#define GMM_CHUNK_FENCED 0x2
+#define GMM_CHUNK_YMAJOR 0x4
+/*
+ * Reserved chunks are marked with this flag. Only a single surface may
+ * be allocated in reserved chunks. Reserved chunks may or may not have
+ * a fence pre-allocated.
+ */
+#define GMM_CHUNK_RESERVED 0x8
+#define GMM_CHUNK_TYPE_MASK 0xf
+
+typedef struct _gmm_mem_buffer {
+ unsigned long size;
+ unsigned long type;
+ unsigned long physical;
+ struct page **pages;
+ int page_count;
+ int vmalloc_flag;
+} gmm_mem_buffer_t;
+
+typedef struct _gmm_chunk {
+ /* Next chunk in the list */
+ struct _gmm_chunk *next;
+ /* Previous chunk in the list */
+ struct _gmm_chunk *previous;
+ /* Current chunk usage state */
+ enum {
+ INUSE_ALLOCATED,
+ FREE_ALLOCATED, /* gmm-allocated pages attached */
+ INUSE_IMPORTED,
+ FREE_IMPORTED /* address space only; no pages attached */
+ } usage;
+ /* The offset of the allocated memory, after alignment */
+ unsigned long offset;
+ /* The number of bytes of memory requested/allocated for this chunk */
+ unsigned long size;
+ /* The number of pages of memory required for "size" bytes */
+ unsigned long pages;
+ /* A boolean flag indicating if the chunk's memory has been bound by AGP */
+ unsigned long bound;
+ /* Either AGP_PHYS_MEMORY or AGP_NORMAL_MEMORY */
+ unsigned long type;
+ gmm_mem_buffer_t *gtt_mem;
+ void *addr;
+ unsigned long ref_cnt;
+ /* An array of page addresses (created by gmm_get_page_list() */
+ unsigned long *page_addresses;
+} gmm_chunk_t;
+
+typedef struct _gmm_context_t {
+ unsigned long max_mem;
+ gmm_chunk_t *head_chunk;
+ gmm_chunk_t *tail_chunk;
+ igd_memstat_t memstat;
+ igd_context_t *context;
+ igd_gtt_info_t *gtt;
+} gmm_context_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/memory.h b/drivers/gpu/drm/emgd/emgd/include/memory.h
new file mode 100644
index 0000000..f85477c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/memory.h
@@ -0,0 +1,421 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memory.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains OS abstracted interfaces to common memory operations.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_MEMORY_H
+#define _OAL_MEMORY_H
+
+#include <linux/slab.h>
+
+unsigned long os_gart_alloc_page( void );
+unsigned long os_gart_virt_to_phys( unsigned char *a );
+void os_gart_free_page( unsigned char *a );
+
+/* #define INSTRUMENT_KERNEL_ALLOCS */
+#ifdef INSTRUMENT_KERNEL_ALLOCS
+#define MAX_FUNC_NAME 64
+
+typedef struct _os_allocd_mem {
+ void *ptr;
+ unsigned int size;
+ char function[MAX_FUNC_NAME];
+ struct _os_allocd_mem *next;
+} os_allocd_mem;
+
+extern os_allocd_mem *list_head;
+extern os_allocd_mem *list_tail;
+
+static inline void *_os_alloc(unsigned int size, const char *function) {
+ os_allocd_mem *mem;
+ void *ptr = kmalloc(size, GFP_KERNEL);
+ printk(KERN_DEBUG "%s OS_ALLOC(size=%u)=0x%p\n", function, size, ptr);
+ mem = kmalloc(sizeof(os_allocd_mem), GFP_KERNEL);
+ if (!ZERO_OR_NULL_PTR(mem)) {
+ mem->ptr = ptr;
+ mem->size = size;
+ strncpy(mem->function, function, MAX_FUNC_NAME);
+ mem->function[MAX_FUNC_NAME-1] = '\0';
+ mem->next = NULL;
+ if (NULL == list_tail) {
+ list_head = mem;
+ } else {
+ list_tail->next = mem;
+ }
+ list_tail = mem;
+ }
+ return ptr;
+}
+
+static inline void _os_free(void *ptr, const char *function) {
+ printk(KERN_DEBUG "%s OS_FREE(0x%p)\n", function, ptr);
+ if (NULL != list_head) {
+ os_allocd_mem *mem = list_head;
+ os_allocd_mem *prev = NULL;
+ while (NULL != mem) {
+ if (mem->ptr == ptr) {
+ if (mem == list_head) {
+ list_head = mem->next;
+ if (mem == list_tail) {
+ list_tail = NULL;
+ }
+ } else {
+ prev->next = mem->next;
+ if (mem == list_tail) {
+ list_tail = prev;
+ }
+ }
+ kfree(mem);
+ break;
+ }
+ prev = mem;
+ mem = mem->next;
+ }
+ }
+ kfree(ptr);
+}
+
+static inline void emgd_report_unfreed_memory(void) {
+ os_allocd_mem *mem = list_head;
+ os_allocd_mem *prev;
+
+ printk(KERN_DEBUG "%s() REPORT ON NON-FREED MEMORY:\n", __FUNCTION__);
+ while (NULL != mem) {
+ printk(KERN_DEBUG " addr=0x%p, size=%u, function=\"%s\"\n",
+ mem->ptr, mem->size, mem->function);
+ prev = mem;
+ mem = mem->next;
+ kfree(prev);
+ }
+}
+
+
+/*!
+ * void *OS_ALLOC(size_t size)
+ *
+ * OS_ALLOC is used by OS independent code to allocate system memory and
+ * return a CPU writeable address to the allocated memory (Virtual address)
+ * The returned address has no guarenteed alignment.
+ * size should be <= 4k for larger sizes use OS_ALLOC_LARGE().
+ *
+ * Allocations returned from OS_ALLOC() should be freed with OS_FREE().
+ *
+ * All Full OAL implementations must implement the _OS_ALLOC entry point
+ * to enable use of this function.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC(a) _os_alloc(a, __FUNCTION__)
+
+/*!
+ * void OS_FREE(void *p)
+ * OS_FREE should be used to free allocations returned from OS_ALLOC()
+ *
+ * All Full OAL implementations must implement the _OS_FREE entry point
+ * to enable use of this function.
+ */
+#define OS_FREE(a) _os_free(a, __FUNCTION__)
+
+/*!
+ * void *OS_ALLOC_LARGE(size_t size)
+ *
+ * OS_ALLOC_LARGE is used by OS independent code to allocate system memory
+ * in the same manner as OS_ALLOC except that size must be > 4k.
+ *
+ * Allocations returned from OS_ALLOC_LARGE() should be freed with
+ * OS_FREE_LARGE().
+ *
+ * All Full OAL implementations must implement the _OS_ALLOC_LARGE entry point
+ * to enable use of this function. This entry point may be implemented
+ * exactly the same as _OS_ALLOC is no diferentiation is required.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC_LARGE(a) _os_alloc(a, __FUNCTION__)
+
+/*!
+ * void OS_FREE_LARGE(void *p)
+ * OS_FREE_LARGE should be used to free allocations returned from
+ * OS_ALLOC_LARGE()
+ *
+ * All Full OAL implementations must implement the _OS_FREE_LARGE entry point
+ * to enable use of this function. This entry point may be implemented
+ * exactly the same as _OS_FREE is no diferentiation is required.
+ *
+ */
+#define OS_FREE_LARGE(a) _os_free(a, __FUNCTION__)
+
+#else /* INSTRUMENT_KERNEL_ALLOCS */
+
+#define OS_ALLOC(a) kmalloc((a), GFP_KERNEL)
+#define OS_FREE(a) kfree(a)
+#define OS_ALLOC_LARGE(a) kmalloc((a), GFP_KERNEL)
+#define OS_FREE_LARGE(a) kfree(a)
+
+#endif /* INSTRUMENT_KERNEL_ALLOCS */
+
+#define OS_ALLOC_PAGE() NULL
+/*!
+ * void *OS_VIRT_TO_PHYS( void *p )
+ *
+ * OS_VIRT_TO_PHYS is used by OS independent code to obtain the physical
+ * address referenced by the virtual address p. The virtual address must be
+ * one returned by OS_ALLOC_PAGE or OS_ALLOC_CONTIGUOUS.
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have
+ * implemented the _OS_ALLOC_PAGE or _OS_ALLOC_CONTIGUOUS macros need
+ * implement the _OS_VIRT_TO_PHYS macro. OS independent code that must
+ * function on all implementation may not use this entry point.
+ *
+ * @returns Physical Address
+ */
+#define OS_VIRT_TO_PHYS(a) os_gart_virt_to_phys(a)
+
+/*!
+ * void OS_FREE_PAGE(void *p)
+ * OS_FREE_PAGE should be used to free allocations returned from
+ * OS_ALLOC_PAGE()
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have implemented
+ * the _OS_ALLOC_PAGE macro need implement the _OS_FREE_PAGE macro.
+ */
+#define OS_FREE_PAGE(a) os_gart_free_page(a)
+
+#define OS_MEMSET(a,b,c) memset(a,b,c)
+#define OS_MEMCPY(a,b,c) memcpy(a,b,c)
+#define OS_MEMCMP(a,b,c) memcmp(a,b,c)
+
+#define OS_OFFSETOF(t,m) offsetof(t,m)
+
+
+/*
+ * void *OS_MEMSET(void *s, int c, size_t n)
+ *
+ * OS_MEMSET sets all bytes of the memory area referenced by address s and
+ * size n to the char value c.
+ *
+ * ALL Full OAL implementations must implement the entry point _OS_MEMSET
+ * to enable use of this function.
+ *
+ * @returns Address s
+ */
+#ifndef OS_MEMSET
+#define OS_MEMSET(a,b,c) _oal_memset(a,b,c)
+#endif
+
+/*
+ * void *OS_MEMCPY(void *dest, void *src, size_t n)
+ *
+ * OS_MEMCPY copies n bytes from the memory referenced by src to the
+ * memory referenced by dest. The areas may not overlap.
+ *
+ * ALL Full OAL implementations must implement the entry point _OS_MEMCPY
+ * to enable use of this function.
+ *
+ * @returns Address dest
+ */
+#ifndef OS_MEMCPY
+#define OS_MEMCPY(a,b,c) _oal_memcpy(a,b,c)
+#endif
+
+/*
+ * void *OS_MEMCMP(void *s1, void *s2, size_t n)
+ *
+ * OS_MEMCMP compares n bytes from the memory referenced by s1 to the
+ * corresponding bytes referenced by s2.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMCMP macro or the built-in version will be used.
+ *
+ * @returns < 0 if the s1 value is less than s2
+ * @returns > 0 if the s1 value is greater than s2
+ * @returns 0 if the values are equal
+ */
+#ifndef OS_MEMCMP
+#define OS_MEMCMP(a,b,c) _oal_memcmp(a,b,c)
+#endif
+
+
+/*
+ * void *OS_MEMZERO(void *s, size_t n)
+ *
+ * OS_MEMZERO sets all bytes of the memory area referenced by address s and
+ * size n to 0.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMZERO macro or the built-in version making use of
+ * of _OS_MEMSET will be used.
+ *
+ * @returns Address s
+ */
+#ifndef OS_MEMZERO
+#define OS_MEMZERO(a,b) OS_MEMSET(a, 0, b)
+#endif
+
+/*
+ * void *OS_MEMZERO(void *s, size_t n)
+ *
+ * OS_MEMZERO sets all bytes of the memory area referenced by address s and
+ * size n to 0.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMZERO macro or the built-in version making use of
+ * of _OS_MEMSET will be used.
+ *
+ * @returns Address s
+ */
+#ifndef OS_STRNCPY
+#define OS_STRNCPY(d, s, n) _oal_strncpy(d, s, n)
+#endif
+
+
+
+
+
+/*!
+ * void *OS_ALLOC_CONTIGUOUS( size_t n, size_t align )
+ *
+ * OS_ALLOC_CONTIGUOUS is used by OS independent code to allocate a number
+ * of aligned system memory pages and return a CPU writeable address to the
+ * allocated memory (Virtual address) The returned address must point to
+ * physically contiguous memory aligned to the requested alignment.
+ *
+ * Allocations returned from OS_ALLOC_CONTIGUOUS() should be freed with
+ * OS_FREE_CONTIGUOUS().
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have the
+ * ability to allocate such pages need implement the _OS_ALLOC_CONTIGUOUS
+ * macro. OS independent code that must function on all implementation may
+ * not use this entry point.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC_CONTIGUOUS(a,b) _OS_ALLOC_CONTIGUOUS(a,b)
+/*!
+ * void OS_FREE_CONTIGUOUS(void *p)
+ * OS_FREE_CONTIGUOUS should be used to free allocations returned from
+ * OS_ALLOC_CONTIGUOUS()
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have implemented
+ * the _OS_ALLOC_CONTIGUOUS macro need implement the _OS_FREE_CONTIGUOUS macro.
+ */
+#define OS_FREE_CONTIGUOUS(a) _OS_FREE_CONTIGUOUS(a)
+
+/*!
+ * size_t OS_OFFSETOF(type, member)
+ *
+ * OS_OFFSETOF is used by OS independent code to obtain the offset of a
+ * given member within a type.
+ *
+ * @returns size_t of the offset of member m within type t
+ */
+#ifndef OS_OFFSETOF
+#define OS_OFFSETOF(t,m) ((size_t)&(((t *)0)->m))
+#endif
+
+/*
+ * This is a OS independent helper is case the operating environment
+ * does not supply a memcmp() function. The OAL may use this implementation.
+ */
+static __inline int _oal_memcmp(const void *s1, const void *s2, unsigned long n)
+{
+ const unsigned char *cs1 = (const unsigned char *) s1;
+ const unsigned char *cs2 = (const unsigned char *)s2;
+
+ for ( ; n-- > 0; cs1++, cs2++) {
+ if (*cs1 != *cs2) {
+ return *cs1 - *cs2;
+ }
+ }
+ return 0;
+}
+
+static __inline void *_oal_memcpy(void *dest, const void *src, size_t n)
+{
+ size_t i;
+
+ i=0;
+ while( i < n ) {
+ ((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
+ i++;
+ }
+ return dest;
+}
+
+static __inline char *_oal_strncpy(char *dest, const char *src, size_t n)
+{
+ size_t i;
+
+ for(i=0; i<n; i++) {
+ if(!(dest[i] = src[i])) {
+ for(i=i; i<n; i++) {
+ dest[i] = '\0';
+ }
+ return dest;
+ }
+ }
+ return dest;
+}
+
+static __inline void *_oal_memset(void *s, int c, size_t n)
+{
+ unsigned int i;
+ for(i=0; i<n; i++) {
+ ((unsigned char *)s)[i] = (unsigned char)c;
+ }
+ return s;
+}
+
+/*
+ * These macros are optional for the OAL port. They are used to do memory
+ * management for virtual apterture space process.
+ */
+
+#ifdef _OS_MAP_STOLEN_MEM
+#define OS_MAP_STOLEN_MEM(a, b, c) _OS_MAP_STOLEN_MEM(a, b, c)
+#else
+#define OS_MAP_STOLEN_MEM(a, b, c) 0
+#endif
+
+#ifdef _OS_VIRT_APERT_AVAILABLE
+#define OS_VIRT_APERT_AVAILABLE() _OS_VIRT_APERT_AVAILABLE()
+#else
+#define OS_VIRT_APERT_AVAILABLE() 0
+#endif
+
+#ifdef _OS_GET_VIRT_APERT_BASE
+#define OS_GET_VIRT_APERT_BASE() _OS_GET_VIRT_APERT_BASE()
+#else
+#define OS_GET_VIRT_APERT_BASE() NULL
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/mode.h b/drivers/gpu/drm/emgd/emgd/include/mode.h
new file mode 100644
index 0000000..1cb8a2c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/mode.h
@@ -0,0 +1,444 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contain header information for set mode support
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MODE_H_
+#define _MODE_H_
+
+/* IO.h is needed for the FAR define */
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <general.h>
+#include <context.h>
+#include <cmd.h>
+#include <pd.h>
+#include <edid.h>
+#include <displayid.h>
+#include <igd_render.h>
+
+/* KMS-related Headers */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_fb_helper.h>
+
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define IGD_INVALID_MODE 0
+
+/*****************/
+/* Plane Features */
+/*****************/
+#define IGD_PLANE_FEATURES_MASK 0x000000FF
+#define IGD_PLANE_DISPLAY 0x00000001
+#define IGD_PLANE_OVERLAY 0x00000002
+#define IGD_PLANE_SPRITE 0x00000004
+#define IGD_PLANE_CURSOR 0x00000008
+#define IGD_PLANE_VGA 0x00000010
+#define IGD_PLANE_DOUBLE 0x00000020
+/*#define IGD_PLANE_CLONE 0x00000040 currently unused */
+#define IGD_PLANE_DIH 0x00000080
+#define IGD_PLANE_USE_PIPEA 0x00000100
+#define IGD_PLANE_USE_PIPEB 0x00000200
+
+/*****************/
+/* Pipe Features */
+/*****************/
+/* pipe's supported features */
+#define IGD_PIPE_FEATURES_MASK 0x000000FF
+#define IGD_PIPE_DOUBLE 0x00000001
+/* the following 2 bits are not pipe features but
+ * pipe identification bits that share the same
+ * pipe_features variable of the pipe structure
+ * NOTE that these bit-wise OR flags in nibble-2
+ * are also used in the port_features variable
+ * of the port structure (same locations) but
+ * called IGD_PORT_USE_PIPEX
+ */
+#define IGD_PIPE_IS_PIPEA 0x00000100
+#define IGD_PIPE_IS_PIPEB 0x00000200
+
+/*******************/
+/* Cursor Features */
+/*******************/
+/*
+ * Cursor's supported features
+ */
+/*
+ * cursor's pipe usage regulations. These are copies of the PIPE_IS_ bits so
+ * that a quick (pipe_features & plane_features & MASK) will tell you if
+ * the pipe can be used.
+ */
+#define IGD_CURSOR_USE_PIPE_MASK 0x00000F00
+#define IGD_CURSOR_USE_PIPEA IGD_PIPE_IS_PIPEA
+#define IGD_CURSOR_USE_PIPEB IGD_PIPE_IS_PIPEB
+
+/*****************/
+/* Port features */
+/*****************/
+/*
+ * Port's supported features
+ *
+ * port features also uses IGD_PORT_SHARE_MASK thus port feature bits
+ * cannot collide with IGD_PORT_SHARE_MASK
+ */
+#define IGD_PORT_FEATURES_MASK 0x000000FF
+#define IGD_RGBA_COLOR 0x00000001
+#define IGD_RGBA_ALPHA 0x00000002
+#define IGD_VGA_COMPRESS 0x00000004 /* Compress VGA to 640x480 */
+#define IGD_PORT_GANG 0x00000008
+/*
+ * port's pipe usage regulations. These are copies of the PIPE_IS_ bits so
+ * that a quick (pipe_features & port_features & MASK) will tell you if
+ * the pipe can be used.
+ */
+#define IGD_PORT_USE_PIPE_MASK 0x00000F00
+#define IGD_PORT_USE_PIPE_MASK_SHIFT 8
+#define IGD_PORT_USE_PIPEA IGD_PIPE_IS_PIPEA
+#define IGD_PORT_USE_PIPEB IGD_PIPE_IS_PIPEB
+/*
+ * Ports Sharing information. The port in question can share a pipe with the
+ * listed ports. If a shares with b, b must share with a too.
+ * Must be the same as IGD_PORT_MASK = 0x3f000
+ */
+#define IGD_PORT_SHARE_MASK IGD_PORT_MASK
+#define IGD_PORT_SHARE_ANALOG IGD_PORT_ANALOG
+#define IGD_PORT_SHARE_DIGITAL IGD_PORT_DIGITAL
+#define IGD_PORT_SHARE_LVDS IGD_PORT_LVDS
+#define IGD_PORT_SHARE_TV IGD_PORT_TV
+
+/* MAX rings, planes and ports connected to a pipe */
+#define IGD_MAX_PIPE_QUEUES 4
+#define IGD_MAX_PIPE_PLANES 5
+#define IGD_MAX_PIPE_DISPLAYS 4
+#define IGD_MAX_PIPES 2
+#define MAX_DISPLAYS IGD_MAX_DISPLAYS /* From igd_mode.h */
+
+/* Parameters to mode_update_plane_pipe_ports */
+#define MODE_UPDATE_PLANE 0x1
+#define MODE_UPDATE_PIPE 0x2
+#define MODE_UPDATE_PORT 0x4
+#define MODE_UPDATE_NONE 0x0
+
+#define PLANE(display) \
+ ((igd_display_plane_t *)(((igd_display_context_t *)display)->plane))
+#define PIPE(display) \
+ ((igd_display_pipe_t *)(((igd_display_context_t *)display)->pipe))
+#define PORT(display, pn) \
+ ((igd_display_port_t *)(((igd_display_context_t *)display)->port[pn-1]))
+#define PORT_OWNER(display) \
+ ((igd_display_port_t *)(((igd_display_context_t *)display)->port[display->port_number-1]))
+
+#define MODE_IS_SUPPORTED(t) (t->mode_info_flags & IGD_MODE_SUPPORTED)
+#define MODE_IS_VGA(t) \
+ ((((pd_timing_t *)t)->mode_info_flags & IGD_MODE_VESA) && \
+ (t->mode_number < 0x1D))
+
+#define IGD_KMS_PIPEA (IGD_PIPE_IS_PIPEA >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+#define IGD_KMS_PIPEB (IGD_PIPE_IS_PIPEB >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+
+#define KMS_PIPE_FEATURES(display) \
+ (((igd_display_pipe_t *)((igd_display_context_t *)display)->pipe)->pipe_features)
+
+#define KMS_PIPE_ID(pipe_features) \
+ ((pipe_features & IGD_PORT_USE_PIPE_MASK) >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+
+
+/* #define DC_PORT_NUMBER(dc, i) ((dc >> (i * 4)) & 0x0f) */
+#define DC_PORT_NUMBER IGD_DC_PORT_NUMBER
+
+/* This structure is used for the mode table which is a list of all
+ * supported modes. */
+
+typedef pd_timing_t igd_timing_info_t, *pigd_timing_info_t;
+
+
+/*
+ * NOTE: The plane typedef is a generic type. Each plane type has an
+ * equivalent typedef that is more specific to the type of plane. They
+ * MUST remain equivalent. If you change one you must change them all.
+ */
+typedef struct _igd_plane {
+ unsigned long plane_reg; /* plane control register */
+ unsigned long plane_features; /* plane feature list */
+ int inuse; /* plane inuse ? */
+ int ref_cnt; /* # of displays using this plane */
+ unsigned long *pixel_formats; /* supported pixel formats */
+ void *plane_info; /* ptr to plane_info */
+ struct _igd_plane *mirror; /* pointer to mirror plane */
+} igd_plane_t;
+
+typedef struct _igd_display_plane {
+ unsigned long plane_reg; /* plane contron register */
+ unsigned long plane_features; /* list of plane features */
+ int inuse; /* plane inuse ? */
+ int ref_cnt; /* # of displays using this plane */
+ unsigned long *pixel_formats; /* list of pixel formats supported */
+ igd_framebuffer_info_t *fb_info; /* attached fb to this plane */
+ struct _igd_display_plane *mirror; /* pointer to mirror plane */
+} igd_display_plane_t, *pigd_display_plane_t;
+
+typedef struct _igd_cursor {
+ unsigned long cursor_reg; /* cursor control register */
+ unsigned long plane_features; /* cursor plane features */
+ int inuse; /* is this cursor in use? */
+ int ref_cnt; /* # of displays using this plane */
+ unsigned long *pixel_formats; /* list of pixel_formats supported */
+ igd_cursor_info_t *cursor_info;
+ struct _igd_cursor *mirror; /* pointer to mirror plane */
+} igd_cursor_t;
+
+typedef struct _igd_clock {
+ unsigned long dpll_control; /* DPLL control register */
+ unsigned long mnp; /* FPx0 register */
+ unsigned long p_shift; /* Bit location of P within control */
+ unsigned long actual_dclk; /* Actual dotclock after calculating dpll */
+}igd_clock_t;
+
+typedef struct _igd_display_pipe {
+ unsigned long pipe_num; /* 0 Based index */
+ unsigned long pipe_reg; /* pipe configuration register */
+ unsigned long timing_reg; /* timing register(htotal) */
+ unsigned long palette_reg; /* palette register */
+ igd_clock_t *clock_reg; /* DPLL clock registers */
+ unsigned long pipe_features; /* pipe features */
+ int inuse; /* pipe allocated? TRUE/FALSE */
+ int ref_cnt; /* # of displays using this pipe */
+ cmd_queue_t *queue[IGD_MAX_PIPE_QUEUES]; /* Queues for this pipe */
+ igd_display_plane_t *plane; /* dsp plane connected to pipe */
+ igd_cursor_t *cursor; /* cursor connected to this pipe */
+ void *sprite; /* sprite connected to this pipe */
+ igd_timing_info_t *timing; /* current timings on the port */
+ igd_display_context_t *owner; /* owner display of this pipe */
+ unsigned long dclk; /* current dclk running on this pipe */
+}igd_display_pipe_t, *pigd_display_pipe_t;
+
+typedef struct _igd_display_port {
+ unsigned long port_type; /* port type */
+ unsigned long port_number; /* port number */
+ char port_name[8]; /* port name DVO A, B, C, LVDS, ANALOG */
+ unsigned long port_reg; /* port control register */
+ unsigned long i2c_reg; /* GPIO pins for i2c on this port */
+ unsigned long dab; /* i2c Device Address Byte */
+ unsigned long ddc_reg; /* GPIO pins for DDC on this port */
+ unsigned long ddc_dab;
+ unsigned long port_features; /* port features */
+ unsigned long clock_bits; /* Clock input to use */
+ int inuse; /* port is in use */
+ unsigned long power_state; /* D Power state for the display/port */
+ unsigned long bl_power_state; /* D Power state for the FP backlight */
+ struct _igd_display_port *mult_port;/* pointer to multiplexed port,
+ * if it is used in that way */
+ igd_display_info_t *pt_info; /* port timing info */
+ pd_driver_t *pd_driver;
+ void *pd_context; /* Context returned from PD */
+ pd_callback_t *callback; /* DD Callback to passed to PD */
+ unsigned long num_timing; /* number of timings available */
+ igd_timing_info_t *timing_table; /* static/dynamic PD timings list */
+ unsigned long i2c_speed; /* Connected encoder's I2C bus speed */
+ unsigned long ddc_speed; /* DDC speed in KHz */
+ igd_param_fp_info_t *fp_info; /* Flat panel parameter info if any */
+ igd_param_dtd_list_t *dtd_list; /* EDID-less DTD info if any */
+ igd_param_attr_list_t *attr_list; /* Saved attributes if any */
+ igd_attr_t *tmp_attr; /* Temp attr array, for copying */
+ unsigned int tmp_attr_num; /* Number of attr in temp array */
+ igd_timing_info_t *fp_native_dtd; /* FP native DTD */
+ unsigned long pd_type; /* Display type given by port driver */
+ unsigned long pd_flags; /* port driver flags */
+ unsigned long saved_bl_power_state;
+
+ /* This attribute list is designed to eventually suck in things above
+ * such as fb_info. For now, it only has color correction attributes */
+ igd_attr_t *attributes;
+
+ unsigned char firmware_type;
+ union {
+ displayid_t *displayid;
+ edid_t *edid; /* EDID information */
+ };
+
+ /* Added for VBIOS size Reduction */
+ unsigned long preserve;
+ unsigned long mult_preserve;
+ unsigned long vga_sync;
+
+}igd_display_port_t, *pigd_display_port_t;
+
+/* This structure is used to save mode state.
+ * Rightnow, it is saving state of current port and its port driver state.
+ * This information is used while restoring to a previously saved mode
+ * state.
+ * TODO: This can be extended to save all display modules (mode, dsp, pi) reg
+ * information along with port driver's state information. This requires
+ * changes to exiting reg module. */
+#define MAX_PORT_DRIVERS 20
+typedef struct _mode_pd_state {
+ igd_display_port_t *port; /* display port */
+ void *state; /* and its port driver state */
+} mode_pd_state_t;
+
+typedef struct _mode_state_t {
+ mode_pd_state_t pd_state[MAX_PORT_DRIVERS];
+} mode_state_t;
+
+
+/**
+ * This holds information about a framebuffer
+ */
+typedef struct _emgd_framebuffer {
+ struct drm_framebuffer base;
+ enum {
+ GMM_FRAMEBUFFER,
+ PVR_FRAMEBUFFER
+ } type;
+ void *pvr_meminfo;
+ struct page **pagelist;
+ unsigned long gtt_offset;
+ unsigned long handle;
+} emgd_framebuffer_t;
+
+typedef struct _emgdfb_par {
+ struct drm_device *dev;
+ emgd_framebuffer_t *emgd_fb;
+} emgdfb_par_t;
+
+
+/**
+ * This holds information about a CRTC.
+ */
+typedef struct _emgd_crtc {
+ struct drm_crtc base;
+
+ /* Spinlock to protect access to this structure */
+ spinlock_t crtc_lock;
+
+ int crtc_id;
+ igd_display_pipe_t *igd_pipe;
+ emgd_framebuffer_t *fbdev_fb;
+ struct drm_mode_set mode_set;
+ struct drm_display_mode saved_mode;
+ struct drm_display_mode saved_adjusted_mode;
+ unsigned char lut_r[256];
+ unsigned char lut_g[256];
+ unsigned char lut_b[256];
+ unsigned char lut_a[256];
+
+ /* Flip request work task */
+ struct work_struct flip_work;
+ unsigned char flip_work_queued;
+
+ /*
+ * Framebuffer that we're in the process of flipping to (may not
+ * actually show up until rendering is complete, the actual
+ * registers are programmed, and a vblank happens).
+ */
+ emgd_framebuffer_t *newfb;
+
+ /*
+ * Target for rendering completion to allow flip to proceed.
+ * Rendering operations may continue to be dispatched against this
+ * FB after the flip ioctl is called, so we need to track the
+ * number of pending operations at the point the ioctl was called
+ * and use that as our target to flip on.
+ */
+ unsigned long render_complete_at;
+
+ /*
+ * Are we waiting for the next vblank event to perform flip cleanup
+ * on this CRTC? Flip cleanup primarily involves sending a
+ * notification event back to userspace.
+ */
+ unsigned char vblank_expected;
+
+ /* Userspace event to send back upon flip completion. */
+ struct drm_pending_vblank_event *flip_event;
+} emgd_crtc_t;
+
+
+/**
+ * This holds information about an individual encoder
+ * */
+typedef struct _emgd_encoder {
+ struct drm_encoder base;
+
+ unsigned long crtc_mask;
+ unsigned long clone_mask;
+ igd_display_port_t *igd_port;
+ mode_pd_state_t state;
+ /* flags is a bit mask. For information
+ * on the different masks, see ENCODER_FLAG_xx
+ */
+ unsigned long flags;
+} emgd_encoder_t;
+
+#define ENCODER_FLAG_FIRST_DPMS 0x1
+#define ENCODER_FLAG_FIRST_ALTER 0x2
+#define ENCODER_FLAG_SEAMLESS 0x4
+
+/**
+ * * This holds information about an individual output
+ * */
+typedef struct _emgd_connector {
+ struct drm_connector base;
+
+ emgd_encoder_t *encoder;
+ unsigned long type;
+ struct drm_property **properties;
+ unsigned long num_of_properties;
+
+ struct _drm_emgd_private *priv;
+} emgd_connector_t;
+
+/**
+ * * This holds information on our framebuffer device.
+ * */
+typedef struct _emgd_fbdev {
+ struct drm_fb_helper helper;
+
+ emgd_framebuffer_t *emgd_fb;
+ u32 pseudo_palette[17];
+ struct list_head fbdev_list;
+ struct _drm_emgd_private *priv;
+} emgd_fbdev_t;
+
+
+
+
+#endif // _IGD_MODE_H_
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/mode_access.h b/drivers/gpu/drm/emgd/emgd/include/mode_access.h
new file mode 100644
index 0000000..307739a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/mode_access.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_access.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Contains functional support to set video mode
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_MODEACCESS_H
+#define _IGD_MODEACCESS_H
+
+#include <mode.h>
+#include <context.h>
+
+extern int mode_getresolution(igd_display_h display_h,
+ unsigned long *width,
+ unsigned long *height);
+
+/*
+ * The power state for the display is the lower(power) of the display
+ * state and the device state. A larger power_state number means a
+ * lower power state.
+ */
+#define GET_DISPLAY_POWER_STATE(d_h, pn) \
+(GET_DEVICE_POWER_STATE(d_h) > ((PORT(d_h, pn))->power_state) ? \
+GET_DEVICE_POWER_STATE(d_h) : ((PORT(d_h, pn))->power_state))
+
+#endif /* _IGD_MODEACCESS_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/module_init.h b/drivers/gpu/drm/emgd/emgd/include/module_init.h
new file mode 100644
index 0000000..8feafea
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/module_init.h
@@ -0,0 +1,109 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: module_init.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the init/power/shutdown prototypes for all optional
+ * (and possibly other) modules.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MODULE_INIT_H
+#define _MODULE_INIT_H
+
+#include <config.h>
+#include <context.h>
+
+extern int mode_init(igd_context_t *context);
+extern int dsp_init(igd_context_t *context);
+extern int pi_init(igd_context_t *context);
+extern int _init_2d(igd_context_t *context);
+extern int _blend_init(igd_context_t *context);
+extern int _overlay_init(igd_context_t *context, igd_param_t *params);
+extern int _cmd_init(igd_context_t *context);
+extern int _pwr_init(igd_context_t *context);
+extern int _reset_init(igd_context_t *context);
+extern int _reg_init(igd_context_t *context, unsigned long flags);
+extern int appcontext_init(igd_context_t *context);
+extern int gmm_init(igd_context_t *context, unsigned long scratch_mem,
+ unsigned long max_fb_size);
+extern void gmm_shutdown(igd_context_t *context);
+
+
+#ifdef CONFIG_2D
+#define INIT_2D(c) _init_2d(c);
+#else
+#define INIT_2D(c) 0
+#endif
+
+#ifdef CONFIG_BLEND
+#define BLEND_INIT(c) _blend_init(c);
+#else
+#define BLEND_INIT(c) 0
+#endif
+
+#ifdef CONFIG_OVERLAY
+#define OVERLAY_INIT(c, p) _overlay_init(c, p)
+#else
+#define OVERLAY_INIT(a, p) 0
+#endif
+
+#ifdef CONFIG_CMD
+#define CMD_INIT(a) _cmd_init(a);
+#else
+#define CMD_INIT(a) 0
+#endif
+
+#ifdef CONFIG_POWER
+#define PWR_INIT(a) _pwr_init(a);
+#else
+#define PWR_INIT(a) 0
+#endif
+
+#ifdef CONFIG_REG
+#define REG_INIT(a, b) _reg_init(a, b);
+#else
+#define REG_INIT(a, b) 0
+#endif
+
+#ifdef CONFIG_RESET
+#define RESET_INIT(a) _reset_init(a);
+#else
+#define RESET_INIT(a) 0
+#endif
+
+#ifdef CONFIG_INTERRUPT
+#define INTERRUPT_INIT(did, mmadr) OS_INIT_INTERRUPT(did, mmadr);
+#else
+#define INTERRUPT_INIT(did, mmadr) 0
+#endif
+
+#ifdef CONFIG_APPCONTEXT
+#define APPCONTEXT_INIT(a) appcontext_init(a)
+#else
+#define APPCONTEXT_INIT(a) 0
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/msvdx.h b/drivers/gpu/drm/emgd/emgd/include/msvdx.h
new file mode 100644
index 0000000..76f33e9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/msvdx.h
@@ -0,0 +1,259 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx.h
+ * $Revision: 1.21 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * These are the defines specific to the MSDVX engine code.
+ *-----------------------------------------------------------------------------
+ */
+#include <linux/list.h>
+#include <context.h>
+
+
+extern unsigned long _msvdx_base;
+#define MSVDX_BASE _msvdx_base
+
+#ifndef _MSVDX_H
+#define _MSVDX_H
+
+/* MTX registers */
+#define PSB_MSVDX_MTX_ENABLE (MSVDX_BASE + 0x0000)
+#define PSB_MSVDX_MTX_STATUS (MSVDX_BASE + 0x0008)
+#define PSB_MSVDX_MTX_KICK (MSVDX_BASE + 0x0080)
+#define PSB_MSVDX_MTX_KICKI (MSVDX_BASE + 0x0088)
+#define PSB_MSVDX_MTX_FAULT0 (MSVDX_BASE + 0x0090)
+#define PSB_MSVDX_MTX_REGISTER_READ_WRITE_DATA (MSVDX_BASE + 0x00f8)
+#define PSB_MSVDX_MTX_REGISTER_READ_WRITE_REQUEST (MSVDX_BASE + 0x00fc)
+#define PSB_MSVDX_MTX_RAM_ACCESS_DATA_EXCHANGE (MSVDX_BASE + 0x0100)
+#define PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER (MSVDX_BASE + 0x0104)
+#define PSB_MSVDX_MTX_RAM_ACCESS_CONTROL (MSVDX_BASE + 0x0108)
+#define PSB_MSVDX_MTX_RAM_ACCESS_STATUS (MSVDX_BASE + 0x010c)
+#define PSB_MSVDX_MTX_SOFT_RESET (MSVDX_BASE + 0x0200)
+#define PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_TIMERDIV_OFFSET (MSVDX_BASE + 0x0208)
+
+#define PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAC (MSVDX_BASE + 0x0340)
+#define PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAA (MSVDX_BASE + 0x0344)
+#define PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAS0 (MSVDX_BASE + 0x0348)
+#define PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAT (MSVDX_BASE + 0x0350)
+
+#define PSB_MSVDX_DMAC_SETUP (MSVDX_BASE + 0x0500)
+#define PSB_MSVDX_DMAC_COUNT (MSVDX_BASE + 0x0504)
+#define PSB_MSVDX_DMAC_PERIPH (MSVDX_BASE + 0x0508)
+#define PSB_MSVDX_DMAC_IRQ_STAT (MSVDX_BASE + 0x050c)
+#define PSB_MSVDX_DMAC_PERIPHERAL_ADDR (MSVDX_BASE + 0x0514)
+/* MSVDX registers */
+#define PSB_MSVDX_CONTROL (MSVDX_BASE + 0x0600)
+#define PSB_MSVDX_INTERRUPT_STATUS (MSVDX_BASE + 0x0608)
+#define PSB_MSVDX_INTERRUPT_CLEAR (MSVDX_BASE + 0x060c)
+#define PSB_MSVDX_HOST_INTERRUPT_ENABLE (MSVDX_BASE + 0x0610)
+#define PSB_MSVDX_MAN_CLK_ENABLE (MSVDX_BASE + 0x0620)
+#define PSB_MSVDX_CORE_REV (MSVDX_BASE + 0x0640)
+#define PSB_MSVDX_MMU_CONTROL0 (MSVDX_BASE + 0x0680)
+#define PSB_MSVDX_MMU_CONTROL1 (MSVDX_BASE + 0x0684)
+#define PSB_MSVDX_MMU_BANK_INDEX (MSVDX_BASE + 0x0688)
+#define PSB_MSVDX_MMU_STATUS (MSVDX_BASE + 0x068c)
+#define PSB_MSVDX_MMU_DIR_LIST_BASE0 (MSVDX_BASE + 0x0694)
+#define PSB_MSVDX_MMU_DIR_LIST_BASE1 (MSVDX_BASE + 0x0698)
+#define PSB_MSVDX_MMU_DIR_LIST_BASE2 (MSVDX_BASE + 0x069c)
+#define PSB_MSVDX_MMU_DIR_LIST_BASE3 (MSVDX_BASE + 0x06a0)
+#define PSB_MSVDX_MMU_MEM_REQ (MSVDX_BASE + 0x06d0)
+#define PSB_MSVDX_MTX_RAM_BANK (MSVDX_BASE + 0x06f0)
+/* RENDEC registers */
+#define PSB_MSVDX_RENDEC_CONTROL0 (MSVDX_BASE + 0x0868)
+#define PSB_MSVDX_RENDEC_CONTROL1 (MSVDX_BASE + 0x086C)
+#define PSB_MSVDX_RENDEC_BUFFER_SIZE (MSVDX_BASE + 0x0870)
+#define PSB_MSVDX_RENDEC_BASE_ADDR0 (MSVDX_BASE + 0x0874)
+#define PSB_MSVDX_RENDEC_BASE_ADDR1 (MSVDX_BASE + 0x0878)
+#define PSB_MSVDX_RENDEC_READ_DATA (MSVDX_BASE + 0x0898)
+#define PSB_MSVDX_RENDEC_CONTEXT0 (MSVDX_BASE + 0x0950)
+#define PSB_MSVDX_RENDEC_CONTEXT1 (MSVDX_BASE + 0x0954)
+#define PSB_MSVDX_RENDEC_CONTEXT2 (MSVDX_BASE + 0x0958)
+#define PSB_MSVDX_RENDEC_CONTEXT3 (MSVDX_BASE + 0x095C)
+#define PSB_MSVDX_RENDEC_CONTEXT4 (MSVDX_BASE + 0x0960)
+#define PSB_MSVDX_RENDEC_CONTEXT5 (MSVDX_BASE + 0x0964)
+
+#define MSVDX_COMMS_AREA_ADDR (MSVDX_BASE + 0x02fd0)
+#define PSB_MSVDX_COMMS_FW_STATUS (MSVDX_COMMS_AREA_ADDR + 0x00)
+#define PSB_MSVDX_COMMS_VLR_RES (MSVDX_COMMS_AREA_ADDR + 0x04)
+#define PSB_MSVDX_COMMS_SCRATCH (MSVDX_COMMS_AREA_ADDR + 0x08)
+#define PSB_MSVDX_COMMS_MSG_COUNTER (MSVDX_COMMS_AREA_ADDR + 0x0c)
+#define PSB_MSVDX_COMMS_SIGNATURE (MSVDX_COMMS_AREA_ADDR + 0x10)
+#define PSB_MSVDX_COMMS_TO_HOST_BUF_SIZE (MSVDX_COMMS_AREA_ADDR + 0x14)
+#define PSB_MSVDX_COMMS_TO_HOST_RD_INDEX (MSVDX_COMMS_AREA_ADDR + 0x18)
+#define PSB_MSVDX_COMMS_TO_HOST_WRT_INDEX (MSVDX_COMMS_AREA_ADDR + 0x1c)
+#define PSB_MSVDX_COMMS_TO_MTX_BUF_SIZE (MSVDX_COMMS_AREA_ADDR + 0x20)
+#define PSB_MSVDX_COMMS_TO_MTX_RD_INDEX (MSVDX_COMMS_AREA_ADDR + 0x24)
+#define PSB_MSVDX_COMMS_OFFSET_FLAGS (MSVDX_COMMS_AREA_ADDR + 0x28)
+#define PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX (MSVDX_COMMS_AREA_ADDR + 0x2c)
+
+#define MTX_CORE_CODE_MEM (0x10)
+#define MTX_CORE_DATA_MEM (0x18)
+#define MTX_CODE_BASE (0x80900000)
+#define MTX_DATA_BASE (0x82880000)
+#define PC_START_ADDRESS (0x80900000)
+#define MSVDX_MTX_ENABLE_MTX_ENABLE_MASK (0x00000001)
+#define MTX_PC (5)
+#define RENDEC_A_SIZE (1024 * 1024 * 2)
+#define RENDEC_B_SIZE (RENDEC_A_SIZE / 4)
+#define FWRK_PADMSG_SIZE (2)
+#define FWRK_MSGID_PADDING (0)
+#define FWRK_MSGID_START_PSR_HOSTMTX_MSG (0x80)
+#define FWRK_MSGID_START_PSR_MTXHOST_MSG (0xc0)
+#define MSVDX_CLK_ENABLE_CR_CORE_MASK (0x00000001)
+#define MSVDX_CLK_ENABLE_CR_VDEB_PROCESS_MASK (0x00000002)
+#define MSVDX_CLK_ENABLE_CR_VDEB_ACCESS_MASK (0x00000004)
+#define MSVDX_CLK_ENABLE_CR_VDMC_MASK (0x00000008)
+#define MSVDX_CLK_ENABLE_CR_VEC_ENTDEC_MASK (0x00000010)
+#define MSVDX_CLK_ENABLE_CR_VEC_ITRANS_MASK (0x00000020)
+#define MSVDX_CLK_ENABLE_CR_MTX_MASK (0x00000040)
+#define MSVDX_CLK_ENABLE_CR_VDEB_ACCESS_AUTO_MASK (0x00040000)
+#define MSVDX_CLK_ENABLE_CR_VDMC_AUTO_MASK (0x00080000)
+#define MSVDX_CLK_ENABLE_CR_VEC_ENTDEC_AUTO_MASK (0x00100000)
+#define MSVDX_CLK_ENABLE_CR_VEC_ITRANS_AUTO_MASK (0x00200000)
+
+
+#define PSB_CLK_ENABLE_ALL \
+ MSVDX_CLK_ENABLE_CR_CORE_MASK |\
+ MSVDX_CLK_ENABLE_CR_VDEB_PROCESS_MASK |\
+ MSVDX_CLK_ENABLE_CR_VDEB_ACCESS_MASK |\
+ MSVDX_CLK_ENABLE_CR_VDMC_MASK |\
+ MSVDX_CLK_ENABLE_CR_VEC_ENTDEC_MASK |\
+ MSVDX_CLK_ENABLE_CR_VEC_ITRANS_MASK |\
+ MSVDX_CLK_ENABLE_CR_MTX_MASK
+
+#define PSB_CLK_ENABLE_MIN MSVDX_CLK_ENABLE_CR_CORE_MASK
+#define PSB_MSVDX_FW_STATUS_HW_IDLE (0x00000001)
+
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV (0x00000002)
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION (0x00000020)
+#define MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE (0x00000200)
+
+#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT \
+ MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION
+
+
+#define FW_VA_RENDER_HOST_INT 0x00004000
+
+#ifndef list_first_entry
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+#endif
+
+enum {
+ /*! Sent by the video driver on the host to the mtx firmware. */
+ IGD_MSGID_INIT = FWRK_MSGID_START_PSR_HOSTMTX_MSG,
+ IGD_MSGID_RENDER,
+ IGD_MSGID_DEBLOCK,
+ IGD_MSGID_BUBBLE,
+
+ /* Test Messages */
+ IGD_MSGID_TEST1,
+ IGD_MSGID_TEST2,
+
+ /*! Sent by the mtx firmware to itself. */
+ IGD_MSGID_RENDER_MC_INTERRUPT,
+
+ /*! Sent by the DXVA firmware on the MTX to the host. */
+ IGD_MSGID_CMD_COMPLETED = FWRK_MSGID_START_PSR_MTXHOST_MSG,
+ IGD_MSGID_CMD_COMPLETED_BATCH,
+ IGD_MSGID_DEBLOCK_REQUIRED,
+ IGD_MSGID_TEST_RESPONCE,
+ IGD_MSGID_ACK,
+
+ IGD_MSGID_CMD_FAILED,
+ IGD_MSGID_CMD_UNSUPPORTED,
+ IGD_MSGID_CMD_HW_PANIC,
+};
+
+struct msvdx_cmd_queue {
+ struct list_head head;
+ void *cmd;
+ unsigned long cmd_size;
+ unsigned long context_id;
+};
+
+/* TODO: From UMG, temporary put here first, may need to use this
+ * MSVDX private structure
+ */
+
+struct msvdx_private {
+ int msvdx_needs_reset;
+
+ unsigned int pmstate;
+
+ struct sysfs_dirent *sysfs_pmstate;
+
+ uint32_t msvdx_current_sequence;
+ uint32_t msvdx_last_sequence;
+
+ /*
+ * MSVDX Rendec Memory
+ */
+ uint32_t base_addr0;
+ uint32_t base_addr1;
+
+ /*
+ * msvdx command queue
+ */
+ /* spinlock_t msvdx_lock; */
+ /* struct mutex msvdx_mutex; */
+ struct list_head msvdx_queue;
+ int msvdx_busy;
+ int msvdx_fw_loaded;
+ void *msvdx_fw;
+ int msvdx_fw_size;
+
+ struct list_head deblock_queue; /* deblock parameter list */
+
+ uint32_t msvdx_hw_busy;
+};
+
+typedef struct msvdx_fw_ {
+ unsigned long fw_text_size;
+ unsigned long *fw_text;
+ unsigned long fw_data_location;
+ unsigned long fw_data_size;
+ unsigned long *fw_data;
+ unsigned long fw_version_size;
+ char *fw_version;
+} msvdx_fw_t;
+
+
+int process_video_decode_plb(igd_context_t *context, unsigned long offset,
+ void *mem_handle, unsigned long *fence_id);
+int msvdx_query_plb(igd_context_t *context, unsigned long *status);
+int msvdx_preinit_mmu(unsigned long hmemcxt);
+int msvdx_init_plb(unsigned long base0, unsigned long base1,
+ void* mem_handle_fw,int reset_flag);
+int msvdx_init_compositor_mmu(unsigned long mmu_base);
+int msvdx_uninit_plb(igd_context_t *context);
+int msvdx_close_context(igd_context_t *context, unsigned long context_id);
+int msvdx_create_context(igd_context_t *context, void *drm_file_priv, unsigned long ctx_id);
+int msvdx_shutdown_plb(igd_context_t *context);
+int msvdx_get_fence_id(igd_context_t *context, unsigned long *fence_id);
+int msvdx_flush_tlb(igd_context_t *context);
+void msvdx_postclose_check(igd_context_t *context, void *drm_file_priv);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/pci.h b/drivers/gpu/drm/emgd/emgd/include/pci.h
new file mode 100644
index 0000000..9a5fc5c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pci.h
@@ -0,0 +1,257 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains OS abstractions for PCI function calls.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_PCI_H
+#define _OAL_PCI_H
+
+
+/*
+ * Standard PCI register definitions.
+ * Only the first 64 bytes are standardized so thiese must all be
+ * defined to numbers less than 0x40
+ */
+#define PCI_RID 0x08
+
+#define PCI_BAR_0 0x10
+#define PCI_BAR_1 0x14
+#define PCI_BAR_2 0x18
+#define PCI_BAR_3 0x1c
+#define PCI_BAR_4 0x20
+#define PCI_BAR_5 0x24
+
+#define PCI_INTERRUPT_LINE 0x3c
+
+/*
+ * This macro _may_ be defined by an OAL port to enable the PCI device
+ * Commonly this is used to enable the device on EFI
+ * The prototype of the function looks like this:
+ * int os_enable_pci(os_pci_dev dev);
+ * The return value from this function should be 0 to indicate success
+ * or non zero to indicate failure.
+ */
+#ifdef _OS_ENABLE_PCI
+#define OS_ENABLE_PCI(a) _OS_ENABLE_PCI(a)
+#else
+#define OS_ENABLE_PCI(a) 0
+#endif
+
+#define OS_PCI_GET_SLOT_ADDRESS(p, b, s, f) os_pci_get_slot_address(p, b, s, f)
+#define OS_PCI_READ_CONFIG_8(p, o, v) os_pci_read_config_8(p, o, (v))
+#define OS_PCI_READ_CONFIG_16(p, o, v) os_pci_read_config_16(p, o, (v))
+#define OS_PCI_READ_CONFIG_32(p, o, v) os_pci_read_config_32(p, o, (v))
+#define OS_PCI_WRITE_CONFIG_8(p, o, v) os_pci_write_config_8(p, o, v)
+#define OS_PCI_WRITE_CONFIG_16(p, o, v) os_pci_write_config_16(p, o, v)
+#define OS_PCI_WRITE_CONFIG_32(p, o, v) os_pci_write_config_32(p, o, v)
+#define OS_PCI_FREE_DEVICE(p) os_pci_free_device(p)
+
+#define OS_PCI_FIND_DEVICE(v, d, p, bus, dev, func) \
+ os_pci_find_device(v, d, p, bus, dev, func)
+
+/*****************************************************************************
+ * Variable: os_pci_dev_t
+ *
+ * Description:
+ * This is a data type that serves as a handle for allocated PCI device.
+ *
+ ****************************************************************************/
+typedef unsigned char *os_pci_dev_t;
+
+
+/*****************************************************************************
+ * Function: os_pci_find_device
+ *
+ * Parameters:
+ * vendor_id : The vendor ID for the device to be found.
+ * device_id : The vendor ID for the device to be found.
+ * bus : The bus number of the device in the PCI topology
+ * dev : The device number of the device in the PCI topology
+ * func : The function number of the device in the PCI topology
+ * pci_device: The last found os_pci_dev_t or NULL.
+ *
+ * Description:
+ * This function will find the PCI device for the paticular vendor and device,
+ * bus, device, and function number.The pci_device parameter should be NULL when
+ * calling the first time
+ * and the last returned value when searching for multiple devices of
+ * the same ID.
+ *
+ * Notes: If the bus number is 0xFFFF, then the function searches for that
+ * vendor_id, device_id pair in the whole PCI topology of the system i.e
+ * it goes through all the buses, devices, functions in the system
+ *
+ ****************************************************************************/
+os_pci_dev_t os_pci_find_device(
+ unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short bus,
+ unsigned short dev,
+ unsigned short func,
+ os_pci_dev_t pci_dev);
+
+/*****************************************************************************
+ * Function: os_get_slot_address
+ *
+ * Parameters:
+ * pci_device: The os_pci_dev_t to query.
+ * bus: The returned bus or NULL if the bus is not needed.
+ * slot: The returned slot or NULL if the bus is not needed.
+ * func: The returned func or NULL if the bus is not needed.
+ *
+ * Description:
+ * This function will return the bus slot and function for an os_pci_dev_t
+ * previously obtained from os_pci_find_device(). Any of the bus/slot/func
+ * parameters may be null if the information is not needed.
+ *
+ ****************************************************************************/
+int os_pci_get_slot_address(
+ os_pci_dev_t pci_dev,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *func);
+
+/*****************************************************************************
+ * Function: os_pci_read_config_8
+ *
+ * Description:
+ * This function retrieves a byte of information, starting at the specified
+ * offset, from the PCI configuration space on a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char* val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_read_config_16
+ *
+ * Description:
+ * This function retrieves a word of information, starting at the specified
+ * offset, from the PCI configuration space on a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short* val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_read_config_32
+ *
+ * Description:
+ * This function retrieves double word of information, starting at the
+ * specified offset, from the PCI configuration space on a particular PCI
+ * device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long* val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_8
+ *
+ * Description:
+ * This function sets a byte of data, starting at the specified offset, to
+ * the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_16
+ *
+ * Description:
+ * This function sets a word of data, starting at the specified offset, to
+ * the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_32
+ *
+ * Description:
+ * This function sets double word of data, starting at the specified offset,
+ * to the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long val
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_disable_legacy_vga_decoding
+ *
+ * Description:
+ * Disabled legacy VGA decoding on a specific PCI device if the kernel is
+ * compiled with support for the VGA arbiter. If the VGA arbiter is not
+ * compiled in, this function is a noop.
+ *
+ ****************************************************************************/
+int os_pci_disable_legacy_vga_decoding(
+ os_pci_dev_t pci_dev
+ );
+
+
+/*****************************************************************************
+ * Function: os_pci_free_device
+ *
+ * Description:
+ * This function free the os_pci_dev_t * that previously allocated with the
+ * os_pci_find_device.
+ *
+ ****************************************************************************/
+void os_pci_free_device(
+ os_pci_dev_t pci_dev
+ );
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/pd.h b/drivers/gpu/drm/emgd/emgd/include/pd.h
new file mode 100644
index 0000000..a12cac5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pd.h
@@ -0,0 +1,767 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd.h
+ * $Revision: 1.12 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_H_
+#define _PD_H_
+
+#include <igd_pd.h>
+#include <igd_debug.h>
+
+/* PD SDK version 2 bytes,
+ * 1st byte is major version,
+ * second byte is minor version.
+ */
+
+/* Update the version number each time there is an
+ * API Change or Change in data structures
+ */
+#define PD_SDK_VERSION 0x0300 /* PD SDK Version */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* This needs to contain the unsigned long for vBIOS. */
+#ifndef BIT
+#define BIT(x) (1L<<x)
+#endif
+
+/* Macro to return:
+ * minimum, if the value < min value
+ * maximum, if the value > max value
+ * value, otherwise
+ */
+#define MINMAX(val, min, max) ((val < min) ? min : ((val > max) ? max : val))
+
+#define PD_REG_LIST_END 0xFFFFFFFF
+#define PD_DAB_LIST_END 0xFFFFFFFF
+#define PD_TIMING_LIST_END 0xFFFF
+
+/* Error codes used for return values */
+#define PD_SUCCESS 0x00 /* Success */
+#define PD_ERR_NOMEM 0x01 /* Unable to allocated requested mem */
+#define PD_ERR_NODEV 0x02 /* No Device/Codec found */
+#define PD_ERR_NODIS 0x03 /* No display found */
+#define PD_ERR_INVALID_PTR 0x04 /* Invalid pointer passed */
+#define PD_ERR_NULL_PTR 0x05 /* Null ptr passed */
+#define PD_ERR_DISPLAY_TYPE 0x06 /* Unsupported display type specified */
+#define PD_ERR_NOPORT_AVAIL 0x07 /* No port available */
+#define PD_ERR_INTERNAL 0x08 /* Critical internal error */
+#define PD_ERR_INVALID_POWER 0x09 /* Invalid power state specified */
+#define PD_ERR_HAND_SHAKE 0x0A /* Magic cookie hand shake failed */
+#define PD_ERR_MODE_NOTSUPP 0x0B /* Unsupported mode */
+#define PD_ERR_I2C_READ 0x0C /* I2C read error */
+#define PD_ERR_I2C_WRITE 0x0D /* I2C write error */
+#define PD_ERR_NULL_STATE 0x0E /* Saved state is NULL */
+/* PD_ERR_NOATTR removed. Return success with 0 count instead */
+#define PD_ERR_NO_TIMINGS 0x10 /* No timing list */
+#define PD_ERR_INVALID_ATTR 0x11 /* Invalid attribute */
+#define PD_ERR_INCORR_ATTR_VALUE 0x12 /* Incorrect attr value */
+#define PD_ERR_ATTR_CANT_CHANGE 0x13 /* Attribute value cannot be changed */
+#define PD_ERR_VER_MISMATCH 0x14 /* PD SDK version mismatch */
+#define PD_ERR_UNSUCCESSFUL 0x15 /* Operation unsuccessful */
+
+typedef struct _pd_reg {
+ unsigned long reg;
+ unsigned long value;
+}pd_reg_t;
+
+
+/* The following structures holds CEA EDID Extension data
+ * Edid and possibly display id would use this structure as
+ * well. PD callback would have a callback function to one the
+ * structure to retrieve EDID like data (ELD)
+ */
+
+
+#define CEA_IEEE_HDMI_ID 0x000C03
+/* Aspect Ratio */
+#define PD_ASPECT_RATIO_NO_DATA 0
+#define PD_ASPECT_RATIO_4_3 1
+#define PD_ASPECT_RATIO_16_9 2
+/* ELD status */
+#define ELD_AVAIL 0x01
+#define ELD_CANNED 0x02
+/* Transmitter audio charactheristic */
+#define PD_AUDIO_CHAR_AVAIL 0x10
+/* CEA data block type */
+#define CEA_VIDEO_DATA_BLOCK 0x40
+#define CEA_AUDIO_DATA_BLOCK 0x20
+#define CEA_VENDOR_DATA_BLOCK 0x60
+#define CEA_SPEAKER_DATA_BLOCK 0x80
+/* Audio block Tag Code */
+#define CEA_AUDIO_LPCM 1
+#define CEA_AUDIO_AC3 2
+#define CEA_AUDIO_MPG1 3
+#define CEA_AUDIO_MP3 4
+#define CEA_AUDIO_MPG2 5
+#define CEA_AUDIO_AAC 6
+#define CEA_AUDIO_DTS 7
+#define CEA_AUDIO_ATRAC 8
+#define CEA_AUDIO_SACD 9
+#define CEA_AUDIO_DD_PLUS 10
+#define CEA_AUDIO_DTS_HD 11
+#define CEA_AUDIO_MLP 12
+/* Pixel Replication */
+#define PIX_REPLICATION_0 1
+#define PIX_REPLICATION_1 2
+#define PIX_REPLICATION_3 4
+/* Quantization */
+#define HDMI_QUANTIZATION_RGB_256 0x00
+#define HDMI_QUANTIZATION_RGB_220 0x01
+#define HDMI_QUANTIZATION_YUV_422 0x02
+#define HDMI_QUANTIZATION_YUV_44 0x03
+/* Colorimetry */
+#define HDMI_COLORIMETRY_NODATA 0x00
+#define HDMI_COLORIMETRY_ITU601 0x01 /* SMPTE 170M, ITU601 */
+#define HDMI_COLORIMETRY_ITU709 0x02
+/* Audio CAP(48,96,192)Khz refer to audio_cap in CEA ELD extension*/
+#define CAP_48_KHZ 0
+#define CAP_96_KHZ 1
+#define CAP_192_KHZ 2
+/* Vendor Specific Data Block */
+#define VSBD_LATENCY_FIELD 8
+typedef struct _cea_audio_format_t{
+ union{
+ unsigned char byte1;
+ struct{
+ unsigned char max_channels : 3;
+ unsigned char audio_format_code : 4;
+ unsigned char reserve_byte1 : 1;
+ };
+ };
+ union{
+ unsigned char byte2;
+ struct{
+ unsigned char _32khz : 1;
+ unsigned char _44khz : 1;
+ unsigned char _48khz : 1;
+ unsigned char _88khz : 1;
+ unsigned char _96khz : 1;
+ unsigned char _176khz : 1;
+ unsigned char _192khz : 1;
+ unsigned char reserve_byte2 : 1;
+ };
+ };
+ /* 3rd byte differs between compressed & uncompressed audio */
+ union{
+ unsigned char max_bitrate;
+ struct{
+ unsigned char _16bit : 1;
+ unsigned char _20bit : 1;
+ unsigned char _24bit : 1;
+ unsigned char reserve_byte3 : 5;
+ };
+ };
+
+}cea_audio_format_t;
+
+typedef struct _speaker_allocation_data_t{
+ struct{
+ unsigned char rsvd : 1;
+ unsigned char rlc_rrc : 1;
+ unsigned char flc_frc : 1;
+ unsigned char rc : 1;
+ unsigned char rl_rr : 1;
+ unsigned char fc : 1;
+ unsigned char lfe : 1;
+ unsigned char fl_fr : 1;
+ };
+ unsigned char reserved[2];
+}speaker_allocation_data_t;
+
+typedef union {
+ unsigned char value;
+ struct {
+ unsigned char code: 7;
+ unsigned char native: 1;
+ };
+} cea_video_blk_t;
+
+typedef struct _audio_capability_t{
+ unsigned char max_channels;
+ unsigned char _20bit;
+ unsigned char _24bit;
+}audio_capability_t;
+
+typedef struct _vsdb_t{
+ union{
+ unsigned char header;
+ struct{
+ unsigned char vendor_block_size: 5;
+ unsigned char tag : 3;
+ };
+ };
+ unsigned char vendor_ieee_id[3];
+ unsigned char src_phy_add[2];
+ unsigned char support_ai;
+ unsigned char max_tmds_clck;
+ union{
+ unsigned char latency_fields;
+ struct{
+ unsigned char reserve : 6;
+ unsigned char i_latency : 1;
+ unsigned char p_latency : 1;
+ };
+ };
+ unsigned char p_video_latency;
+ unsigned char p_audio_latency;
+ unsigned char i_video_latency;
+ unsigned char i_audio_latency;
+
+}vsdb_t;
+
+typedef struct _cea_extension{
+ unsigned char rev_number;
+ unsigned char canned_eld;
+ union{
+ unsigned char caps;
+ struct{
+ unsigned char total_native_format : 4;
+ unsigned char YCC_422 : 1;
+ unsigned char YCC_444 : 1;
+ unsigned char audio_support : 1;
+ unsigned char underscan_support : 1;
+ };
+ };
+
+ /* Short Video Descriptor */
+ int total_short_video_desc;
+ cea_video_blk_t *short_video_desc;
+ /* Short Audio Descriptor */
+ int total_short_audio_desc;
+ cea_audio_format_t *short_audio_desc;
+ /* Vendor Descriptor Block */
+ unsigned char *vendor_data_block;
+
+ unsigned char audio_flag; /* Define is ELD status */
+ unsigned char NPL;
+ unsigned char K0;
+ unsigned char K1;
+ audio_capability_t audio_cap[3]; /* Panel audio capability (48,96,192)Khz*/
+
+ /* AVI Info frames data */
+ int pixel_rep; /* Pixel replication */
+ int quantization; /* Quantization */
+ int aspect_ratio; /* Aspect Ratio */
+ int colorimetry; /* Colorimetry */
+ int video_code;
+ /* Consolidate ELD information here */
+ union{
+ unsigned char eld_ptr[256];
+ struct {
+ union {
+ unsigned char version;
+ struct {
+ unsigned char cea_ver: 3;
+ unsigned char eld_ver: 5;
+ };
+ };
+ union {
+ unsigned char capability;
+ struct {
+ unsigned char hdcp: 1;
+ unsigned char repeater: 1;
+ unsigned char _44ms: 1;
+ unsigned char reserved1: 5;
+ };
+ };
+ union {
+ unsigned short length;
+ struct {
+ unsigned short mnl: 3;
+ unsigned short vsdbl: 3;
+ unsigned short sadc: 4;
+ unsigned short reserved2: 6;
+ };
+ };
+ unsigned short manu_id;
+ unsigned short prod_id;
+ unsigned char LPCM_CAD[3]; /* LPCM for ELD */
+ unsigned char speaker_alloc_block[3];
+ vsdb_t vendor_block; /* 13 byte */
+ unsigned char misc_data[229];
+ };
+ };
+}cea_extension_t;
+
+/* Following are the callback functions provided to port driver. It also
+ * provides a call back context. Every time port driver has to pass this
+ * callback context when calling a callback function.
+ *
+ * read_regs: Port driver has to pass a list of pd_reg_t's which
+ * it want to read. The list has to end with PD_I2C_LIST_END.
+ * The values read will be set to the for every list->reg,
+ * value will be set in list->value.
+ *
+ * Return value == 0 on success
+ * != 0 on failure
+ *
+ * write_regs: Port driver has to pass a list of pd_reg_t's which
+ * it want to write. The list has to end with PD_LIST_END.
+ * Caller has to provide already masked values. This callback
+ * function doesn't do any masking. If, port driver wants to
+ * write only some bits of a reg, first it has to read the
+ * register and then set bits and write the register.
+ *
+ * Return value == 0 on success
+ * != 0 on failure
+ */
+
+#define PD_REG_I2C 0x00000001
+#define PD_REG_LPC 0x00000002
+#define PD_REG_DMA 0x00000003
+#define PD_REG_PCI 0x00000004
+#define PD_REG_MIO 0x00000005 /* MMIO 32 bits */
+#define PD_REG_PIO8 0x00000006 /* Port IO 1 byte */
+#define PD_REG_PIO16 0x00000007 /* Port IO 2 bytes */
+#define PD_REG_PIO32 0x00000008 /* Port IO 4 bytes */
+#define PD_REG_MIO8 0x00000009 /* MMIO 8 bits */
+#define PD_REG_BRIDGE_OPCODE 0x0000000D /* Host bridge read and write */
+#define PD_REG_DDC 0x0000000E /* Read the ddc */
+#define PD_REG_DDC_FW 0x0000000F /* Read the ddc */
+
+typedef int (*pd_read_regs_p)(void *callback_context, pd_reg_t *list,
+ unsigned long type);
+typedef int (*pd_write_regs_p)(void *callback_context, pd_reg_t *list,
+ unsigned long type);
+
+typedef struct _pd_callback {
+ void *callback_context;
+ pd_read_regs_p read_regs;
+ pd_write_regs_p write_regs;
+ unsigned long port_num; /* Added for SDVO port driver */
+ cea_extension_t **eld; /* EDID like Data */
+ unsigned char reset;
+}pd_callback_t;
+
+/* IMP NOTE: All below structures should be with same size.
+ * pd_attr_t : General attribute structure
+ * pd_range_attr_t : Range type attribute structure
+ * pd_list_attr_t : List type attribute
+ * pd_list_entry_attr_t : Entry for a list
+ * pd_bool_attr_t : Boolean type attribute
+ * pd_buffer_attr_t : Buffer type attribute
+ */
+typedef igd_attr_t pd_attr_t;
+typedef igd_range_attr_t pd_range_attr_t;
+typedef igd_list_attr_t pd_list_attr_t;
+typedef igd_list_entry_attr_t pd_list_entry_attr_t;
+typedef igd_bool_attr_t pd_bool_attr_t;
+typedef igd_buffer_attr_t pd_buffer_attr_t;
+
+#define ATTR(a) ((pd_attr_t *)a) /* General attr */
+#define RATTR(a) ((pd_range_attr_t *)a) /* Range attr */
+#define LHATTR(a) ((pd_list_attr_t *)a) /* List head attr */
+#define LEATTR(a) ((pd_list_entry_attr_t *)a) /* List entry attr */
+#define BATTR(a) ((pd_bool_attr_t *)a) /* Bool attr */
+#define BUATTR(a) ((pd_buffer_attr_t *)a) /* Buffer attr */
+
+/* Timing structure flag defines */
+#define PD_SCAN_INTERLACE 0x80000000
+#define PD_LINE_DOUBLE 0x40000000
+#define PD_PIXEL_DOUBLE 0x20000000
+#define PD_MODE_TEXT 0x10000000 /* VGA Text mode */
+
+#define PD_HSYNC_HIGH 0x08000000
+#define PD_VSYNC_HIGH 0x04000000
+#define PD_BLANK_LOW 0x02000000
+#define PD_MODE_VESA 0x01000000 /* VGA/VESA mode number is valid */
+
+#define PD_MODE_STALL 0x00800000 /* Flag to enable stall signal */
+#define PD_MODE_SCALE 0x00400000 /* Request NATIVE timings */
+
+#define PD_ASPECT_16_9 0x00200000 /* 16:9 aspect ratio, otherwise it is 4:3 */
+#define PD_MODE_CEA 0x00100000
+
+#define PD_MODE_DTD 0x00080000 /* Read from EDID */
+#define PD_MODE_DTD_USER 0x00040000 /* User defined timing */
+#define PD_MODE_DTD_FP_NATIVE 0x00020000 /* Native fp timing */
+#define PD_MODE_SUPPORTED 0x00010000
+
+#define PD_MODE_FACTORY 0x00008000 /* Factory supported mode */
+#define PD_MODE_RB 0x00004000 /* Reduced blanking mode */
+
+/* Macro to put at the end timing table */
+#define PD_TIMING_TABLE_END \
+{\
+ PD_TIMING_LIST_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
+ NULL, 0, 0\
+}\
+
+/* Timing structure */
+typedef struct _pd_timing {
+ unsigned short width; /* width */
+ unsigned short height; /* height */
+ unsigned short refresh; /* refresh rate */
+ unsigned long dclk; /* refresh rate dot clock in kHz */
+ unsigned short htotal; /* horizontal total */
+ unsigned short hblank_start; /* horizontal blank start */
+ unsigned short hblank_end; /* horizontal blank end */
+ unsigned short hsync_start; /* horizontal sync start */
+ unsigned short hsync_end; /* horizontal sync end */
+ unsigned short vtotal; /* vertical total */
+ unsigned short vblank_start; /* vertical blank start */
+ unsigned short vblank_end; /* vertical blank end */
+ unsigned short vsync_start; /* vertical sync start */
+ unsigned short vsync_end; /* vertical sync end */
+ short mode_number; /* VGA or VESA mode number */
+ unsigned long mode_info_flags; /* Valid Flags
+ - PD_SCAN_INTERLACE
+ - PD_LINE_DOUBLE
+ - PD_PIXEL_DOUBLE
+ - PD_HSYNC_HIGH
+ - PD_VSYNC_HIGH
+ - PD_MODE_SUPPORTED
+ - PD_MODE_DTD */
+ unsigned short x_offset;
+ unsigned short y_offset;
+ void *extn_ptr; /* INTERNAL pointer for use by main driver only */
+ unsigned short reserved_dd; /* Reserved for device dependant layer */
+ unsigned short reserved_dd_ext; /* Reserved for device dependant layer */
+} pd_timing_t;
+
+/* Bit field flags for pd_driver_t->driver_flags */
+#define PD_FLAG_GANG_MODE 0x00000001 /* driver is running in gang mode*/
+#define PD_FLAG_CLK_SOURCE 0x00000002 /* clk source is port driver */
+#define PD_FLAG_PIPE_MASTER 0x00000004 /* master port driver */
+#define PD_FLAG_REV_DATA_ORDER 0x00000008 /* reverse data order requested */
+#define PD_FLAG_I740_DATA_ORDER 0x00000010 /* For I740 Data ordering. If this
+ flag isn't set, then it is
+ Flat panel data ordering */
+#define PD_FLAG_DUAL_DVO 0x00000020 /* Same port driver will be loaded
+ * on both DVOB & DVOC with same
+ * DAB */
+#define PD_FLAG_GANG_MODE_EVEN_ODD 0x00000040 /* pd wants gang mode in even
+ * pixels on one DVO port &
+ * odd pixels on other DVO port.
+ * Default is upper half pixel
+ * on one DVO port and lower
+ * half on the other DVO port.
+ */
+#define PD_FLAG_UP_SCALING 0x00000080 /* pd supports up-scaling */
+#define PD_FLAG_DOWN_SCALING 0x00000100 /* pd supports down-scaling */
+#define PD_FLAG_CLOCK_MASTER 0x00000200 /* clock master port driver */
+#define PD_FLAG_GANG_MODE_DVOCLKINV 0x00000400 /* GangMode DVO Clk inversion */
+#define PD_FLAG_NO_VGA_2X_IMAGE 0x00000800 /* Gang Mode operation might
+ * request this flag */
+
+/* Flag for set_mode function */
+/* Though these are bit fields, both cannot be used at same time */
+#define PD_SET_MODE_PIPE_A 0x1
+#define PD_SET_MODE_PIPE_B 0x2
+#define PD_SET_MODE_FLAG_TEST 0x4
+
+/* Flags for save and restore */
+#define PD_NO_RESTORE_FREE_STATE 0x1
+
+/* Power Modes */
+#define PD_POWER_MODE_D0 0x0
+#define PD_POWER_MODE_D1 0x1
+#define PD_POWER_MODE_D2 0x2
+#define PD_POWER_MODE_D3 0x3
+
+#define PD_FILE_SIZE 8 /* File name size for port driver excluding
+ * extension. Extension can be max of 3 chars. */
+
+/* Following is the abstraction of port driver. Port driver passes this
+ * driver information to display driver as part of registering itself with
+ * display driver. pd_register(pd_driver_t *) is called from port driver
+ * in its init function which is called whenever port driver is loaded.
+ *
+ * Port driver provides following list of functions to display driver.
+ * Display driver calls these functions to do the required operations.
+ *
+ * type - supporting display type for the port driver
+ *
+ * flags - flags for the driver. And cannot be changed at runtime.
+ * Once these flags are passed to main driver, they will be
+ * used while setting the mode.
+ *
+ * context - Driver's contextual information. The driver can save
+ * all needed state information in this opaque pointer
+ * such that the driver is entirely reentrant. No writeable
+ * data may be saved in any non-stack variables by a driver
+ * therefore all necessary data must be saved in a private
+ * structure and stored in this pointer. This pointer is
+ * passed to the driver with each function call.
+ *
+ * validate - Display driver calls this function to validate the port
+ * driver by passing a magic cookie. Port driver does some
+ * magic operation and returns another cookie back to caller.
+ * If the returned cookie has correct value then the driver
+ * passes the validation, otherwise driver cannot communicate
+ * with display driver.
+ *
+ * open - This function is to detect for any port device (codec).
+ * pd_callback_t has all the required callback functions
+ * to do this operation.
+ *
+ * init_device - This function detects and initializes any display devices
+ * attached to the codec.
+ *
+ * For ex: a multi function encoder can support a FlatPanel or
+ * TVout display. It has to detect and check for any
+ * Flatpanel or TVout display device attached, then it
+ * initializes the display devices.
+ *
+ * pd_close - closes the display device and frees any memory allocated.
+ *
+ * set_mode - sets/tests a mode. Display (or main) driver calls this
+ * function to set a mode when the encoder in D3 power state.
+ * At this time, DVO timings are off.
+ * If encoder wants to run setmode in any other power state,
+ * then first thing it needs to do is enter into that power
+ * state and then do setmode.
+ *
+ * When this function returns it is expected that:
+ * 1. Either encoder is in D0 power state or
+ * it defers until post_set_mode().
+ * 2. In case of external encoder (example: TVOut encoder)
+ * driving the reference clock, the clock is running.
+ *
+ * post_set_mode- This is called after GMCH DVO timings are on.
+ * This function can be null if there is nothing to do.
+ * This is used to do any post processing on the encoder
+ * after GMCH starts driving the timings. When this function
+ * returns it is expected that the encoder is in D0 power state.
+ * Parameters:
+ * context - port driver context
+ * mode - current timing
+ * flags - not used (for future use).
+ *
+ * set_attrs - to set provided list of attributes.
+ *
+ * get_attrs - to get list of attributes.
+ *
+ * get_timing_list - returns the list of supported modes for the current
+ * attributes. For example if the TVFormat is NTSC, this
+ * function will return only the modes supported for NTSC.
+ *
+ * set_power - to set the power state of the display device.
+ *
+ * get_power - to get the current power state of the display device.
+ *
+ * pd_save - to save the current state of the registers.
+ * - returns the current state in the double pointer 'state'.
+ *
+ * pd_restore - to restore to the passed state. This functions frees the
+ * resources allocated that state.
+ * - pass the previously saved state in 'state'.
+ *
+ * If PD_NO_RESTORE_FREE_STATE is set, then it just frees
+ * the resources without restoring the state.
+ *
+ * pd_get_port_status - to get the status of port/display
+ *
+ *
+ * All functions return value:
+ * == 0 - if success
+ * != 0 - if failure
+ */
+
+
+/* Note on version AA.BB.CC.DD
+ * AA - Major version
+ * BB - Minor version
+ * CC - Patch version if any
+ * DD - Bug fixes if any
+ *
+ * 01.00.00.00 is the first initial major version */
+typedef struct _pd_version {
+ unsigned char major;
+ unsigned char minor;
+ unsigned char patch;
+ unsigned char bug_fix;
+} pd_version_t;
+
+
+typedef enum {
+ PD_DISP_STATUS_DETACHED = 0, /* Display is not connected */
+ PD_DISP_STATUS_ATTACHED, /* Display is connected */
+ PD_DISP_STATUS_UNKNOWN /* Unable to determine */
+} pd_display_status_t;
+
+/* Port/Display information */
+typedef struct _pd_port_status {
+ pd_display_status_t connected; /* Display status */
+ unsigned long display_type; /* Type of display, if connected */
+} pd_port_status_t;
+
+typedef struct _pd_driver {
+ unsigned long pd_sdk_version; /* PD SDK version - interface ver */
+ char name[PD_NAME_SIZE]; /* Descriptive name of port driver */
+ char num_devices; /* Number of devices it is driving */
+ pd_version_t *version; /* Driver version */
+ unsigned long type;
+ unsigned long flags;
+ unsigned long *dab_list; /* PD_DAB_LIST_END terminated list */
+ unsigned long i2c_speed; /* Encoder I2C speed in KHz */
+ unsigned long (*validate)(unsigned long cookie);
+ int (*open) (pd_callback_t *callback, void **context);
+ int (*init_device)(void *context);
+ int (*pd_close) (void *context);
+ int (*set_mode) (void *context, pd_timing_t *mode, unsigned long flags);
+ int (*post_set_mode)(void *context, pd_timing_t *mode, unsigned long flags);
+ int (*set_attrs) (void *context, unsigned long num, pd_attr_t *list);
+ int (*get_attrs) (void *context, unsigned long *num, pd_attr_t **list);
+ int (*get_timing_list)(void*context,pd_timing_t*in_list,pd_timing_t**list);
+ int (*set_power) (void *context, unsigned long state);
+ int (*get_power) (void *context, unsigned long *state);
+ int (*pd_save) (void *context, void **state, unsigned long flags);
+ int (*pd_restore) (void *context, void *state, unsigned long flags);
+ int (*pd_get_port_status) (void *context, pd_port_status_t *port_status);
+} pd_driver_t;
+
+/* Mode filter helper function for port drivers */
+/* Structure representing encoder capabilities for mode filtering */
+typedef struct _pd_dvo_info {
+ unsigned long min_dclk; /* Min clock */
+ unsigned long max_dclk; /* Max clock */
+ unsigned char upscale; /* Is upscalable? */
+ unsigned char downscale; /* Is downscalable? */
+ unsigned short upscale_min_width; /* Min upscale width */
+ unsigned short upscale_min_height; /* Min upscale height */
+ unsigned short downscale_max_width; /* Max downscale width */
+ unsigned short downscale_max_height; /* Max downscale height */
+} pd_dvo_info_t;
+
+typedef struct _pd_display_info {
+ unsigned char panel_fit; /* Incoming */
+ unsigned char fixed_res; /* Outgoing */
+ unsigned short width; /* Outgoing */
+ unsigned short height; /* Outgoing */
+ pd_timing_t *native_dtd; /* Outgoing */
+} pd_display_info_t;
+
+/* All following functions are provided to port drivers as a binary file.
+ *
+ * pd_register: This function is called by port driver to register with
+ * display driver. It passes its driver structure to display
+ * driver.
+ *
+ * pd_malloc: This function is used to allocate any dynamic memory required
+ * in port driver. Port driver will pass the size of the memory
+ * it is requesting in bytes.
+ *
+ * Return value == pointer to the allocated memory on success
+ * == NULL if failed to allocated the memory
+ *
+ * pd_memset: This function is used to set the passed byte in memory
+ * for size bytes.
+ *
+ * pd_memcpy: This function is used to copy size bytes from src pointer to
+ * dest pointer.
+ *
+ * free: This function is used to free the memory previously allocated
+ * using malloc callback function.
+ *
+ * usleep: This function is used to get any delay in port driver.
+ * 'usec' is specified in micro seconds.
+ *
+ * No return value.
+ * ui_usleep: This function is used to get any delay in port driver uniterrupted.
+ * 'usec' is specified in micro seconds.
+ *
+ * No return value.
+ *
+ * printf: This function is used to do any debug prints for port driver.
+ * This has exactly the same syntax and usage of standard
+ * printf in 'C'.
+ *
+ * strcpy: This function is used to copy src string into dest string.
+ * This has exactly the same syntax and usage of standard
+ * strcpy in 'C'.
+ *
+ * filter: This function is to filter the incoming mode list based on
+ * dvo_info. Memory is allocated for outgoing list. No changes
+ * to in_list.
+ */
+int pd_register(void *handle, pd_driver_t *driver);
+void *pd_malloc(unsigned long size);
+void *pd_memset(void *address, int c, unsigned long size);
+void *pd_memcpy(void *dst, void *src, unsigned long size);
+void pd_free (void *address);
+
+void pd_usleep(unsigned long usec);
+void pd_ui_usleep(unsigned long usec);
+char *pd_strcpy(char *dest, char const *src);
+int *pd_printf(const char *format, ...);
+int pd_check_attr(pd_attr_t *curr, pd_attr_t *in);
+/* Mode filter helper function for port drivers */
+int pd_filter_timings(void *context, pd_timing_t *inlist, pd_timing_t **olist,
+ pd_dvo_info_t *dvo_info, pd_display_info_t *display_info);
+
+/* pd_get_attr() : To return the request attr from the list.
+ * In case of 'attr_id' is a list type attribute, then caller
+ * can request either LIST head itself or list entry for that
+ * attribute. */
+#define PD_GET_ATTR_LIST 0x0001
+#define PD_GET_ATTR_LIST_ENTRY 0x0002
+pd_attr_t *pd_get_attr(pd_attr_t *attr_list, unsigned long num_attrs,
+ unsigned long attr_id, unsigned long flag);
+
+/*
+// Typedefinitions
+typedef int (*pd_register_p) (void *handle, pd_driver_t *driver);
+typedef void *(*pd_malloc_p)(unsigned long size);
+typedef void *(*pd_memset_p)(void *address, int c, unsigned long size);
+typedef void *(*pd_memcpy_p)(void *dst, void *src, unsigned long size);
+typedef void (*pd_free_p) (void *address);
+typedef void (*pd_usleep_p)(unsigned long usec);
+typedef char *(*pd_strcpy_p)(char *dest, char const *src);
+typedef int *(*pd_printf_p)(const char *format, ...);
+typedef int (*pd_check_attr_p)(pd_attr_t *curr, pd_attr_t *in);
+typedef pd_attr_t *(*pd_get_attr_p)(pd_attr_t *attr_list,
+ unsigned long num_attrs, unsigned long attr_id, unsigned long flag);
+typedef emgd_debug_t *(*pd_get_emgd_debug_p)( void );
+typedef unsigned long *(*pd_get_dropped_debug_messages_p)( void );
+typedef void *(*pd_get_debug_log_mutex_p)( void );
+
+// Mode filter helper function for port drivers
+typedef int (*pd_filter_timings_p)(void *context, pd_timing_t *inlist,
+ pd_timing_t **olist, pd_dvo_info_t *dvo_info,
+ pd_display_info_t *display_info);
+*/
+#endif /* _PD_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/pd_init.h b/drivers/gpu/drm/emgd/emgd/include/pd_init.h
new file mode 100644
index 0000000..eb78285
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pd_init.h
@@ -0,0 +1,191 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_init.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains configurable definitions to statically link port
+ * drivers with display driver.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_INIT_H
+#define _PD_INIT_H
+
+#include <config.h>
+
+/* Enable Analog (CRT) port driver */
+#ifdef CONFIG_PD_ANALOG
+extern int analog_init(void *handle);
+#define ANALOG_INIT(handle) analog_init(handle)
+#else
+#define ANALOG_INIT(handle) 0
+#endif
+
+/* Enable RGBA port driver */
+#ifdef CONFIG_PD_RGBA
+extern int rgba_init(void *handle);
+#define RGBA_INIT(handle) rgba_init(handle)
+#else
+#define RGBA_INIT(handle) 0
+#endif
+
+/* Enable Silicon Image 154/164 FP port driver */
+#ifdef CONFIG_PD_SII164
+extern int sii164_init(void *handle);
+#define SII164_INIT(handle) sii164_init(handle)
+#else
+#define SII164_INIT(handle) 0
+#endif
+
+/* Enable Texas Instruments 410 FP port driver */
+#ifdef CONFIG_PD_TI410
+extern int ti410_init(void *handle);
+#define TI410_INIT(handle) ti410_init(handle)
+#else
+#define TI410_INIT(handle) 0
+#endif
+
+/* Enable Chrontel 7009 TMDS & TVOut port driver */
+#ifdef CONFIG_PD_CH7009
+extern int ch7009_init(void *handle);
+#define CH7009_INIT(handle) ch7009_init(handle)
+#else
+#define CH7009_INIT(handle) 0
+#endif
+
+/* Enable National Semiconductor 2501 LVDS port driver */
+#ifdef CONFIG_PD_NS2501
+extern int ns2501_init(void *handle);
+#define NS2501_INIT(handle) ns2501_init(handle)
+#else
+#define NS2501_INIT(handle) 0
+#endif
+
+/* Enable TL955 port driver */
+#ifdef CONFIG_PD_TL955
+extern int tl955_init(void *handle);
+#define TL955_INIT(handle) tl955_init(handle)
+#else
+#define TL955_INIT(handle) 0
+#endif
+
+/* Enable Th164 port driver */
+#ifdef CONFIG_PD_TH164
+extern int th164_init(void *handle);
+#define TH164_INIT(handle) th164_init(handle)
+#else
+#define TH164_INIT(handle) 0
+#endif
+
+/* Enable FS454 port driver */
+#ifdef CONFIG_PD_FS454
+extern int fs454_init(void *handle);
+#define FS454_INIT(handle) fs454_init(handle)
+#else
+#define FS454_INIT(handle) 0
+#endif
+
+/* Enable NS387/389 port driver */
+#ifdef CONFIG_PD_NS387
+extern int ns387_init(void *handle);
+#define NS387_INIT(handle) ns387_init(handle)
+#else
+#define NS387_INIT(handle) 0
+#endif
+
+/* Enable connexant port driver */
+#ifdef CONFIG_PD_CX873
+extern int cx873_init(void *handle);
+#define CX873_INIT(handle) cx873_init(handle)
+#else
+#define CX873_INIT(handle) 0
+#endif
+
+/* Enable Internal LVDS port driver */
+#ifdef CONFIG_PD_LVDS
+extern int lvds_init(void *handle);
+#define LVDS_INIT(handle) lvds_init(handle)
+#else
+#define LVDS_INIT(handle) 0
+#endif
+
+/* Enable SDVO port driver */
+#ifdef CONFIG_PD_SDVO
+extern int sdvo_init(void *handle);
+#define SDVO_INIT(handle) sdvo_init(handle)
+#else
+#define SDVO_INIT(handle) 0
+#endif
+
+/* Enable Integrated TV port driver for NAPA*/
+#ifdef CONFIG_PD_TV
+extern int tv_init(void *handle);
+#define TV_INIT(handle) tv_init(handle)
+#else
+#define TV_INIT(handle) 0
+#endif
+
+/* Enable FS460 port driver */
+#ifdef CONFIG_PD_FS460
+extern int fs460_init(void *handle);
+#define FS460_INIT(handle) fs460_init(handle)
+#else
+#define FS460_INIT(handle) 0
+#endif
+
+/* Enable FS450 port driver */
+#ifdef CONFIG_PD_FS450
+extern int fs450_init(void *handle);
+#define FS450_INIT(handle) fs450_init(handle)
+#else
+#define FS450_INIT(handle) 0
+#endif
+
+/* Enable Chrontel 7017 LVDS & TVOut port driver */
+#ifdef CONFIG_PD_CH7017
+extern int ch7017_init(void *handle);
+#define CH7017_INIT(handle) ch7017_init(handle)
+#else
+#define CH7017_INIT(handle) 0
+#endif
+
+/* Enable internal HDMI port driver */
+#ifdef CONFIG_PD_HDMI
+extern int hdmi_init(void *handle);
+#define HDMI_INIT(handle) hdmi_init(handle)
+#else
+#define HDMI_INIT(handle) 0
+#endif
+
+/* Enable Dummy Port Driver*/
+#ifdef CONFIG_PD_PD000
+extern int pd000_init(void *handle);
+#define PD000_INIT(handle) pd000_init(handle)
+#else
+#define PD000_INIT(handle) 0
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/pi.h b/drivers/gpu/drm/emgd/emgd/include/pi.h
new file mode 100644
index 0000000..d14d39e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pi.h
@@ -0,0 +1,86 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pi.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PI_H_
+#define _PI_H_
+
+#include <context.h>
+#include <mode.h>
+#include <pd.h>
+
+/* power states */
+#define IGD_DEVICE_ON 1
+#define IGD_DEVICE_OFF 0
+
+#define PI_FIRMWARE_EDID 0x1
+#define PI_FIRMWARE_DISPLAYID 0x2
+
+/* get_native_dtd() flags */
+#define PI_ALL_TIMINGS 0x0001
+#define PI_SUPPORTED_TIMINGS 0x0002
+extern unsigned long get_native_dtd(igd_timing_info_t *timing_table,
+ unsigned long flags, pd_timing_t **native_dtd, unsigned long native_flags);
+
+extern igd_timing_info_t crt_timing_table[];
+extern int crt_timing_table_size;
+
+#ifndef CONFIG_MICRO
+extern igd_timing_info_t cea_timing_table[];
+extern int cea_timing_table_size;
+extern type_std_t cea_std_lookup[];
+extern int cea_std_lookup_size;
+#endif
+
+extern int pi_pd_register(pd_driver_t *pd_driver);
+extern int pi_pd_register(pd_driver_t *pd_driver);
+extern int pi_read_regs(void *callback_context, pd_reg_t *list,
+ unsigned long reg_type);
+extern int pi_write_regs(void *callback_context, pd_reg_t *list,
+ unsigned long reg_type);
+extern int pi_program_port_dvo(igd_display_context_t *, unsigned long);
+extern int pi_program_port_analog(igd_display_context_t *, unsigned long);
+extern int pi_program_port_rgba(igd_display_context_t *, unsigned long);
+extern int pi_program_port_lvds(igd_display_context_t *, unsigned long);
+
+/* Function to get attr value from port driver attr list */
+extern int pi_pd_find_attr_and_value(igd_display_port_t *port,
+ unsigned long attr_id,
+ unsigned long flag,
+ pd_attr_t **caller_pd_attr,
+ unsigned long * attr_value);
+
+/* Function to get attr value from user provided init attribute list */
+extern int pi_get_port_init_attr(igd_display_port_t *port,
+ unsigned long id,
+ unsigned long *value);
+extern int pi_save_mode_state(igd_display_port_t *port,
+ reg_state_id_t reg_state_id);
+#endif /* _PI_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h b/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
new file mode 100644
index 0000000..3a1417c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
@@ -0,0 +1,67 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the inter-module header file for the client context module.
+ * It contains data structures needed for modules to use and manipulate
+ * the device state including hardware context switching.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _APPCONTEXT_PLB_H
+#define _APPCONTEXT_PLB_H
+
+#include <context.h>
+#include <igd_mode.h>
+
+/*
+ * This data structure contains a copy of all needed state variables and
+ * the logical context used by hardware for context switching. An IGD
+ * client driver can allocate a client context for each client or allocate
+ * just one to be shared by all clients.
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+typedef struct _appcontext {
+ void *state3d;
+ void *state2d;
+ unsigned char *hw_context_virt;
+ unsigned long hw_context_phys;
+ unsigned long hw_context_offset;
+}appcontext_t, appcontext_plb_t;
+
+int appcontext_set_plb(igd_display_h display,
+ int priority,
+ appcontext_t *context,
+ int extstate_save_enable,
+ int extstate_restore_enable,
+ int force_restore,
+ int restore_inhibit);
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h b/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
new file mode 100644
index 0000000..c4252cb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Device dependent header file for the command interface for poulsbo
+ * devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PLB_CMD_H
+#define _PLB_CMD_H
+
+#include <io.h>
+#include <sched.h>
+
+#include <instr_common.h>
+#include <utils.h>
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/context.h b/drivers/gpu/drm/emgd/emgd/include/plb/context.h
new file mode 100755
index 0000000..b9ef5038f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/context.h
@@ -0,0 +1,212 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: context.h
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_PLB_CONTEXT_H
+#define _HAL_PLB_CONTEXT_H
+
+#include <sched.h>
+
+#include <pci.h>
+#include <igd_render.h>
+#include <plb/sgx.h>
+#include <servicesint.h>
+/*
+ * FIXME: Promote io_mapped/io_base to DI layer
+ *
+ * Note: This define is for the vBIOS OAL only. Do not use
+ * it anywhere else, use the actual type name.
+ */
+#define PLATFORM_CONTEXT_T platform_context_plb_t
+
+typedef struct psb_use_reg {
+ unsigned long reg_seq;
+ unsigned long base;
+ unsigned long size;
+ unsigned long data_master;
+ unsigned char * virt;
+} psb_use_reg_t;
+
+typedef struct drmBO {
+ unsigned long offset;
+} drmBO_t;
+
+typedef struct psb_closed_dpm {
+ drmBO_t *page_table_bo;
+ drmBO_t *parameter_bo;
+ unsigned int num_pages;
+ unsigned int context_id;
+ unsigned int ta_global_list;
+ unsigned int ta_threshold;
+ unsigned int zls_threshold;
+} psb_closed_dpm_t;
+
+typedef struct _psb_sgx_priv {
+
+ /* HW workaround table */
+ /* ***********************************************/
+ struct pclosed_vopt vopt;
+
+ /* stuff required to be setup by sgx_init in cmd */
+ /* ***********************************************/
+ struct psb_use_reg use_code[SGX_MAX_USSE_THRDS];
+ igd_dma_t drm_bo[DRM_BO_MEM_TYPES];
+
+ igd_dma_t commBO;
+ igd_dma_t codeBO;
+ igd_dma_t sProg;
+ igd_dma_t geom;
+ igd_dma_t local;
+
+ unsigned long usse_reg_dm;
+ unsigned long num_use_attribute_registers;
+
+ psb_closed_dpm_t dpms[2];
+ /* What is an igd_command variable doing here?!
+ * should we move this into an appcontext_plb
+ * structure and let psb_sgx_priv_t have a ptr
+ * to the active appcontext_plb pointer? i.e. an
+ * appcontext created for 3d context?
+ */
+ igd_command_t context_select;
+
+ /* stuff required to be setup by sgx_init in gart */
+ /* ***********************************************/
+ unsigned int cache_ctrl;
+
+ /* state required to be setup by sgx_init in pwr */
+ /* ***********************************************/
+} psb_sgx_priv_t;
+
+/* Values used in platform_context_plb_t->flip_pending
+ * This corresponds to the pipe, which is a bit strange,
+ * but since the flip must wait for a vBlank, it is
+ * based off the PIPE */
+#define PLB_FLIP_PIPE_A_PENDING 1
+#define PLB_FLIP_PIPE_B_PENDING 2
+
+typedef struct _tnc_topaz_priv {
+
+ /* current video task */
+ unsigned long topaz_cur_codec;
+ unsigned long cur_mtx_data_size;
+ int topaz_needs_reset;
+ int topaz_start_idle;
+ unsigned long topaz_idle_start_jiffies;
+ /* used by topaz_lockup */
+ unsigned long topaz_current_sequence;
+ unsigned long topaz_last_sequence;
+ unsigned long topaz_finished_sequence;
+
+ /*
+ * topaz command queueu
+ */
+ int topaz_busy; /* 0 means topaz is free */
+ int topaz_fw_loaded;
+
+ /* topaz ccb data */
+ unsigned long topaz_ccb_buffer_addr;
+ unsigned long topaz_ccb_ctrl_addr;
+ unsigned long topaz_ccb_size;
+ unsigned long topaz_cmd_windex;
+ unsigned short topaz_cmd_seq;
+
+ unsigned long stored_initial_qp;
+ unsigned long topaz_frame_skip;
+ unsigned long topaz_dash_access_ctrl;
+
+ unsigned char *topaz_ccb_wb;
+ unsigned long topaz_wb_offset;
+ unsigned long *topaz_sync_addr;
+ unsigned long topaz_sync_offset;
+ unsigned long topaz_sync_cmd_seq;
+ unsigned long topaz_sync_id;
+ /**
+ * Virtual address to writeback memory in the aperture space.
+ */
+ unsigned char *virt_wb;
+ /**
+ * Offset in gmm space for write back memory.
+ */
+ unsigned long wb_offset;
+ int selected_codec;
+} tnc_topaz_priv_t;
+
+struct msvdx_pvr_info;
+
+typedef struct _platform_context_plb {
+ int irq;
+ unsigned short did;
+ os_pci_dev_t pcidev0;
+ os_pci_dev_t pcidev1;
+ os_pci_dev_t lpc_dev;
+ os_pci_dev_t bridgedev;
+ unsigned char tnc_dev3_rid; /* TNC Device 3 RID*/
+ os_pci_dev_t stbridgedev;
+ os_pci_dev_t stgpiodev;
+ unsigned long rendec_base0;
+ unsigned long rendec_base1;
+ /*
+ * Cached value of the SGX's PSB_CR_BIF_DIR_LIST_BASE1, which is
+ * used to configure MSVDX MMU base 0.
+ */
+ unsigned long psb_cr_bif_dir_list_base1;
+ int msvdx_needs_reset;
+ spinlock_t msvdx_lock;
+ spinlock_t msvdx_init_plb;
+ spinlock_t topaz_init_tnc;
+ unsigned long msvdx_status;
+ int msvdx_busy;
+ struct list_head msvdx_queue;
+ unsigned long msvdx_dash_access_ctrl;
+ struct msvdx_pvr_info *msvdx_pvr;
+ psb_sgx_priv_t sgx_priv_data;
+ tnc_topaz_priv_t tpz_private_data;
+ unsigned long msvdx_fence;
+ int topaz_busy;
+ unsigned long src_pat_data_offset;
+ unsigned long glyph_data_offset;
+ unsigned long sequence;
+ unsigned long mtx_submitted;
+ unsigned long mtx_completed;
+ unsigned long mtx_buf_size;
+ unsigned long host_buf_size;
+ unsigned long mtx_buf_offset;
+ unsigned long host_buf_offset;
+ /* Flip pending. This is used in the mode
+ * module, but it is intialized in the cmd
+ * module along with the other mutex-es */
+ unsigned int flip_pending;
+ os_pthread_mutex_t flip_mutex;
+ int force_polling;
+ int irq_enabled;
+} platform_context_plb_t, platform_context_tnc_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/instr.h b/drivers/gpu/drm/emgd/emgd/include/plb/instr.h
new file mode 100644
index 0000000..791808a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/instr.h
@@ -0,0 +1,224 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+#ifndef _INSTR_PLB_H
+#define _INSTR_PLB_H
+
+#include <instr_common.h>
+
+typedef struct _igd_vertex {
+ unsigned long x;
+ unsigned long x_ieee_fp;
+ unsigned long y;
+ unsigned long y_ieee_fp;
+ unsigned long z;
+ unsigned long z_ieee_fp;
+ unsigned long argb;
+} igd_vertex_t, *pigd_vertex_t;
+
+/* Common FP numbers */
+#define IEEE_FP_0 0x00000000
+#define IEEE_FP_1 0x3f800000
+
+/* For EMGD_WRITE32 */
+#include <io.h>
+
+
+/* All instruction sizes must be Double DWORD aligned for the current
+ * platform. The exception to this is the NOOP, which may be useful
+ * not being Double DWORD aligned. */
+
+/* color depth */
+#define PLB_PF_1BIT_PALETTE 0x0
+#define PLB_PF_2BIT_PALETTE 0x1
+#define PLB_PF_4BIT_PALETTE 0x2
+#define PLB_PF_8BIT_PALETTE 0x3
+#define PLB_PF_8BIT_ALPHA 0x4
+#define PLB_PF_4BIT_ALPHA 0x5
+#define PLB_PF_8BPP 0x6
+#define PLB_PF_16BPP4444 0x7
+#define PLB_PF_16BPP555 0x8
+#define PLB_PF_16BPP1555 0x9
+#define PLB_PF_16BPP565 0xA
+#define PLB_PF_24BPP 0xB
+#define PLB_PF_32BPP 0xC
+#define PLB_PF_32BPP_UYVY 0xD
+#define PLB_PF_32BPP_AYUV 0xE
+
+/*-----------------*/
+/* 2D Instructions */
+/*-----------------*/
+/* Size of 2D Instructions */
+#define PLB_2D_PAT_CONTROL_SIZE 1
+#define PLB_2D_CONTROL_SIZE 3
+#define PLB_2D_SRC_SURF_SIZE 2
+#define PLB_2D_DEST_SURF_SIZE 2
+#define PLB_2D_PAT_SURF_SIZE 2
+#define PLB_2D_MASK_SURF_SIZE 2
+#define PLB_2D_SRC_OFFSET_SIZE 1
+#define PLB_2D_MASK_OFFSET_SIZE 1
+#define PLB_2D_SRC_PAL_SIZE 1
+#define PLB_2D_PAT_PAL_SIZE 1
+/* The 2D_BLT_SIZE is different when doing a Fill */
+#define PLB_2D_BLT_SIZE 3
+#define PLB_2D_BLT_FILL_SIZE 4
+#define PLB_2D_CLIP_SIZE 2
+#define PLB_2D_FENCE_SIZE 1
+#define PLB_2D_FLUSH_SIZE 1
+#define PLB_2D_BLT_SRC_COPY_SIZE 3
+
+/* 2D instruction (BR0) */
+#define _PLB_2D_CLIP (0x0 << 28)
+#define _PLB_2D_PAT_CONTROL (0x1 << 28)
+#define _PLB_2D_CONTROL (0x2 << 28)
+#define _PLB_2D_SRC_OFFSET (0x3 << 28)
+#define _PLB_2D_MASK_OFFSET (0x4 << 28)
+#define _PLB_2D_FENCE (0x7 << 28)
+#define _PLB_2D_BLT (0x8 << 28)
+#define _PLB_2D_SRC_SURF (0x9 << 28)
+#define _PLB_2D_DEST_SURF (0xa << 28)
+#define _PLB_2D_PAT_SURF (0xb << 28)
+#define _PLB_2D_SRC_PAL (0xc << 28)
+#define _PLB_2D_PAT_PAL (0xd << 28)
+#define _PLB_2D_MASK_SURF (0xe << 28)
+#define _PLB_2D_FLUSH (0xf << 28)
+
+/* In 2D Control */
+#define PSB_2D_SRCCK_CTRL 1
+#define PSB_2D_DSTCK_CTRL 2
+#define PSB_2D_ALPHA_CTRL 4
+
+#define PLB_2D_BLT_CTRL_ROT_0 0
+#define PLB_2D_BLT_CTRL_ROT_90 (1<<25)
+#define PLB_2D_BLT_CTRL_ROT_180 (2<<25)
+#define PLB_2D_BLT_CTRL_ROT_270 (3<<25)
+
+/* Top Left or Bottom Right */
+#define PLB_2D_BLT_CTRL_ORDER_TL2BR 0
+#define PLB_2D_BLT_CTRL_ORDER_BR2TL (1<<23)
+#define PLB_2D_BLT_CTRL_ORDER_TR2BL (2<<23)
+#define PLB_2D_BLT_CTRL_ORDER_BL2TR (3<<23)
+
+#define PLB_2D_BLT_CTRL_DEST_CK_DISABLE 0
+#define PLB_2D_BLT_CTRL_DEST_CK_PASS_MATCH (1<<21)
+#define PLB_2D_BLT_CTRL_DEST_CK_KILL_MATCH (2<<21)
+
+#define PLB_2D_BLT_CTRL_SRC_CK_DISABLE 0
+#define PLB_2D_BLT_CTRL_SRC_CK_PASS_MATCH (1<<19)
+#define PLB_2D_BLT_CTRL_SRC_CK_KILL_MATCH (2<<19)
+
+#define PLB_2D_BLT_CTRL_CLIP_DISABLE 0
+#define PLB_2D_BLT_CTRL_CLIP_ENABLE (1<<18)
+
+#define PLB_2D_BLT_CTRL_ALPHA_BLEND_DISABLE 0
+#define PLB_2D_BLT_CTRL_ALPHA_BLEND_ENABLE (1<<17)
+
+#define PLB_2D_BLT_CTRL_FILL 0
+#define PLB_2D_BLT_CTRL_PATTERN (1<<16)
+
+/*----------------*/
+/* 2D Abstraction */
+/*----------------*/
+#define PLB_2D_CLIP(queue, xmin, xmax, ymin, ymax) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_CLIP | (xmax << 12) | xmin); \
+ CMD_2D_WRITE_PLB(queue, (ymax << 12) | ymin);
+
+#define PLB_2D_PAT_CONTROL(queue, pt, width, height) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_CONTROL | (pt.x << 15) | \
+ (pt.y << 10) | (width << 5) | height);
+
+#define PLB_2D_CONTROL(queue, ctrl_flag, ck_color, ck_mask) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_CONTROL | ctrl_flag); \
+ CMD_2D_WRITE_PLB(queue, ck_color); \
+ CMD_2D_WRITE_PLB(queue, ck_mask);
+
+#define PLB_2D_FENCE(queue) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_FENCE);
+
+#define PLB_2D_FLUSH(queue) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_FLUSH);
+
+#define PLB_2D_DEST_SURF(queue, pf, pitch, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_DEST_SURF | (pf<<15) | pitch); \
+ CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_SRC_SURF(queue, pf, pitch, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_SURF | (pf<<15) | pitch); \
+ CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_PAT_SURF(queue, pf, pitch, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_SURF | (pf<<15) | pitch); \
+ CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_MASK_SURF(queue, pitch, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_MASK_SURF | pitch); \
+ CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_SRC_OFFSET(queue, pt) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_OFFSET | (pt.x<<12) | pt.y);
+
+#define PLB_2D_MASK_OFFSET(queue, pt) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_MASK_OFFSET | (pt.x<<12) | pt.y);
+
+#define PLB_2D_SRC_PAL(queue, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_PAL | offset);
+
+#define PLB_2D_PAT_PAL(queue, offset) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_PAL | offset);
+
+/* Color fill from Top Left to Bottom Right */
+#define PLB_2D_BLT_FILL_TL2BR(queue, control, rop, fill, rect) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop); \
+ CMD_2D_WRITE_PLB(queue, fill); \
+ CMD_2D_WRITE_PLB(queue, (rect->x1<<12) | rect->y1); \
+ CMD_2D_WRITE_PLB(queue, ((rect->x2-rect->x1)<<12) | \
+ (rect->y2-rect->y1));
+
+/* Color fill from Bottom Right to Top Left */
+#define PLB_2D_BLT_FILL_BR2TL(queue, control, rop, fill, rect) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop); \
+ CMD_2D_WRITE_PLB(queue, fill); \
+ CMD_2D_WRITE_PLB(queue, ((rect->x2-1)<<12) | (rect->y2-1)); \
+ CMD_2D_WRITE_PLB(queue, ((rect->x2-rect->x1)<<12) | \
+ (rect->y2-rect->y1));
+
+#define PLB_2D_BLT_SRC_COPY(queue, control, rop, pt, w, h) \
+ CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop); \
+ CMD_2D_WRITE_PLB(queue, (pt.x<<12) | pt.y); \
+ CMD_2D_WRITE_PLB(queue, (w<<12) | h);
+
+#define PLB_2D_BLT_CHROMA(queue, chroma_color) \
+ CMD_2D_WRITE_PLB(queue, chroma_color);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/mi.h b/drivers/gpu/drm/emgd/emgd/include/plb/mi.h
new file mode 100644
index 0000000..fcbc706
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/mi.h
@@ -0,0 +1,77 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is a header file for the Intel GFX commands.
+ * This includes commands specific to Intel hardware and structures specific
+ * to Intel hardware. All other commands and structures are available
+ * through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MI_H
+#define _MI_H
+
+#include <igd_mode.h>
+#include <igd_render.h>
+
+/* FIXME: This file has not been checked for PLB. */
+
+#define MI_FLUSH_OPTIONS_MASK 0x0000000f
+#define MI_FLUSH_MAP 0x00000001
+#define MI_FLUSH_RENDER 0x00000004
+/* #define MI_FLUSH_END_SCENE 0x00000008 Not available on PLB? */
+/* #define MI_FLUSH_WRITE_DIRTY 0x00000010 Not available on PLB? */
+
+extern int mi_display_buffer_info_plb(igd_display_h display_h,
+ int priority,
+ unsigned long flags);
+
+extern int mi_wait_scan_priority_arb_on_off_plb(igd_command_t *addr,
+ int priority, int enable);
+
+extern int mi_wait_scan_lines_excl_plb(igd_display_h display_h,
+ int priority,
+ unsigned long start,
+ unsigned long end);
+
+extern int mi_wait_scan_lines_incl_plb(igd_display_h display_h,
+ int priority,
+ unsigned long start,
+ unsigned long end);
+
+extern int mi_wait_vblank_plb(igd_display_h display_h,
+ int priority);
+
+extern int mi_flush_plb(igd_display_h display_h, int priority,
+ unsigned int flush_options, unsigned int flags);
+
+extern int mi_wait_for_scan_plb(igd_display_h display_h, int priority,
+ igd_rect_t *dest_rect);
+
+extern int mi_user_interrupt_plb(igd_display_h display_h, int priority);
+
+#endif /* _MI_H */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/regs.h b/drivers/gpu/drm/emgd/emgd/include/plb/regs.h
new file mode 100644
index 0000000..95d880f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/regs.h
@@ -0,0 +1,747 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: regs.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the register definition file for the PLB platform. This should
+ * contain device dependent register definitions. Standard register
+ * definitions (VGA, PCI, etc) should not be put in this file. For those
+ * see pci.h or vga.h.
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * Note: Use _REGS_H_ instead of _PLB_REGS_H_ to insure that no file can
+ * include 2 device dependent register files.
+ */
+#ifndef _REGS_H_
+#define _REGS_H_
+
+#include <pci.h>
+#include <psb_regs.h>
+#include <msvdx.h>
+
+/*-----------------------------------------------------------------------------
+ * PCI Register Definitions
+ *---------------------------------------------------------------------------*/
+#define PLB_PCI_MMADR PCI_BAR_0
+#define PLB_PCI_IOBAR PCI_BAR_1
+#define PLB_PCI_GMADR PCI_BAR_2
+#define PLB_PCI_GTTADR PCI_BAR_3
+
+#define PLB_PCI_GC 0x52
+#define PLB_PCI_BSM 0x5C
+
+#define PLB_MMIO_SIZE (512*1024)
+#define PLB_GTT_SIZE (128*1024)
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane A Register Definitions (70180h - 70188h)
+ *---------------------------------------------------------------------------*/
+#define DSPAAFLIP 0x7017C
+#define DSPACNTR 0x70180
+#define DSPAADDR 0x70184
+#define DSPASTRIDE 0x70188
+#define DSPASIZE 0x70190
+#define DSPAKEYVAL 0x70194
+#define DSPAKEYMASK 0x70198
+
+/*
+ * FIXME: Review and clean up this file. Everything below this point needs
+ * to be reviewed for accuracy or removed.
+ */
+
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG 0x3DA /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA /* Feature Control Register (Read) */
+#define MSR_PORT 0x3C2 /* Miscellaneous Output Port */
+#define MSR_PORT_LSB 0xC2 /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT 0x3CC /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00 0x3C2 /* Input Status Register 0 */
+#define STATUS_REG_01 0x3DA /* Input Status Register 1 */
+#define STATUS_REG_01_MONO 0x3BA /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK 0x3C6 /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX 0x3C7 /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE 0x3C7 /* Color Palette State Register */
+#define DAC_WRITE_INDEX 0x3C8 /* Color Palette Index Register */
+#define DAC_DATA_REG 0x3C9 /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Attribute Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define AR_PORT_LSB 0xC0 /*Attribute Controller Index Port LSB */
+
+#define AR00 0x00 /* Color Data Register */
+#define AR01 0x01 /* Color Data Register */
+#define AR02 0x02 /* Color Data Register */
+#define AR03 0x03 /* Color Data Register */
+#define AR04 0x04 /* Color Data Register */
+#define AR05 0x05 /* Color Data Register */
+#define AR06 0x06 /* Color Data Register */
+#define AR07 0x07 /* Color Data Register */
+#define AR08 0x08 /* Color Data Register */
+#define AR09 0x09 /* Color Data Register */
+#define AR0A 0x0A /* Color Data Register */
+#define AR0B 0x0B /* Color Data Register */
+#define AR0C 0x0C /* Color Data Register */
+#define AR0D 0x0D /* Color Data Register */
+#define AR0E 0x0E /* Color Data Register */
+#define AR0F 0x0F /* Color Data Register */
+#define AR10 0x10 /* Mode Control Register */
+#define AR11 0x11 /* Overscan Color Register */
+#define AR12 0x12 /* Color Plane Enable Register */
+#define AR13 0x13 /* Horizontal Pixel Panning Register */
+#define AR14 0x14 /* Pixel Pad Register */
+
+
+/*-----------------------------------------------------------------------------
+ * CRT Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define CR_PORT_LSB 0xD4 /* CRT Controller Index Port LSB */
+#define CRT_3D4 0x3D4 /* Color CRTC Index Port */
+#define CRT_3B4 0x3B4 /* Monochrome CRTC Index Port */
+
+#define CR00 0x00 /* Horizontal Total Register */
+#define CR01 0x01 /* Horizontal Display Enable End Reg */
+#define CR02 0x02 /* Horizontal Blank Start Register */
+#define CR03 0x03 /* Horizontal Blank End Register */
+#define CR04 0x04 /* Horizontal Sync Start Register */
+#define CR05 0x05 /* Horizontal Sync End Register */
+#define CR06 0x06 /* Vertical Total Register */
+#define CR07 0x07 /* Overflow Register */
+#define CR08 0x08 /* Preset Row Scan Register */
+#define CR09 0x09 /* Maximum Scan Line Register */
+#define DOUBLE_SCANLINE BIT7 /* Double scan ( 1 = Enable ) */
+#define LCOMP_BIT9 BIT6 /* Bit 9 of line compare register */
+#define VBLANK_BIT9 BIT5 /* Bit 9 of vertical blank start */
+#define CR0A 0x0A /* Cursor Start Scan Line Register */
+#define CR0B 0x0B /* Cursor End Scan Line Register */
+#define CR0C 0x0C /* Start Address High Register */
+#define CR0D 0x0D /* Start Address Low Register */
+#define CR0E 0x0E /* Cursor Location High Register */
+#define CR0F 0x0F /* Cursor Location Low Register */
+#define CR10 0x10 /* Vertical Sync Start Register */
+#define CR11 0x11 /* Vertical Sync End Register */
+#define CR12 0x12 /* Vertical Display Enable End Reg */
+#define CR13 0x13 /* Offset Register */
+#define CR14 0x14 /* Underline Row Register */
+#define CR15 0x15 /* Vertical Blank Start Register */
+#define CR16 0x16 /* Vertical Blank End Register */
+#define CR17 0x17 /* CRT Mode Control Register */
+#define CR18 0x18 /* Line Compare Register */
+#define CR22 0x22 /* Memory Data Latches Register */
+#define CR24 0x24 /* Attribute Controller Toggle Reg */
+
+
+/*-----------------------------------------------------------------------------
+ * Graphics Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define GR_PORT_LSB 0xCE /* Graphics Controller Index Port LSB */
+
+#define GR00 0x00 /* Set/Reset Register */
+#define GR01 0x01 /* Enable Set/Reset Register */
+#define GR02 0x02 /* Color Compare Register */
+#define GR03 0x03 /* Data Rotate Register */
+#define GR04 0x04 /* Read Map Select Register */
+#define GR05 0x05 /* Graphics Mode Register */
+#define GR06 0x06 /* Micsellaneous Register */
+#define RANGE_MAP_MASK BIT3 + BIT2 /* Address range to map mask */
+#define A0_BF_RANGE 000h /* Map to A0000h-BFFFFh range */
+#define GRAF_MODE BIT0 /* 1 = Grahics mode, 0 = Text mode */
+#define GR07 0x07 /* Color Don't Care Register */
+#define GR08 0x08 /* Bit Mask Register */
+#define GR10 0x10 /* Address Mapping */
+#define PAGING_TARGET BIT2 + BIT1 /* 00 = Local/Stolen, 01 = Memory mapped regs */
+#define PAGE_MODE BIT0 /* Page Map allow access to all FB mem */
+#define GR11 0x11 /* Page Selector */
+#define GR18 0x18 /* Software Flag */
+
+
+/*-----------------------------------------------------------------------------
+ * Sequencer Register Definitions
+ *---------------------------------------------------------------------------*/
+#define SR_PORT_DATA 0x3C5 /* Sequencer Data Port */
+#define SR_PORT_LSB 0xC4 /* Sequencer Index Port LSB */
+
+#define SR00 0x00 /* Reset Register */
+#define SR01 0x01 /* Clocking Mode Register */
+#define DOT_CLOCK_DIVIDE BIT3 /* Divide pixel clock by 2 */
+#define SR02 0x02 /* Plane/Map Mask Register */
+#define SR03 0x03 /* Character Font Register */
+#define SR04 0x04 /* Memory Mode Register */
+#define SR07 0x07 /* Horizontal Character Counter Reset */
+
+
+
+
+
+#define PLB_OFFSET_VGA_MSAC 0x62
+#define INTEL_OFFSET_VGA_CORECLK 0xF0
+
+#define INTEL_OFFSET_BRIDGE_CAPREG 0xE0
+
+#define PCI_CAPREG_4 0x44 /* Capability Identification Reg[39:31] */
+#define PCI_MOBILE_BIT BIT0
+
+#define PCI_GMS_MASK BIT6 + BIT5 + BIT4 /* GFX Mode Select Bits Mask */
+#define PCI_LOCAL BIT4 /* Local memory enabled */
+#define PCI_DVMT_512K BIT5 /* 512KB DVMT */
+#define PCI_DVMT_1M BIT5 + BIT4 /* 1MB DVMT */
+#define PCI_DVMT_8M BIT6 /* 8MB DVMT */
+
+#define PCI_DRB_REG 0x60 /* DRAM row boundary Register */
+#define PCI_DRC_REG 0x7C /* DRAM Controller Mode Register */
+#define PCI_DT_MASK BIT0 + BIT1 /* Select SDRAM types.
+ * = 00: Single data rate SDRAM
+ * = 01: Dual data rate SDRAM
+ * = Other: Reserved
+ */
+#define DT_SDR_SDRAM 00 /* Single data rate SDRAM */
+#define DT_DDR_SDRAM 01 /* Dual data rate SDRAM */
+
+#define PCI_ESMRAMC_REG 0x91 /* Extended System Management RAM Reg */
+#define PCI_TSEG_SZ BIT1 /* TSEG size bit */
+#define PCI_TSEG_512K 0 /* 512K TSEG */
+#define PCI_TSEG_1M BIT1 /* 1MB TSEG */
+
+#define PCI_GCLKIO_REG 0xC0 /* GMCH Clock and IO Control Register */
+#define PCI_AGP_Bit BIT9 /* AGP/DVO Mux Select:
+ * = 0, DVO/ZV
+ * = 1, AGP
+ */
+#define PCI_GMCHCFG_REG 0xC6 /* GMCH Configuration Register */
+#define PCI_SMFREQ_MASK BIT10 + BIT11
+ /* System Mem Frequency Select
+ * = 00: Intel Reserved
+ * = 01: System Memory Frequency is 166Mhz (DDR333) - Intel Reserved
+ * = 10: System Memory Frequency is 133Mhz (SDR133, DDR266)
+ * = 11: System Memory Frequency is 100Mhz (DDR200)
+ */
+#define SYS_MEM_FREQ_166 1 /* System Memory Frequency is 166Mhz */
+#define SYS_MEM_FREQ_133 2 /* System Memory Frequency is 133Mhz */
+#define SYS_MEM_FREQ_100 3 /* System Memory Frequency is 100Mhz */
+#define PCI_SMFREQ_POS 10 /* System Memory Frequency position */
+
+#define PCI_CONFIG_LMINT 0xE0
+#define PREALLOCATED_SIZE (8 * 1024 * 1024)
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG 0x3DA /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA /* Feature Control Register (Read) */
+#define MSR_PORT 0x3C2 /* Miscellaneous Output Port */
+#define MSR_PORT_LSB 0xC2 /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT 0x3CC /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00 0x3C2 /* Input Status Register 0 */
+#define STATUS_REG_01 0x3DA /* Input Status Register 1 */
+#define STATUS_REG_01_MONO 0x3BA /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK 0x3C6 /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX 0x3C7 /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE 0x3C7 /* Color Palette State Register */
+#define DAC_WRITE_INDEX 0x3C8 /* Color Palette Index Register */
+#define DAC_DATA_REG 0x3C9 /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Memory mapped I/O Registers Definitions
+ *---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Instruction and Interrupt Control Registers (01000h - 02FFFh)
+ *---------------------------------------------------------------------------*/
+#define PGTBL_CTL 0x02020 /* Page Table Control Register */
+#define HWS_PGA 0x02080 /* Hardware Status Page Address register */
+#define HWSTAM 0x02098 /* Hardware Status Mask */
+#define SCPD0 0x0209C /* Scratch Pad 0 (Debug) */
+#define IER 0x020A0 /* Interrupt Enable */
+#define IIR 0x020A4 /* Interrupt Identity */
+#define IMR 0x020A8 /* Interrupt Mask */
+#define ISR 0x020AC /* Interrupt Status */
+#define EIR 0x020B0 /* Error Identity */
+#define EMR 0x020B4 /* Error Mask */
+#define ESR 0x020B8 /* Error Status */
+#define FW_BLC1 0x020D8 /* FIFO Watermark Burst Length Control */
+#define FW_BLC2 0x020DC /* FIFO Watermark Burst Length Control */
+#define FW_BLC_SELF 0x020E0 /* Display FIFO Watermark */
+#define MI_ARB_STATE 0x020E4 /* Memory Interface Arbitration State */
+#define FW_BLC3 0x020EC /* FIFO Watermark Burst Length Control */
+#define G_DEBUG 0x020FC /* G-UNIT Debug enable register */
+
+
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (02000h - 031FFh)
+ * --------------------------------------------------------------------------*/
+#define FENCE0 0x02000 /* Fence table registers */
+#define FENCE1 0x02004
+#define FENCE2 0x02008
+#define FENCE3 0x0200C
+#define FENCE4 0x02010
+#define FENCE5 0x02014
+#define FENCE6 0x02018
+#define FENCE7 0x0201C
+#define FENCE8 0x03000
+#define FENCE9 0x03004
+#define FENCE10 0x03008
+#define FENCE11 0x0300C
+#define FENCE12 0x03010
+#define FENCE13 0x03014
+#define FENCE14 0x03018
+#define FENCE15 0x0301C
+
+/*-----------------------------------------------------------------------------
+ * MISC I/0 Contol Register ( 05000h - 05FFFh )
+ *---------------------------------------------------------------------------*/
+#define IO_OFF 0x05000 /* Register group offset */
+
+#define IO00 0x05000 /* Hsync / Vsync control register */
+#define GPIO0 0x05010 /* GPIO register 0 (DDC1) */
+#define DDC1_SCL_PIN GPIO0_SCL_PIN /* DDC1 SCL GPIO pin # */
+#define DDC1_SDA_PIN GPIO0_SDA_PIN /* DDC1 SDA CPIO pin # */
+#define GPIO1 0x05014 /* GPIO register 1 (I2C) */
+#define I2C_SCL_PIN GPIO1_SCL_PIN /* I2C SCL GPIO pin # */
+#define I2C_SDA_PIN GPIO1_SDA_PIN /* I2C SDA CPIO pin # */
+#define GPIO2 0x05018 /* GPIO register 2 (DDC2) */
+#define DDC2_SCL_PIN GPIO2_SCL_PIN /* DDC2 SCL GPIO pin # */
+#define DDC2_SDA_PIN GPIO2_SDA_PIN /* DDC2 SDA CPIO pin # */
+#define GPIO3 0x0501C /* GPIO register 3 (AGP mux DVI DDC) */
+#define GPIO4 0x05020 /* GPIO register 4 (AGP mux I2C) */
+#define GPIO5 0x05024 /* GPIO register 5 (AGP mux DDC2/I2C) */
+
+#define GPIOPIN0 GPIO0
+#define GPIOPIN1 GPIO0+1
+#define GPIOPIN2 GPIO1
+#define GPIOPIN3 GPIO1+1
+#define GPIOPIN4 GPIO2
+#define GPIOPIN5 GPIO2+1
+#define GPIOPIN6 GPIO3
+#define GPIOPIN7 GPIO3+1
+#define GPIOPIN8 GPIO4
+#define GPIOPIN9 GPIO4+1
+#define GPIOPIN10 GPIO5
+#define GPIOPIN11 GPIO5+1
+#define GPIOPINMAX 12
+
+#define GMBUS0 0x5100 /* GMBUS clock/device select register */
+#define GMBUS1 0x5104 /* GMBUS command/status register */
+#define GMBUS2 0x5108 /* GMBUS status register */
+#define GMBUS3 0x510C /* GMBUS data buffer register */
+#define GMBUS4 0x5110 /* GMBUS REQUEST_INUSE register */
+#define GMBUS5 0x5120 /* GMBUS 2-Byte Index register */
+#define GMBUS6 0x5124 /* GMBUS Clock divider */
+
+/* GMBUS1 Bits */
+#define SW_CLR_INT BIT31
+#define SW_RDY BIT30
+#define ENT BIT29
+#define STO BIT27
+#define ENIDX BIT26
+#define STA BIT25
+
+/* GMBUS2 Bits */
+#define INUSE BIT15
+#define HW_WAIT BIT14
+#define HW_TMOUT BIT13
+#define HW_INT BIT12
+#define HW_RDY BIT11
+#define HW_BUS_ERR BIT10
+#define GA BIT9
+
+/*-----------------------------------------------------------------------------
+ * Clock Control and PM Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define VGA0_DIVISOR 0x06000 /* VGA 0 Divisor */
+#define VGA1_DIVISOR 0x06004 /* VGA 1 Divisor */
+#define VGA_PD 0x06010 /* VGA Post Divisor Select */
+#define DPLLACNTR 0x06014 /* Display PLL A Control */
+#define DPLLBCNTR 0x06018 /* Display PLL B Control */
+#define FPA0 0x06040 /* DPLL A Divisor 0 */
+#define FPA1 0x06044 /* DPLL A Divisor 1 */
+#define FPB0 0x06048 /* DPLL B Divisor 0 */
+#define FPB1 0x0604C /* DPLL B Divisor 1 */
+
+#define DREFCLK 0x0
+#define TVCLKINBC 0x4000
+#define CLOCK_2X 0x40000000
+
+#define P2D_CG_DIS 0x06200 /* Clock Gating Disable */
+#define P3D_CG_DIS 0x06204 /* Clock Gating Disable */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Palette Register Definitions (0A000h - 0AFFFh)
+ *---------------------------------------------------------------------------*/
+#define DPALETTE_A 0x0A000 /* Display Pipe A Palette */
+#define DPALETTE_B 0x0A800 /* Display Pipe B Palette */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline / Port Register Definitions (60000h - 6FFFFh)
+ *---------------------------------------------------------------------------*/
+#define DP_OFFSET 0x60000 /* register group offset */
+#define PIPEA_TIMINGS 0x60000
+#define HTOTAL_A 0x60000 /* Pipe A Horizontal Total Register */
+#define ACTIVE_DISPLAY 0x7FF /* bit [ 10:0 ] */
+#define HBLANK_A 0x60004 /* Pipe A Horizontal Blank Register */
+#define HSYNC_A 0x60008 /* Pipe A Horizontal Sync Register */
+#define VTOTAL_A 0x6000C /* Pipe A Vertical Total Register */
+#define VBLANK_A 0x60010 /* Pipe A Vertical Blank Register */
+#define VSYNC_A 0x60014 /* Pipe A Vertical Sync Register */
+#define PIPEASRC 0x6001C /* Pipe A Source Image Size Register */
+#define BCLRPAT_A 0x60020 /* Pipe A Border Color Pattern Register */
+#define CRCCTRLREDA 0x60050 /* Pipe A CRC Red Control Register */
+#define CRCCTRLGREENA 0x60054 /* Pipe A CRC Green Control Register */
+#define CRCCTRLBLUEA 0x60058 /* Pipe A CRC Blue Control Register */
+#define CRCCTRLRESA 0x6005C /* Pipe A CRC Alpha Control Register */
+
+#define PIPEB_TIMINGS 0x61000
+#define HTOTAL_B 0x61000 /* Pipe B Horizontal Total Register */
+#define HBLANK_B 0x61004 /* Pipe B Horizontal Blank Register */
+#define HSYNC_B 0x61008 /* Pipe B Horizontal Sync Register */
+#define VTOTAL_B 0x6100C /* Pipe B Vertical Total Register */
+#define VBLANK_B 0x61010 /* Pipe B Vertical Blank Register */
+#define VSYNC_B 0x61014 /* Pipe B Vertical Sync Register */
+#define PIPEBSRC 0x6101C /* Pipe B Source Image Size Register */
+#define BCLRPAT_B 0x61020 /* Pipe B Border Color Pattern Register */
+#define CRCCTRLREDB 0x61050 /* Pipe B CRC Red Control Register */
+#define CRCCTRLGREENB 0x61054 /* Pipe B CRC Green Control Register */
+#define CRCCTRLBLUEB 0x61058 /* Pipe B CRC Blue Control Register */
+#define CRCCTRLRESB 0x6105C /* Pipe B CRC Alpha Control Register */
+
+#define PORT_HPLUG_EN 0x61110 /* Port Hot Plug Enable */
+#define PORT_HPLUG_STAT 0x61114 /* Port Hot Plug Status */
+#define SDVOBCNTR 0x61140 /* Digital Display Port B Control */
+#define SDVOCCNTR 0x61160 /* Digital Display Port B Control */
+#define LVDSCNTR 0x61180 /* Digital Display Port Control */
+
+/* Panel Power Sequencing */
+#define LVDS_PNL_PWR_STS 0x61200 /* LVDS Panel Power Status Register */
+#define LVDS_PNL_PWR_CTL 0x61204 /* LVDS Panel Power Control Register */
+#define PP_ON_DELAYS 0x61208 /* Panel Power On Sequencing Delays */
+#define PP_OFF_DELAYS 0x6120C /* Panel Power Off Sequencing Delays */
+#define PP_DIVISOR 0x61210 /* Panel Power Cycle Delay and Reference */
+
+/* Panel Fitting */
+#define PFIT_CONTROL 0x61230 /* Panel Fitting Control */
+#define PFIT_PGM_RATIOS 0x61234 /* Programmed Panel Fitting Ratios */
+#define PFIT_AUTO_RATIOS 0x61238 /* Programmed Panel Fitting Ratios */
+#define PFIT_INIT_PHASE 0x6123C /* Programmed Panel Fitting Ratios */
+
+/* Backlight control */
+#define BLC_PWM_CTL 0x61254 /* Backlight PWM Control */
+#define BLM_HIST_CTL 0x61260 /* Image BLM Histogram Control */
+
+#define PORT_EN BIT31
+#define PORT_PIPE_SEL BIT30
+#define PORT_PIPE_SEL_POS 30
+#define PORT_PIPE_A 0 /* 0 = Pipe A */
+#define PORT_PIPE_B BIT30 /* 1 = Pipe B */
+#define STALL_MASK BIT29 + BIT28
+#define STALL_ENABLE BIT28
+#define SYNC_MASK BIT15 + BIT11 + BIT10 + BIT4 + BIT3
+#define SYNC_POLARITY BIT15 /* 1 = Use VGA register */
+#define VSYNC_OUTPUT BIT11
+#define HSYNC_OUTPUT BIT10
+#define VSYNC_POLARITY BIT4
+#define HSYNC_POLARITY BIT3
+#define FP_DATA_ORDER BIT14
+#define SUBDATA_ORDER BIT6
+#define BORDER_EN BIT7
+#define DISPLAY_EN BIT2
+#define INTERLACED_BIT 0x00100000
+#define RGBA_BITS 0x00030000
+
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline A Register ( 70000h - 70024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEA_SCANLINE_COUNT 0x70000 /* Pipe A Scan Line Count (RO) */
+#define PIPEA_SCANLINE_COMPARE 0x70004 /* Pipe A SLC Range Compare (RO) */
+#define PIPEA_CONF 0x70008 /* Pipe A Configuration */
+#define PIPE_STATUS_OFFSET 0x1C
+#define PIPEA_STAT 0x70024 /* Pipe A Display Status */
+#define PIPEA_DISP_ARB_CTRL 0x70030 /* Display Arbitration Control */
+#define FW_BLC_AB 0x70034
+#define FW_BLC_C 0x70038
+#define PIPEA_FRAME_HIGH 0x70040 /* Pipe A Frame Count High */
+#define PIPEA_FRAME_PIXEL 0x70044 /* Pipe A Frame Cnt Low & pixel count */
+
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+
+
+/* following bit flag defs can be re-used for Pipe-B */
+#define PIPE_ENABLE BIT31
+#define PIPE_LOCK BIT25
+#define GAMMA_MODE BIT24
+#define HOT_PLUG_EN BIT26
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical sync interrupts.
+ */
+#define VSYNC_STS_EN BIT25
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical blank interrupts.
+ */
+#define VBLANK_STS_EN BIT17
+#define HOT_PLUG_STS BIT10
+#define VSYNC_STS BIT9
+#define VBLANK_STS BIT1
+/* The following are "sticky" status bits in the PIPE{A|B}_STAT register. They
+ * are cleared by writing a 1 to them. Theres is code that reads a
+ * PIPE{A|B}_STAT register into a variable, then modifies the variable, and
+ * writes it back to the register. These bits should be treated specially, so
+ * as not to inadvertantly clear the status bits, so that other code looking
+ * for those bits to be set won't miss it.
+ */
+#define PIPESTAT_STS_BITS ((unsigned long) BIT31 | BIT13 | BIT12 | BIT11 | \
+ VSYNC_STS | BIT8 | BIT5 | BIT4 | VBLANK_STS | BIT0)
+
+/*-----------------------------------------------------------------------------
+ * Hardware Cursor Register Definitions (70080h - 7009Ch)
+ *---------------------------------------------------------------------------*/
+#define CUR_A_CNTR 0x70080 /*Cursor A Control */
+#define CUR_B_CNTR 0x700C0
+#define CUR_BASE_OFFSET 0x4
+#define CUR_POS_OFFSET 0x8
+#define CUR_PAL0_OFFSET 0x10
+#define CUR_PAL1_OFFSET 0x14
+#define CUR_PAL2_OFFSET 0x18
+#define CUR_PAL3_OFFSET 0x1C
+
+/* Define these for ease of reference */
+#define CURSOR_A_BASE CUR_A_CNTR + CUR_BASE_OFFSET
+#define CURSOR_A_POS CUR_A_CNTR + CUR_POS_OFFSET
+#define CURSOR_A_PAL0 CUR_A_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_A_PAL1 CUR_A_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_A_PAL2 CUR_A_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_A_PAL3 CUR_A_CNTR + CUR_PAL3_OFFSET
+#define CURSOR_B_BASE CUR_B_CNTR + CUR_BASE_OFFSET
+#define CURSOR_B_POS CUR_B_CNTR + CUR_POS_OFFSET
+#define CURSOR_B_PAL0 CUR_B_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_B_PAL1 CUR_B_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_B_PAL2 CUR_B_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_B_PAL3 CUR_B_CNTR + CUR_PAL3_OFFSET
+
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags 00h - 0Fh
+ *---------------------------------------------------------------------------*/
+#define DSP_CHICKENBITS 0x70400 /* Chicken Bit */
+#define SWFABASE 0x70410 /* Software flags A Base Addr */
+#define SWF00 0x70410
+#define SWF01 0x70414
+#define SWF02 0x70418
+#define SWF03 0x7041C
+#define SWF04 0x70420
+#define SWF05 0x70424
+#define SWF06 0x70428
+#define SWF07 0x7042C
+#define SWF08 0x70430
+#define SWF09 0x70434
+#define SWF0A 0x70438
+#define SWF0B 0x7043C
+#define SWF0C 0x70440
+#define SWF0D 0x70444
+#define SWF0E 0x70448
+#define SWF0F 0x7044C
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline B Register ( 71000h - 71024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEB_SCANLINE_COUNT 0x71000 /* Pipe B Disp Scan Line Count Reg */
+#define PIPEB_SCANLINE_COMPARE 0x71004 /* Pipe B Disp Scan Line Cnt Range Cmp */
+#define PIPEB_CONF 0x71008 /* Pipe B Pixel Pipeline Config Reg */
+#define PIPEB_STAT 0x71024 /* Display Status Select Register */
+#define PIPEB_FRAME_HIGH 0x71040 /* Pipe B Frame Count High */
+#define PIPEB_FRAME_PIXEL 0x71044 /* Pipe B Frame Cnt Low and pixel cnt */
+
+
+#define VBLANK_EVN_STS_EN BIT20
+#define VBLANK_ODD_STS_EN BIT21
+#define VBLANK_EVN_STS BIT4
+#define VBLANK_ODD_STS BIT5
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane B Register Definitions (71180h - 71188h)
+ *---------------------------------------------------------------------------*/
+#define DSPBFLIP 0x7117C /* Display B Async flip */
+#define DSPBCNTR 0x71180 /* Display Plane B */
+#define DSPBADDR 0x71184 /* Display B Start Address */
+#define DSPBSTRIDE 0x71188 /* Display B Stride */
+#define DSPBPOS 0x7118C /* Display B Sprite Offset */
+#define DSPBSIZE 0x71190 /* Display B Sprite Size */
+#define DSPBKEYVAL 0x71194 /* Sprite color key value */
+#define DSPBKEYMASK 0x71198 /* Sprite color key mask */
+
+
+
+/*-----------------------------------------------------------------------------
+ * Source Format Definition for DSPxCNTR
+ *---------------------------------------------------------------------------*/
+#define DSPxCNTR_ARGB_8888 0x1C000000
+#define DSPxCNTR_RGB_8888 0x18000000
+#define DSPxCNTR_RGB_565 0x14000000
+#define DSPxCNTR_RGB_555 0x10000000
+#define DSPxCNTR_RGB_8 0x08000000
+#define DSPxCNTR_SRC_FMT_MASK 0x3C000000 /*mask for above*/
+
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags 10h - 1Fh
+ *---------------------------------------------------------------------------*/
+#define SWFBBASE 0x71410 /* Software flags B Base Addr */
+#define SWF10 0x71410
+#define SWF11 0x71414
+#define SWF12 0x71418
+#define SWF13 0x7141C
+#define SWF14 0x71420
+#define SWF15 0x71424
+#define SWF16 0x71428
+#define SWF17 0x7142C
+#define SWF18 0x71430
+#define SWF19 0x71434
+#define SWF1A 0x71438
+#define SWF1B 0x7143C
+#define SWF1C 0x71440
+#define SWF1D 0x71444
+#define SWF1E 0x71448
+#define SWF1F 0x7144C
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane C Register Definitions (72180h - 72188h)
+ *---------------------------------------------------------------------------*/
+#define DSPCCNTR 0x72180 /* Display Plane C */
+#define DSPCADDR 0x72184 /* Display C Start Address */
+#define DSPCSTRIDE 0x72188 /* Display C Stride */
+#define DSPCPOS 0x7218C /* Display C Position */
+#define DSPCSIZE 0x72190 /* Display C Size */
+#define DSPCKEYMINVAL 0x72194 /* Sprite color key Min */
+#define DSPCKEYMASK 0x72198 /* Sprite color key mask */
+#define DSPCKEYMAXVAL 0x721A0 /* Display C Sprint color key Max */
+
+#define DCLRC0 0x721D0 /* Display C Color Correction 0 */
+#define DCLRC1 0x721D4 /* Display C Color Correction 1 */
+#define DPYC_GAMC5 0x721E0 /* Display C Gamma Correction 5 */
+#define DPYC_GAMC4 0x721E4 /* Display C Gamma Correction 4 */
+#define DPYC_GAMC3 0x721E8 /* Display C Gamma Correction 3 */
+#define DPYC_GAMC2 0x721EC /* Display C Gamma Correction 2 */
+#define DPYC_GAMC1 0x721F0 /* Display C Gamma Correction 1 */
+#define DPYC_GAMC0 0x721F4 /* Display C Gamma Correction 0 */
+
+#define PLANE_ENABLE BIT31
+#define GAMMA_ENABLE BIT30
+#define BPP_MASK BIT29 + BIT28 + BIT27 + BIT26
+#define BPP_POS 26
+#define STEREO_ENABLE BIT25
+#define PIPE_SEL BIT24
+#define PIPE_SEL_POS 24
+#define PIXEL_MULTIPLY BIT21 + BIT20
+#define STEREO_POLARITY BIT18
+
+/* Common offsets for all Display Pipeline registers */
+#define DSP_START_OFFSET 0x04 /* Offset from the control reg */
+#define DSP_STRIDE_OFFSET 0x08 /* Offset from the control reg */
+#define DSP_SIZE_OFFSET 0x10 /* Offset from the control reg */
+
+
+
+/*-----------------------------------------------------------------------------
+ * VGA Display Plane Control Register Definitions (71400h)
+ *---------------------------------------------------------------------------*/
+#define VP00 0x71400
+#define VGACNTRL 0x71400 /* VGA Display Plane Control Register */
+#define VGA_DOUBLE BIT30
+#define VGA_PIPE BIT29
+#define VGA_CENTER_MASK BIT25 + BIT24
+#define VGA_CENTER_1 BIT25
+#define VGA_CENTER_0 BIT24
+#define VGA_PAL_READ BIT23
+#define VGA_PAL_MASK BIT22 + BIT21
+#define VGA_PALA_DISABLE BIT22
+#define VGA_PALB_DISABLE BIT21
+#define DAC_8_BIT BIT20
+#define VGA_8_DOT BIT18
+
+#define ADD_ID 0x71408 /* ADD Card ID Register*/
+
+#define OVADD 0x30000 /* Overlay Control */
+
+/*-----------------------------------------------------------------------------
+ * Software Flag Registers (71410h - 71428h)
+ *---------------------------------------------------------------------------*/
+
+/* Map old software flag names to their new Gen4 names */
+#define SF00 SWF10
+#define SF01 SWF11
+#define SF02 SWF12
+#define SF03 SWF13
+#define SF04 SWF14
+#define SF05 SWF15
+#define SF06 SWF16
+
+
+
+/*-----------------------------------------------------------------------------
+ * Scratch register to be used as additional parameter in SMI
+ *---------------------------------------------------------------------------*/
+#define SCRATCH_SWF6 0x71428
+
+/*-----------------------------------------------------------------------------
+ * Miscellaneous registers
+ ----------------------------------------------------------------------------*/
+#define HW_ST_PAGE_ADDR 0x02080
+
+
+/*-----------------------------------------------------------------------------
+ * GMBUS : I2C Bus Types
+ ----------------------------------------------------------------------------*/
+#define GMBUS_ANALOG_DDC 1
+#define GMBUS_INT_LVDS_DDC 2
+
+#define GMBUS_DVO_REG 3
+
+#define GMBUS_DVOB_DDC 4
+#define GMBUS_DVOC_DDC 5
+
+#endif /* _REGS_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h b/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
new file mode 100644
index 0000000..b882efc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
@@ -0,0 +1,217 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sgx.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * These are the defines specific to the SGX engine code.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _SGX_H
+#define _SGX_H
+
+
+/* ---------------------------------------------------------*/
+/* MACROS */
+/* ---------------------------------------------------------*/
+#ifndef BUG_ON
+#define BUG_ON(_cond)
+#endif
+
+#ifndef BUG
+#define BUG()
+#endif
+
+
+/* ---------------------------------------------------------*/
+/* DEFINES*/
+/* ---------------------------------------------------------*/
+/* PSB SGX Memory buffer types */
+/* FIXME! - rename 'DRM' prefix to 'SGX'
+ * if we start using this */
+#define DRM_BO_MEM_LOCAL 0
+#define DRM_BO_MEM_TT 1
+#define DRM_BO_MEM_VRAM 2
+#define DRM_BO_MEM_PRIV0 3
+#define DRM_BO_MEM_PRIV1 4
+#define DRM_BO_MEM_PRIV2 5
+#define DRM_BO_MEM_PRIV3 6
+#define DRM_BO_MEM_PRIV4 7
+#define DRM_BO_MEM_TYPES 8
+ /* For now. */
+#define DRM_BO_LOCK_UNLOCK_BM (1 << 0)
+#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1)
+
+/* GMM APERTURE FUNCTIONAL SEGMENTATION
+ * - BEWARE!!!! we are not using this kind
+ * of pre-allocated slots in IEGD arch
+ * so this should remain commented!!??
+ *
+#define PSB_VDC_OFFSET 0x00000000
+#define PSB_VDC_SIZE 0x000080000
+#define PSB_SGX_SIZE 0x8000
+#define PSB_SGX_OFFSET 0x00040000
+#define PSB_MMIO_RESOURCE 0
+#define PSB_GATT_RESOURCE 2
+#define PSB_GTT_RESOURCE 3
+#define PSB_GMCH_CTRL 0x52
+#define PSB_BSM 0x5C
+#define _PSB_GMCH_ENABLED 0x4
+#define PSB_PGETBL_CTL 0x2020
+#define _PSB_PGETBL_ENABLED 0x00000001
+#define PSB_SGX_2D_SLAVE_PORT 0x4000
+#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+#define PSB_NUM_VALIDATE_BUFFERS 512
+#define PSB_MEM_KERNEL_START 0x10000000
+#define PSB_MEM_PDS_START 0x20000000
+#define PSB_MEM_RASTGEOM_START 0x30000000
+#define PSB_MEM_MMU_START 0x40000000
+*/
+
+#define XPSB_LOCAL_SIZE 4096
+#define XPSB_SPROG_SIZE 1024
+#define XPSB_GEOM_SIZE 8192
+
+#define PSB_HW_COOKIE_SIZE 16
+#define PSB_HW_FEEDBACK_SIZE 8
+
+#define PAGE_SHIFT 12
+#define PSB_DPM_BUFFER_PAGES ((10*1024*1024) >> PAGE_SHIFT)
+#define PSB_DPM_TABLE_SIZE 0x40000
+#define PSB_PARAM_PAGE_SHIFT PAGE_SHIFT
+#define PSB_PARAM_PAGE_SIZE PAGE_SIZE
+#define PSB_MIN_NONGLOBAL_PAGES 1024
+#define PSB_PLM(_val, _base) \
+ (((_val) << (_base ## _SHIFT)) & (_base ## _MASK))
+
+/*
+ * Number of registers in a PDS attribute chunk.
+ */
+#define PSB_PDS_CHUNK_SIZE (32)
+#define PSB_PDS_CHUNK_SIZE_SHIFT (5)
+
+/*
+ * Number of registers reserved for output registers.
+ */
+#define PSB_USE_NUM_OUTPUT_REGISTERS (384)
+
+/*
+ * Total number of USE registers.
+ */
+
+#define PSB_USE_NUM_UNIFIED_REGISTERS (2048)
+/*
+ *
+ */
+
+#define PSB_USE_DEFAULT_TEMP_REG_COUNT (384)
+#define PSB_USE_DEFAULT_TEMP_GRAN (4)
+#define PSB_USE_DEFAULT_TEMP_REG_INIT (24)
+#define PSB_USE_DEFAULT_ATTRIB_REG_COUNT (2048 - 384 * 2) /* 1280 */
+
+
+/* ---------------------------------------------------------*/
+/* STRUCTURES */
+/* ---------------------------------------------------------*/
+struct drm_psb_xhw_arg {
+ unsigned long op;
+ int ret;
+ unsigned long irq_op;
+ unsigned long issue_irq;
+ unsigned long cookie[PSB_HW_COOKIE_SIZE];
+ union {
+ struct {
+ unsigned long w;
+ unsigned long h;
+ unsigned long size;
+ unsigned long clear_p_start;
+ unsigned long clear_num_pages;
+ } si;
+ struct {
+ unsigned long fire_flags;
+ unsigned long hw_context;
+ unsigned long offset;
+ unsigned long engine;
+ unsigned long flags;
+ unsigned long feedback[PSB_HW_FEEDBACK_SIZE];
+ } sb;
+ struct {
+ unsigned long pages;
+ unsigned long size;
+ } bi;
+ struct {
+ unsigned long bca;
+ unsigned long rca;
+ unsigned long flags;
+ } oom;
+ } arg;
+};
+struct pclosed_vopt
+{
+ int fix_hw_brn_20267;
+ int fix_hw_brn_20696;
+ int fix_hw_brn_20852;
+ int fix_hw_brn_21024;
+ int fix_hw_brn_21049;
+ int fix_hw_brn_21117;
+ int fix_hw_brn_21158;
+ int fix_hw_brn_21183;
+ int fix_hw_brn_21226;
+ int fix_hw_brn_21227;
+ int fix_hw_brn_21301;
+ int fix_hw_brn_21329;
+ int fix_hw_brn_21351;
+ int fix_hw_brn_21369;
+ int fix_hw_brn_21387;
+ int fix_hw_brn_21246;
+ int fix_hw_brn_21500;
+ int fix_hw_brn_21551;
+ int fix_hw_brn_21592;
+ int fix_hw_brn_21652;
+ int fix_hw_brn_21788;
+ int fix_hw_brn_21826;
+ int fix_hw_brn_21878;
+ int fix_hw_brn_21893;
+ int fix_hw_brn_21934;
+ int fix_hw_brn_21986;
+ int fix_hw_brn_22048;
+ int fix_hw_brn_22107;
+ int fix_hw_brn_22111;
+ int fix_hw_brn_22136;
+ int fix_hw_brn_22162;
+ int fix_hw_brn_22329;
+ int fix_hw_brn_22336;
+ int fix_hw_brn_22364;
+ int fix_hw_brn_22117;
+ int fix_hw_brn_22380;
+ int fix_hw_brn_22391;
+ int fix_hw_brn_22393;
+ int fix_hw_brn_22462;
+ int fix_hw_brn_22563;
+ int fix_hw_brn_22666;
+ int fix_hw_brn_23281;
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h b/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
new file mode 100644
index 0000000..68f4a80
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
@@ -0,0 +1,398 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is an inter-module header file for manipulating the 3D
+ * State variables.
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * This is referenced from Napa code. For Poulsbo, the HW spec may be
+ * different. Be ready for the new change.
+ */
+
+#ifndef _STATE3D_H
+#define _STATE3D_H
+
+#include <plb/appcontext.h>
+
+/* The dispatch table */
+typedef struct _state3d_dispatch_plb_t {
+ int lsi1_s2_needs_s3; /* Does LSI1 S2 also require S3? */
+ int lsi2_s3_830_845;
+} state3d_dispatch_plb_t;
+
+/* The array of buffer infos are used for these purposes */
+#define COLOR_BUFFER_INDEX 0
+#define DEPTH_BUFFER_INDEX 1
+#define AUX0_BUFFER_INDEX 2
+#define AUX1_BUFFER_INDEX 3
+#define INTRA_BUFFER_INDEX 4
+
+typedef struct _state3d_buffer_info_plb {
+ union {
+ struct {
+ unsigned long pitch :14;
+ unsigned long :7;
+ unsigned long tile_walk :1;
+ unsigned long tiled :1;
+ unsigned long fenced :1;
+ unsigned long buffer_id :4;
+ unsigned long aux_id :1;
+ unsigned long :3;
+ };
+ unsigned long dw1;
+ };
+ union {
+ unsigned long base;
+ unsigned long dw2;
+ };
+ unsigned long mod;
+} state3d_buffer_info_plb_t;
+
+typedef struct _state3d_dest_buffer_vars_plb {
+ union {
+ struct {
+ unsigned long vert_offset :1;
+ unsigned long vert_stride :1;
+ unsigned long depth_format :3;
+ unsigned long :1;
+ unsigned long depth_component :1;
+ unsigned long :1;
+ unsigned long color_format :4;
+ unsigned long write_select :3;
+ unsigned long :1;
+ unsigned long vert_bias :4;
+ unsigned long horiz_bias :4;
+ unsigned long dither_disable :1;
+ unsigned long gamma_blend_enable :1;
+ unsigned long dither_patten :2;
+ unsigned long :4;
+ };
+ unsigned long dw1;
+ };
+ unsigned long mod;
+} state3d_dest_buffer_vars_plb_t;
+
+typedef struct _state3d_vertex_buffer {
+ unsigned long addr;
+ unsigned long width;
+ unsigned long pitch;
+ unsigned long enable;
+ unsigned long mod;
+} state3d_vertex_buffer_t;
+
+#define VERTEX_BUFFER_ADDR_MODIFIED 0x1
+#define VERTEX_BUFFER_WIDTH_MODIFIED 0x2
+#define VERTEX_BUFFER_PITCH_MODIFIED 0x4
+#define VERTEX_BUFFER_ENABLE_MODIFIED 0x8
+
+typedef struct _state3d_texture_coord_set {
+ unsigned long format;
+ unsigned long enable;
+ unsigned long mod;
+} state3d_texture_coord_set_t;
+
+typedef struct _state3d_coord_set {
+ unsigned long transform_enable;
+ unsigned long normalized_coords;
+ unsigned long source;
+ unsigned long type;
+ unsigned long addr_v_control_mode;
+ unsigned long addr_u_control_mode;
+ unsigned long mod;
+} state3d_coord_set_t;
+
+typedef struct _state3d_texel_stream {
+ unsigned long modification_enable;
+ unsigned long modifier_unit_index;
+ unsigned long coord_select;
+ unsigned long map_select;
+ unsigned long mod;
+} state3d_texel_stream_t;
+
+#define MODIFICATION_ENABLE_MODIFIED 0x1
+#define MODIFIER_UNIT_INDEX_MODIFIED 0x2
+#define COORD_SELECT_MODIFIED 0x4
+#define MAP_SELECT_MODIFIED 0x8
+
+typedef struct _state3d_texel_modifier {
+ unsigned long texel_stream_index;
+ unsigned long bump_param_table_index;
+ unsigned long enable;
+ unsigned long mod;
+} state3d_texel_modifier_t;
+
+#define TEXEL_STREAM_INDEX_MODIFIED 0x1
+#define BUMP_PARAM_TABLE_INDEX_MODIFIED 0x2
+#define ENABLE_MODIFIED 0x4
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S3 Instruction.
+ */
+typedef struct _state3d_imm1_state3 {
+ unsigned long point_width;
+ unsigned long line_width;
+ unsigned long alpha_shade_mode;
+ unsigned long fog_shade_mode;
+ unsigned long specular_shade_mode;
+ unsigned long color_shade_mode;
+ unsigned long cull_mode;
+ unsigned long point_width_present;
+ unsigned long specular_color_present; /* And Fog Factor */
+ unsigned long diffuse_color_present;
+ unsigned long depth_offset_present;
+ unsigned long position_mask;
+ unsigned long specular_add_enable;
+ unsigned long fog_enable;
+ unsigned long local_depth_bias_enable;
+ unsigned long sprite_point_enable;
+ unsigned long antialiasing_enable;
+ unsigned long mod;
+} state3d_imm1_state3_t;
+
+#define POINT_WIDTH_MODIFIED 0x1
+#define LINE_WIDTH_MODIFIED 0x2
+#define ALPHA_SHADE_MODE_MODIFIED 0x4
+#define FOG_SHADE_MODE_MODIFIED 0x8
+#define SPECULAR_SHADE_MODE_MODIFIED 0x10
+#define COLOR_SHADE_MODE_MODIFIED 0x20
+#define CULL_MODE_MODIFIED 0x40
+#define POINT_WIDTH_PRESENT_MODIFIED 0x80
+#define SPECULAR_COLOR_PRESENT_MODIFIED 0x100
+#define DIFFUSE_COLOR_PRESENT_MODIFIED 0x200
+#define DEPTH_OFFSET_PRESENT_MODIFIED 0x400
+#define POSITION_MASK_MODIFIED 0x800
+#define SPECULAR_ADD_ENABLE_MODIFIED 0x1000
+#define FOG_ENABLE_MODIFIED 0x2000
+#define LOCAL_DEPTH_BIAS_ENABLE_MODIFIED 0x4000
+#define SPRITE_POINT_ENABLE_MODIFIED 0x8000
+#define ANTIALAISING_ENABLE_MODIFIED 0x10000
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S7 Instruction.
+ */
+typedef struct _state3d_imm1_state7 {
+ unsigned long global_depth_bias;
+ unsigned long stencil_reference_value;
+ unsigned long stencil_test_function;
+ unsigned long stencil_fail_op;
+ unsigned long stencil_pass_depth_fail_op;
+ unsigned long stencil_pass_depth_pass_op;
+ unsigned long stencil_buffer_write_enable;
+ unsigned long stencil_test_enable;
+ unsigned long color_dither_enable;
+ unsigned long logic_op_enable;
+ unsigned long mod;
+} state3d_imm1_state7_t;
+
+#define GLOBAL_DEPTH_BIAS_MODIFIED 0x1
+#define STENCIL_REFERENCE_VALUE_MODIFIED 0x2
+#define STENCIL_TEST_FUNCTION_MODIFIED 0x4
+#define STENCIL_FAIL_OP_MODIFIED 0x8
+#define STENCIL_PASS_DEPTH_FAIL_OP_MODIFIED 0x10
+#define STENCIL_PASS_DEPTH_PASS_OP_MODIFIED 0x20
+#define STENCIL_BUFFER_WRITE_ENABLE_MODIFIED 0x40
+#define STENCIL_TEST_ENABLE_MODIFIED 0x80
+#define COLOR_DITHER_ENABLE_MODIFIED 0x100
+#define LOGIC_OP_ENABLE_MODIFIED 0x200
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S8 Instruction.
+ */
+typedef struct _state3d_imm1_state8 {
+ unsigned long alpha_test_enable;
+ unsigned long alpha_test_function;
+ unsigned long alpha_reference_value;
+ unsigned long depth_test_enable;
+ unsigned long depth_test_function;
+ unsigned long color_buffer_blend_enable;
+ unsigned long color_blend_function;
+ unsigned long source_blend_factor;
+ unsigned long destination_blend_factor;
+ unsigned long depth_buffer_write_enable;
+ unsigned long color_buffer_write_enable;
+ unsigned long triangle_provoking_vertex_select;
+} state3d_imm1_state8_t;
+
+typedef struct _state3d_imm2_tms0 {
+ unsigned long tm_map_base_addr;
+ unsigned long tm_utilize_fence_regs;
+ unsigned long reverse_gamma_enable;
+} state3d_imm2_tms0_t;
+
+typedef struct _state3d_imm2_tms1 {
+ unsigned long tm_height;
+ unsigned long tm_width;
+ unsigned long tm_palette_select;
+ unsigned long tm_surface_format;
+ unsigned long tm_texel_format;
+ unsigned long tm_color_space_conversion_enable;
+ unsigned long tm_tiled_surface;
+ unsigned long tm_tile_walk;
+} state3d_imm2_tms1_t;
+
+typedef struct _state3d_imm2_tms2 {
+ unsigned long tm_dword_pitch;
+ unsigned long tm_cube_face_enables;
+ unsigned long tm_map_format;
+ unsigned long tm_vertical_line_stride;
+ unsigned long tm_vertical_line_stride_offset;
+ unsigned long tm_output_channel_selection;
+ unsigned long tm_base_mip_level;
+ unsigned long tm_lod_preclamp_enable;
+} state3d_imm2_tms2_t;
+
+typedef struct _state3d_imm2_tms3 {
+ unsigned long tm_mip_mode_filter;
+ unsigned long tm_mag_mode_filter;
+ unsigned long tm_min_mode_filter;
+ unsigned long tm_texture_lod_bias;
+ unsigned long tm_colorkey_enable;
+ unsigned long tm_chromakey_enable;
+ unsigned long tm_maximum_mip_level;
+ unsigned long tm_minimum_mip_level;
+ unsigned long tm_kill_pixel_enable;
+ unsigned long tm_keyed_texture_filter_mode;
+} state3d_imm2_tms3_t;
+
+typedef struct _state3d_imm2_tms4 {
+ unsigned long tm_default_color;
+} state3d_imm2_tms4_t;
+
+/*
+ * All pointers may be NULL. If so defaults should be assumed.
+ */
+typedef struct _state3d {
+ igd_surface_t color_buffer;
+ igd_surface_t depth_buffer;
+ state3d_vertex_buffer_t vertex_buffer[2];
+ state3d_texture_coord_set_t texture_coord_set[8];
+ unsigned long texture_coord_count;
+ state3d_imm1_state3_t imm1_s3;
+ state3d_coord_set_t coord_set[4];
+ state3d_texel_modifier_t texel_modifier[2];
+ state3d_texel_stream_t texel_stream[4];
+ state3d_imm1_state7_t imm1_s7;
+ state3d_imm1_state8_t imm1_s8;
+ state3d_imm2_tms0_t imm2_tms0[4];
+ state3d_imm2_tms1_t imm2_tms1[4];
+ state3d_imm2_tms2_t imm2_tms2[4];
+ state3d_imm2_tms3_t imm2_tms3[4];
+ state3d_imm2_tms4_t imm2_tms4[4];
+ state3d_buffer_info_plb_t buffer_info[5];
+ state3d_dest_buffer_vars_plb_t buffer_vars;
+ unsigned long mod;
+ state3d_dispatch_plb_t *dispatch;
+} state3d_t, state3d_plb_t;
+
+#define IMM1_MODIFIED 0x1ff
+#define IMM1_S0_MODIFIED 0x1
+#define IMM1_S1_MODIFIED 0x2
+#define IMM1_S2_MODIFIED 0x4
+#define IMM1_S3_MODIFIED 0x8
+#define IMM1_S4_MODIFIED 0x10
+#define IMM1_S5_MODIFIED 0x20
+#define IMM1_S6_MODIFIED 0x40
+#define IMM1_S7_MODIFIED 0x80
+#define IMM1_S8_MODIFIED 0x100
+#define IMM2_MODIFIED 0xf0000
+#define IMM2_TM0_MODIFIED 0x10000
+#define IMM2_TM1_MODIFIED 0x20000
+#define IMM2_TM2_MODIFIED 0x40000
+#define IMM2_TM3_MODIFIED 0x80000
+
+#define LOAD_S0 0x1
+#define LOAD_S1 0x2
+#define LOAD_S2 0x4
+#define LOAD_S3 0x8
+#define LOAD_S4 0x10
+#define LOAD_S5 0x20
+#define LOAD_S6 0x40
+#define LOAD_S7 0x80
+#define LOAD_S8 0x100
+#define LOAD_TM 0xf0000
+#define LOAD_TM0 0x10000
+#define LOAD_TM1 0x20000
+#define LOAD_TM2 0x40000
+#define LOAD_TM3 0x80000
+
+#define STATE3D_SET_ALPHA_TEST_ENABLE(s, v) \
+ s->imm1_s8.alpha_test_enable = (v & 1); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_ALPHA_TEST_FUNCTION(s, v) \
+ s->imm1_s8.alpha_test_function = (v & 7); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_ALPHA_REFERENCE_VALUE(s, v) \
+ s->imm1_s8.alpha_reference_value = (v & 0xf); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_TEST_ENABLE(s, v) \
+ s->imm1_s8.depth_test_enable = (v & 1); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_TEST_FUNCTION(s, v) \
+ s->imm1_s8.depth_test_function = (v & 7); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BUFFER_BLEND_ENABLE(s, v) \
+ s->imm1_s8.color_buffer_blend_enable = (v & 1); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BLEND_FUNCTION(s, v) \
+ s->imm1_s8.color_blend_function = (v & 7); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_SOURCE_BLEND_FACTOR(s, v) \
+ s->imm1_s8.source_blend_factor = (v & 0xf); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DESTINATION_BLEND_FACTOR(s, v) \
+ s->imm1_s8.destination_blend_factor = (v & 0xf); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_BUFFER_WRITE_ENABLE(s, v) \
+ s->imm1_s8.depth_buffer_write_enable = (v & 1); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BUFFER_WRITE_ENABLE(s, v) \
+ s->imm1_s8.color_buffer_write_enable = (v & 1); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_TRIANGLE_PROVOKING_VERTEX_SELECT(s, v) \
+ s->imm1_s8.triangle_provoking_vertex_select = (v & 3); \
+ s->mod |= IMM1_S8_MODIFIED;
+
+
+#define STATE3D(ac) ((state3d_t *)((appcontext_plb_t *)ac)->state3d)
+
+int state3d_update_plb(igd_command_t **in, appcontext_t *appcontext);
+int state3d_update_size(appcontext_t *appcontext);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h b/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
new file mode 100644
index 0000000..37327bc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
@@ -0,0 +1,1299 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is an inter-module header file for manipulating the 3D
+ * State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE3D_PLB_H
+#define _STATE3D_PLB_H
+
+#include <plb/appcontext.h>
+
+typedef struct _state3d_anti_aliasing_plb {
+ union {
+ struct {
+ unsigned int :6;
+ unsigned int line_aa_region_width :2;
+ unsigned int line_aa_region_width_mod_en :1;
+ unsigned int :5;
+ unsigned int line_end_cap_aa_region_width :2;
+ unsigned int line_end_cap_aa_region_width_mod_en :1;
+ unsigned int :15;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+
+} state3d_anti_aliasing_plb_t;
+
+#define STATE3D_ANTI_ALIASING_UPDATED_PLB 1
+#define STATE3D_ANTI_ALIASING_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_backface_stencil_ops_plb {
+ union {
+ struct {
+ unsigned int double_sided_en :1;
+ unsigned int double_sided_en_mod_en :1;
+ unsigned int pass_depth_pass_op :3;
+ unsigned int pass_depth_fail_op :3;
+ unsigned int fail_op :3;
+ unsigned int test_function :3;
+ unsigned int multiple_mod_en :1;
+ unsigned int ref_val :8;
+ unsigned int ref_val_mod_en :1;
+ unsigned int :8;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_backface_stencil_ops_plb_t;
+#define STATE3D_BACKFACE_STENCIL_OPS_UPDATED_PLB 1
+#define STATE3D_BACKFACE_STENCIL_OPS_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_backface_stencil_masks_plb {
+ union {
+ struct {
+ unsigned int write_mask :8;
+ unsigned int test_mask :8;
+ unsigned int write_mask_mod_en :1;
+ unsigned int test_mask_mod_en :1;
+ unsigned int :14;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_backface_stencil_masks_plb_t;
+#define STATE3D_BACKFACE_STENCIL_MASK_UPDATED_PLB 1
+#define STATE3D_BACKFACE_STENCIL_MASK_DWORD_COUNT_PLB 1
+
+/* FIXME: Details are ignored in this struct */
+typedef struct _state3d_bin_control_plb {
+ unsigned int dw0;
+ unsigned int dw1;
+ unsigned int dw2;
+ unsigned int dw3;
+ unsigned int dw4;
+ unsigned int dw5;
+ unsigned int updated;
+} state3d_bin_control_plb_t;
+#define STATE3D_BIN_CONTROL_UPDATED_PLB 1
+#define STATE3D_BIN_CONTROL_DWORD_COUNT_PLB 6
+
+typedef struct _state3d_buffer_info_plb {
+ unsigned int dw0;
+ union {
+ struct {
+ unsigned int :2;
+ unsigned int buffer_pitch :12;
+ unsigned int :7;
+ unsigned int tile_walk :1;
+ unsigned int tiled_surface :1;
+ unsigned int util_fence_regs :1;
+ unsigned int buffer_id :4;
+ unsigned int aux_buffer_id :1;
+ unsigned int :3;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int :2;
+ unsigned int buffer_base_addr :26;
+ };
+ unsigned int dw2;
+ };
+ unsigned int updated;
+} state3d_buffer_info_plb_t;
+#define STATE3D_BUFFER_INFO_UPDATED_PLB 1
+#define STATE3D_BUFFER_INFO_DWORD_COUNT_PLB 3
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_BACK 0x03
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_AUX 0x04
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_MC_INTRA_CORR 0x05
+#define STATE3D_BUFFER_INFO_BUFFERID_DEPTH 0x07
+
+typedef struct _state3d_chroma_key_plb {
+ union {
+ struct {
+ unsigned int :30;
+ unsigned int table_index :2;
+ };
+ unsigned int dw1;
+ };
+ union {
+ unsigned int lo_val;
+ unsigned int dw2;
+ };
+ union {
+ unsigned int hi_val;
+ unsigned int dw3;
+ };
+ unsigned int updated;
+} state3d_chroma_key_plb_t;
+#define STATE3D_CHROMA_KEY_UPDATED_PLB 1
+#define STATE3D_CHROMA_KEY_DWORD_COUNT_PLB 4
+
+typedef struct _state3d_clear_parameters_plb {
+ union {
+ struct {
+ unsigned int stencil_write_en :1;
+ unsigned int depth_buffer_write_en :1;
+ unsigned int color_buffer_write_en :1;
+ unsigned int :13;
+ unsigned int clear_primitive_type :1;
+ unsigned int :15;
+ };
+ unsigned int dw1;
+ };
+ union {
+ unsigned int clear_color_buffer_val;
+ unsigned int dw2;
+ };
+ union {
+ unsigned int clear_depth_buffer_val;
+ unsigned int dw3;
+ };
+ union {
+ unsigned int clear_color;
+ unsigned int dw4;
+ };
+ union {
+ unsigned int clear_depth;
+ unsigned int dw5;
+ };
+ union {
+ struct {
+ unsigned int clear_stencil :8;
+ unsigned int :24;
+ };
+ unsigned int dw6;
+ };
+ unsigned int updated;
+} state3d_clear_parameters_plb_t;
+#define STATE3D_CLEAR_PARAMETERS_UPDATED_PLB 1
+#define STATE3D_CLEAR_PARAMETERS_DWORD_COUNT_PLB 7
+
+typedef struct _state3d_constant_blend_color_plb {
+ union {
+ unsigned int color;
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_constant_blend_color_plb_t;
+#define STATE3D_CONSTANT_BLEND_COLOR_UPDATED_PLB 1
+#define STATE3D_CONSTANT_BLEND_COLOR_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_coord_set_bindings_plb {
+ union {
+ struct {
+ unsigned int internal_tc_set_0_src :3;
+ unsigned int internal_tc_set_1_src :3;
+ unsigned int internal_tc_set_2_src :3;
+ unsigned int internal_tc_set_3_src :3;
+ unsigned int internal_tc_set_4_src :3;
+ unsigned int internal_tc_set_5_src :3;
+ unsigned int internal_tc_set_6_src :3;
+ unsigned int internal_tc_set_7_src :3;
+ unsigned int :8;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_coord_set_bindings_plb_t;
+#define STATE3D_COORD_SET_BINDINGS_UPDATED_PLB 1
+#define STATE3D_COORD_SET_BINDINGS_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_default_diffuse_plb {
+ union {
+ unsigned int color;
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_default_diffuse_plb_t;
+#define STATE3D_DEFAULT_DIFFUSE_UPDATED_PLB 1
+#define STATE3D_DEFAULT_DIFFUSE_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_default_specular_plb {
+ union {
+ unsigned int color;
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_default_specular_plb_t;
+#define STATE3D_DEFAULT_SPECULAR_UPDATED_PLB 1
+#define STATE3D_DEFAULT_SPECULAR_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_default_z_plb {
+ union {
+ unsigned int depth;
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_default_z_plb_t;
+#define STATE3D_DEFAULT_Z_UPDATED_PLB 1
+#define STATE3D_DEFAULT_Z_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_depth_offset_scale_plb {
+ union {
+ unsigned int global_val;
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_depth_offset_scale_plb_t;
+#define STATE3D_DEPTH_OFFSET_SCALE_UPDATED_PLB 1
+#define STATE3D_DEPTH_OFFSET_SCALE_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_depth_subrectangle_enable_plb {
+ union {
+ struct {
+ unsigned int enable :1; /* B-spec says this is difeatured, MUST BE DISABLE */
+ unsigned int mod_en :1;
+ unsigned int :30;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_depth_subrectangle_enable_plb_t;
+#define STATE3D_DEPTH_SUBRECTANGLE_ENABLE_UPDATED_PLB 1
+#define STATE3D_DEPTH_SUBRECTANGLE_ENABLE_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_dest_buffer_variables_plb {
+ union {
+ struct {
+ unsigned int vert_line_stride_offset :1;
+ unsigned int vert_line_stride :1;
+ unsigned int depth_buffer_format :2;
+ unsigned int :4;
+ unsigned int color_buffer_format :4;
+ unsigned int write_select_422_channel :3;
+ unsigned int :1;
+ unsigned int dest_origin_vert_bias :4;
+ unsigned int dest_origin_horiz_bias :4;
+ unsigned int dither_enhance_dis :1;
+ unsigned int linear_gamma_blend_en :1;
+ unsigned int dither_pattern_select :2;
+ unsigned int lod_preclamp_en :1;
+ unsigned int early_depth_test_en :1;
+ unsigned int texture_default_color_mode :1;
+ unsigned int :1;
+ };
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_dest_buffer_variables_plb_t;
+#define STATE3D_DEST_BUFFER_VARIABLES_UPDATED_PLB 1
+#define STATE3D_DEST_BUFFER_VARIABLES_DWORD_COUNT_PLB 2
+
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_8BIT 0
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_X1R5G6B5 1
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_R5G6B5 2
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A8R8G8B8 3
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPY 4
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_NORMAL 5
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPUV 6
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPUVY 7
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A4R4G4B4 8
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A1R5G5B5 9
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A2R10G10B10 0xA
+
+typedef struct _state3d_drawing_rectangle_plb {
+ union {
+ struct {
+ unsigned int :24;
+ unsigned int y_dither_offset :2;
+ unsigned int x_dither_offset :2;
+ unsigned int :2;
+ unsigned int depth_buffer_coord_offset_dis :1;
+ unsigned int fast_scissor_clip_dis :1;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int clip_draw_rect_x_min :16;
+ unsigned int clip_draw_rect_y_min :16;
+ };
+ unsigned int dw2;
+ };
+ union {
+ struct {
+ unsigned int clip_draw_rect_x_max :16;
+ unsigned int clip_draw_rect_y_max :16;
+ };
+ unsigned int dw3;
+ };
+ union {
+ struct {
+ unsigned int draw_rect_origin_x :16;
+ unsigned int draw_rect_origin_y :16;
+ };
+ unsigned int dw4;
+ };
+ unsigned int updated;
+} state3d_drawing_rectangle_plb_t;
+#define STATE3D_DRAWING_RECTANGLE_UPDATED_PLB 1
+#define STATE3D_DRAWING_RECTANGLE_DWORD_COUNT_PLB 5
+
+typedef struct _state3d_filter_coefficients_4x4_plb {
+ /* FIXME: This might be an over simplified abstraction
+ * and may subject to change to meet its semantic later */
+ unsigned int filter1[32];
+ unsigned int filter2[32];
+ unsigned int updated;
+} state3d_filter_coefficients_4x4_plb_t;
+#define STATE3D_FILTER_COEFFICIENT_4X4_UPDATED_PLB 1
+#define STATE3D_FILTER_COEFFICIENT_4X4_DWORD_COUNT_PLB 65
+
+typedef struct _state3d_filter_coefficients_6x5_plb {
+ union {
+ struct {
+ unsigned int k1 :16;
+ unsigned int k2 :16;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int k3 :16;
+ unsigned int k4 :16;
+ };
+ unsigned int dw2;
+ };
+ union {
+ struct {
+ unsigned int k5 :16;
+ unsigned int k6 :16;
+ };
+ unsigned int dw3;
+ };
+ unsigned int updated;
+} state3d_filter_coefficients_6x5_plb_t;
+#define STATE3D_FILTER_COEFFICIENT_6X5_UPDATED_PLB 1
+#define STATE3D_FILTER_COEFFICIENT_6X5_DWORD_COUNT_PLB 4
+
+typedef struct _state3d_fog_color_plb {
+ union {
+ struct {
+ unsigned int blue :8;
+ unsigned int green :8;
+ unsigned int red :8;
+ unsigned int :8;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_fog_color_plb_t;
+#define STATE3D_FOG_COLOR_UPDATED_PLB 1
+#define STATE3D_FOG_COLOR_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_fog_mode_plb {
+ union {
+ struct {
+ unsigned int :4;
+ unsigned int linear_fog_c1_const:16;
+ unsigned int :3;
+ unsigned int fog_density_mod_en: 1;
+ unsigned int linear_fog_c1c2_const_mod_en :1;
+ unsigned int fog_source :1;
+ unsigned int :1;
+ unsigned int fog_source_mod_en :1;
+ unsigned int fog_func :2;
+ unsigned int :1;
+ unsigned int fog_func_mod_en :1;
+ };
+ unsigned int dw1;
+ };
+ union {
+ unsigned int linear_fog_c2_const;
+ unsigned int dw2;
+ };
+ union {
+ unsigned int fog_density;
+ unsigned int dw3;
+ };
+ unsigned int updated;
+} state3d_fog_mode_plb_t;
+
+#define STATE3D_FOG_MODE_UPDATED_PLB 1
+#define STATE3D_FOG_MODE_DWORD_COUNT_PLB 4
+
+typedef struct _state3d_independent_alpha_blend_plb {
+ union {
+ struct {
+ unsigned int dest_factor :4;
+ unsigned int :1;
+ unsigned int dest_factor_mod_en :1;
+ unsigned int src_factor :4;
+ unsigned int :1;
+ unsigned int src_factor_mod_en :1;
+ unsigned int :4;
+ unsigned int function :3;
+ unsigned int :2;
+ unsigned int function_mod_en :1;
+ unsigned int enable :1;
+ unsigned int enable_mod_en :1;
+ unsigned int :8;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_independent_alpha_blend_plb_t;
+#define STATE3D_INDEPENDENT_ALPHA_BLEND_UPDATED_PLB 1
+#define STATE3D_INDEPENDENT_ALPHA_BLEND_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_load_indirect_plb {
+ union {
+ struct {
+ unsigned int block_num :8;
+ unsigned int block_mask :6;
+ unsigned int mem_space_select :1;
+ unsigned int :17;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int static_buffer_valid :1;
+ unsigned int force_static_load :1;
+ unsigned int static_buffer_addr :30;
+ };
+ unsigned int dw_sis0;
+ };
+ union {
+ struct {
+ unsigned int static_buffer_length :9;
+ unsigned int :23;
+ };
+ unsigned int dw_sis1;
+ };
+ union {
+ struct {
+ unsigned int dynamic_buffer_valid :1;
+ unsigned int dynamic_buffer_reset :1;
+ unsigned int dynamic_buffer_addr :30;
+ };
+ unsigned int dw_dis0;
+ };
+ union {
+ struct {
+ unsigned int sampler_buffer_valid :1;
+ unsigned int force_sampler_load :1;
+ unsigned int sampler_buffer_addr :30;
+ };
+ unsigned int dw_ssb0;
+ };
+ union {
+ struct {
+ unsigned int sampler_buffer_length :9;
+ unsigned int :23;
+ };
+ unsigned int dw_ssb1;
+ };
+ union {
+ struct {
+ unsigned int map_buffer_valid :1;
+ unsigned int force_map_load :1;
+ unsigned int map_buffer_addr :30;
+ };
+ unsigned int dw_msb0;
+ };
+ union {
+ struct {
+ unsigned int map_buffer_length :9;
+ unsigned int :23;
+ };
+ unsigned int dw_msb1;
+ };
+ union {
+ struct {
+ unsigned int psp_buffer_valid :1;
+ unsigned int force_psp_load :1;
+ unsigned int psp_buffer_addr :30;
+ };
+ unsigned int dw_psp0;
+ };
+ union {
+ struct {
+ unsigned int psp_buffer_length :9;
+ unsigned int :23;
+ };
+ unsigned int dw_psp1;
+ };
+ union {
+ struct {
+ unsigned int psc_buffer_valid :1;
+ unsigned int force_psc_load :1;
+ unsigned int psc_buffer_addr :30;
+ };
+ unsigned int dw_psc0;
+ };
+ union {
+ struct {
+ unsigned int psc_buffer_length :9;
+ unsigned int :23;
+ };
+ unsigned int dw_psc1;
+ };
+ unsigned int updated;
+} state3d_load_indirect_plb_t;
+#define STATE3D_LOAD_INDIRECT_UPDATED_PLB 1
+#define STATE3D_LOAD_INDIRECT_DWORD_COUNT_PLB 12
+#define STATE3D_LOAD_INDIRECT_HEADER_DWORD_COUNT_PLB 1
+#define STATE3D_LOAD_INDIRECT_PSP_DWORD_COUNT_PLB 2
+
+typedef struct _state3d_load_state_immediate_1_plb {
+ union {
+ struct {
+ unsigned int state_num :4;
+ unsigned int load_dw_s0 :1;
+ unsigned int load_dw_s1 :1;
+ unsigned int load_dw_s2 :1;
+ unsigned int load_dw_s3 :1;
+ unsigned int load_dw_s4 :1;
+ unsigned int load_dw_s5 :1;
+ unsigned int load_dw_s6 :1;
+ unsigned int load_dw_s7 :1;
+ unsigned int :20;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int vtx_cache_invalid_dis :1;
+ unsigned int :1;
+ unsigned int vtx_buf_addr :26;
+ unsigned int :4;
+ };
+ unsigned int dw_s0;
+ };
+ union {
+ struct {
+ unsigned int :16;
+ unsigned int vtx_buf_pitch :6;
+ unsigned int :2;
+ unsigned int vtx_buf_width :6;
+ unsigned int :2;
+ };
+ unsigned int dw_s1;
+ };
+ union {
+ /*
+ struct {
+ unsigned int :4;
+ } tex_coord_set_fmt[8];
+ */
+ struct {
+ unsigned int tex_coord_set_0_fmt :4;
+ unsigned int tex_coord_set_1_fmt :4;
+ unsigned int tex_coord_set_2_fmt :4;
+ unsigned int tex_coord_set_3_fmt :4;
+ unsigned int tex_coord_set_4_fmt :4;
+ unsigned int tex_coord_set_5_fmt :4;
+ unsigned int tex_coord_set_6_fmt :4;
+ unsigned int tex_coord_set_7_fmt :4;
+ };
+ unsigned int dw_s2;
+ };
+ union {
+ /*
+ struct {
+ unsigned int pspec_crtn_dis :1;
+ unsigned int wrap_short_tcz :1;
+ unsigned int wrap_short_tcy :1;
+ unsigned int wrap_short_tcx :1;
+ } tex_coor_set[8];
+ */
+ struct {
+ unsigned int tex_coord_set_0_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_0_wrap_short_tcz :1;
+ unsigned int tex_coord_set_0_wrap_short_tcy :1;
+ unsigned int tex_coord_set_0_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_1_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_1_wrap_short_tcz :1;
+ unsigned int tex_coord_set_1_wrap_short_tcy :1;
+ unsigned int tex_coord_set_1_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_2_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_2_wrap_short_tcz :1;
+ unsigned int tex_coord_set_2_wrap_short_tcy :1;
+ unsigned int tex_coord_set_2_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_3_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_3_wrap_short_tcz :1;
+ unsigned int tex_coord_set_3_wrap_short_tcy :1;
+ unsigned int tex_coord_set_3_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_4_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_4_wrap_short_tcz :1;
+ unsigned int tex_coord_set_4_wrap_short_tcy :1;
+ unsigned int tex_coord_set_4_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_5_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_5_wrap_short_tcz :1;
+ unsigned int tex_coord_set_5_wrap_short_tcy :1;
+ unsigned int tex_coord_set_5_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_6_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_6_wrap_short_tcz :1;
+ unsigned int tex_coord_set_6_wrap_short_tcy :1;
+ unsigned int tex_coord_set_6_wrap_short_tcx :1;
+
+ unsigned int tex_coord_set_7_pspec_crtn_dis :1;
+ unsigned int tex_coord_set_7_wrap_short_tcz :1;
+ unsigned int tex_coord_set_7_wrap_short_tcy :1;
+ unsigned int tex_coord_set_7_wrap_short_tcx :1;
+
+ };
+ unsigned int dw_s3;
+ };
+ union {
+ struct {
+ unsigned int anti_alias_en :1;
+ unsigned int sprite_point_en :1;
+ unsigned int fog_param_present :1;
+ unsigned int local_depth_offset_en :1;
+ unsigned int force_specular_diffuse_color :1;
+ unsigned int force_default_diffuse_color :1;
+ unsigned int position_mask :3;
+ unsigned int local_depth_offset_present: 1;
+ unsigned int diffuse_color_present :1;
+ unsigned int specular_color_fog_factor_present :1;
+ unsigned int point_width_present :1;
+ unsigned int cull_mode :2;
+ unsigned int color_shade_mode :1;
+ unsigned int specular_shade_mode :1;
+ unsigned int fog_shade_mode :1;
+ unsigned int alpha_shade_mode :1;
+ unsigned int line_width :4;
+ unsigned int point_width :9;
+ };
+ unsigned int dw_s4;
+ };
+ union {
+ struct {
+ unsigned int logic_op_en :1;
+ unsigned int color_dither_en :1;
+ unsigned int stencil_test_en :1;
+ unsigned int stencil_buffer_write_en :1;
+ unsigned int stencil_pass_depth_pass_op :3;
+ unsigned int stencil_pass_depth_fail_op :3;
+ unsigned int stencil_fail_op :3;
+ unsigned int stencil_test_func :3;
+ unsigned int stencil_ref_val :8;
+ unsigned int fog_enable :1;
+ unsigned int global_depth_offset_en :1;
+ unsigned int last_pixel_en :1;
+ unsigned int force_default_point_width :1;
+ unsigned int color_buffer_component_write_dis :4;
+ };
+ unsigned int dw_s5;
+ };
+ union {
+ struct {
+ unsigned int triang_list_provoke_vtx_sel :2;
+ unsigned int color_buffer_write_en :1;
+ unsigned int depth_buffer_write_en :1;
+ unsigned int dest_blend_factor :4;
+ unsigned int src_blend_factor :4;
+ unsigned int color_blend_func :3;
+ unsigned int color_buffer_blend_en :1;
+ unsigned int depth_test_func :3;
+ unsigned int depth_test_en :1;
+ unsigned int alpha_ref_val :8;
+ unsigned int alpha_test_func :3;
+ unsigned int alpha_test_en :1;
+ };
+ unsigned int dw_s6;
+ };
+ union {
+ unsigned int global_depth_offset_const;
+ unsigned int dw_s7;
+ };
+ unsigned int updated;
+} state3d_load_state_immediate_1_plb_t;
+/* FIXME: Need to refine to smaller enable flags */
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_UPDATED_PLB 1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_HEADER_DWORD_COUNT_PLB 1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_STATES_ALL_DWORD_COUNT_PLB 8
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_ZERO 1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_ONE 2
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_SRC_ALPHA 5
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_SRC_ALPHA 6
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_DST_ALPHA 7
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_DST_ALPHA 8
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_CONST_ALPHA 0xe
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_CONST_ALPHA 0xf
+
+typedef struct _state3d_map_deinterlacer_parameters_plb {
+ union {
+ struct {
+ unsigned int da_en_y :1;
+ unsigned int da_en_uv :1;
+ unsigned int :30;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int edge_threshold_low_y :8;
+ unsigned int edge_threshold_high_y :8;
+ unsigned int edge_threshold_low_uv :8;
+ unsigned int edge_threshold_high_uv :8;
+ };
+ unsigned int dw2;
+ };
+ unsigned int updated;
+} state3d_map_deinterlacer_parameters_plb_t;
+#define STATE3D_MAP_DEINTERLACER_PARAMETERS_UPDATED_PLB 1
+#define STATE3D_MAP_DEINTERLACER_PARAMETERS_DWORD_COUNT_PLB 3
+
+typedef struct _state3d_map_palette_load_32_plb {
+ union {
+ struct {
+ unsigned int color_num :4;
+ unsigned int :12;
+ unsigned int :16;
+ };
+ unsigned int dw0;
+ };
+ unsigned int color[16];
+ unsigned int updated;
+} state3d_map_palette_load_32_plb_t;
+#define STATE3D_MAP_PALETTE_LOAD_32_UPDATED_PLB 1
+#define STATE3D_MAP_PALETTE_LOAD_32_DWORD_COUNT_PLB 17
+
+typedef struct _state3d_map_state_texmap_plb {
+ union {
+ struct {
+ unsigned int vert_stride_offset :1;
+ unsigned int vert_stride :1;
+ unsigned int base_addr :26;
+ unsigned int :3;
+ };
+ unsigned int tm_dw0;
+ };
+ union {
+ struct {
+ unsigned int tile_walk :1;
+ unsigned int tiled_surface :1;
+ unsigned int util_fence_regs :1;
+ unsigned int texel_format :4;
+ unsigned int surface_format :3;
+ unsigned int width :11;
+ unsigned int height :11;
+ };
+ unsigned int tm_dw1;
+ };
+ union {
+ struct {
+ unsigned int depth :8;
+ unsigned int :1;
+ unsigned int max_lod :6;
+ unsigned int cube_face_en :6;
+ unsigned int dword_pitch :11;
+ };
+ unsigned int tm_dw2;
+ };
+} state3d_map_state_texmap_plb_t;
+#define STATE3D_MAP_STATE_MAPSURF_8BIT_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_I8_PLB 0
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_L8_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_A4P4_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_P4A4_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_A8_PLB 4
+ #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_MONO8_PLB 5
+#define STATE3D_MAP_STATE_MAPSURF_16BIT_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_R5G6B5_PLB 0
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A1R5G5B5_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A4R4G4B4_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A8L8_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_V8U8_PLB 5
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_L6V5U5_PLB 6
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_I16_PLB 7
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_L16_PLB 8
+ #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A16_PLB 9
+#define STATE3D_MAP_STATE_MAPSURF_32BIT_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8R8G8B8_PLB 0
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8B8G8R8_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8R8G8B8_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8B8G8R8_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_Q8W8V8U8_PLB 4
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8X8V8U8_PLB 5
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_L8X8V8U8_PLB 6
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8L8V8U8_PLB 7
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2R10G10B10_PLB 8
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2B10G10R10_PLB 9
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2W10V10U10_PLB 0xA
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_G16R16_PLB 0xB
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_V16U16_PLB 0xC
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8I24_PLB 0xD
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8L24_PLB 0xE
+ #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8A24_PLB 0xF
+ #define STATE3D_MAP_STATE_MAPSURF_422_PLB 5
+ #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPY_PLB 0
+ #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_NORMAL_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPUV_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPUVY_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_PLB 6
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX1_PLB 0
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX2_3_PLB 1
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX4_5_PLB 2
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_FX1_PLB 3
+ #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX1_RGB_PLB 4
+#define STATE3D_MAP_STATE_MAPSURF_4BIT_INDEXED_PLB 7
+ #define STATE3D_MAP_STATE_MAPSURF_4BIT_INDEXED_MAPTEXEL_A8R8G8B8_PLB 7
+typedef struct _state3d_map_state_plb {
+ union {
+ struct {
+ unsigned int map_num :6;
+ unsigned int :9;
+ unsigned int retain :1;
+ unsigned int :16;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int map_mask :16;
+ unsigned int :16;
+ };
+ unsigned int dw1;
+ };
+ state3d_map_state_texmap_plb_t texmap[16]; /* Napa support 16 texture maps, B-spec-1a pg198 */
+ unsigned int updated;
+} state3d_map_state_plb_t;
+/* FIXME: Need to refine to smaller enable flags */
+#define STATE3D_MAP_STATE_UPDATED_PLB 1
+#define STATE3D_MAP_STATE_MAX_DWORD_COUNT_PLB 50
+#define STATE3D_MAP_STATE_HEADER_DWORD_COUNT_PLB 2
+#define STATE3D_MAP_STATE_SINGLE_TM_DWORD_COUNT_PLB 3
+
+typedef struct _state3d_modes_4_plb {
+ union {
+ struct {
+ unsigned int stencil_write_mask :8;
+ unsigned int stencil_test_mask :8;
+ unsigned int stencil_write_mask_mod_en :1;
+ unsigned int stencil_test_mask_mod_en :1;
+ unsigned int logic_op_func :4;
+ unsigned int :1;
+ unsigned int logic_op_func_mod_en :1;
+ unsigned int :8;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_modes_4_plb_t;
+#define STATE3D_MODES_4_UPDATED_PLB 1
+#define STATE3D_MODES_4_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_modes_5_plb {
+ union {
+ struct {
+ unsigned int :16;
+ unsigned int pipelined_tex_cache_op :1;
+ unsigned int tex_cache_dis :1;
+ unsigned int pipelined_render_cache_op :1;
+ unsigned int :13;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_modes_5_plb_t;
+
+#define STATE3D_MODES_5_UPDATED_PLB 1
+#define STATE3D_MODES_5_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_pixel_shader_const_elem_plb {
+ unsigned int const_x;
+ unsigned int const_y;
+ unsigned int const_z;
+ unsigned int const_w;
+} state3d_pixel_shader_const_elem_plb_t;
+
+typedef struct _state3d_pixel_shader_constants_plb {
+ union {
+ struct {
+ unsigned int const_num :8;
+ unsigned int :24;
+ };
+ unsigned int dw0;
+ };
+ union {
+ unsigned int reg_mask;
+ unsigned int dw1;
+ };
+ state3d_pixel_shader_const_elem_plb_t elem[32];
+ unsigned int updated;
+} state3d_pixel_shader_constants_plb_t;
+#define STATE3D_PIXEL_SHADER_CONSTANTS_UPDATED_PLB 1
+#define STATE3D_PIXEL_SHADER_CONSTANTS_HEADER_DWORD_COUNT_PLB 2
+#define STATE3D_PIXEL_SHADER_CONSTANTS_SINGLE_ELEM_DWORD_COUNT_PLB 4
+
+typedef struct _state3d_pixel_shader_program_ari_instr_plb {
+ union {
+ struct {
+ unsigned int :2;
+ unsigned int src0_reg_num :5;
+ unsigned int src0_reg_type :3;
+ unsigned int dest_channel_mask :4;
+ unsigned int dest_reg_num :4;
+ unsigned int :1;
+ unsigned int dest_reg_type :3;
+ unsigned int dest_saturate :1;
+ unsigned int :1;
+ unsigned int opcode :5;
+ unsigned int :3;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int src1_y_channel_select :3;
+ unsigned int src1_y_channel_negate :1;
+ unsigned int src1_x_channel_select :3;
+ unsigned int src1_x_channel_negate :1;
+ unsigned int src1_reg_num :5;
+ unsigned int src1_reg_type :3;
+ unsigned int src0_w_channel_select :3;
+ unsigned int src0_w_channel_negate :1;
+ unsigned int src0_z_channel_select :3;
+ unsigned int src0_z_channel_negate :1;
+ unsigned int src0_y_channel_select :3;
+ unsigned int src0_y_channel_negate :1;
+ unsigned int src0_x_channel_select :3;
+ unsigned int src0_x_channel_negate :1;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int src2_w_channel_select :3;
+ unsigned int src2_w_channel_negate :1;
+ unsigned int src2_z_channel_select :3;
+ unsigned int src2_z_channel_negate :1;
+ unsigned int src2_y_channel_select :3;
+ unsigned int src2_y_channel_negate :1;
+ unsigned int src2_x_channel_select :3;
+ unsigned int src2_x_channel_negate :1;
+ unsigned int src2_reg_num :5;
+ unsigned int src2_reg_type :3;
+ unsigned int src1_w_channel_select :3;
+ unsigned int src1_w_channel_negate :1;
+ unsigned int src1_z_channel_select :3;
+ unsigned int src1_z_channel_negate :1;
+ };
+ unsigned int dw2;
+ };
+
+ void * next_instr;
+ unsigned char ps_id;
+} state3d_pixel_shader_program_ari_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_tex_instr_plb {
+ union {
+ struct {
+ unsigned int samp_reg_num :4;
+ unsigned int :10;
+ unsigned int dest_reg_num :4;
+ unsigned int :1;
+ unsigned int dest_reg_type :3;
+ unsigned int :2;
+ unsigned int opcode :5;
+ unsigned int :3;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int :17;
+ unsigned int addr_reg_num :4;
+ unsigned int :3;
+ unsigned int addr_reg_type :3;
+ unsigned int :5;
+ };
+ unsigned int dw1;
+ };
+ unsigned int dw2;
+
+ void * next_instr;
+ unsigned char ps_id;
+} state3d_pixel_shader_program_tex_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_dcl_instr_plb {
+ union {
+ struct {
+ unsigned int :10;
+ unsigned int dcl_channel_mask :4;
+ unsigned int dcl_reg_num :4;
+ unsigned int :1;
+ unsigned int dcl_reg_type :2;
+ unsigned int :1;
+ unsigned int samp_type :2;
+ unsigned int opcode :5;
+ unsigned int :3;
+ };
+ unsigned int dw0;
+ };
+ unsigned int dw1;
+ unsigned int dw2;
+
+ void * next_instr;
+ unsigned char ps_id;
+} state3d_pixel_shader_program_dcl_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_instr_plb {
+ unsigned int idw0; //instruction's first dword
+ unsigned int idw1; //instruction's second dword
+ unsigned int idw2; //instruction's third dword
+} state3d_pixel_shader_program_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_plb {
+ union {
+ struct {
+ unsigned int instr_num :9;
+ unsigned int :6;
+ unsigned int retain :1;
+ unsigned int :16;
+ };
+ unsigned int dw0;
+ };
+ state3d_pixel_shader_program_instr_plb_t instr[123];
+ unsigned int updated;
+} state3d_pixel_shader_program_plb_t;
+
+/*
+#define STATE3D_PIXEL_SHADER_PROGRAM_ARI_INSTR_UPDATED_PLB 1
+#define STATE3D_PIXEL_SHADER_PROGRAM_TEX_INSTR_UPDATED_PLB 1
+#define STATE3D_PIXEL_SHADER_PROGRAM_DCL_INSTR_UPDATED_PLB 1
+*/
+#define STATE3D_PIXEL_SHADER_PROGRAM_HEADER_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_rasterization_rules_plb {
+ union {
+ struct {
+ unsigned int :3;
+ unsigned int tri_fan_provok_vtx_sel :2;
+ unsigned int tri_fan_provok_vtx_sel_mod_en :1;
+ unsigned int line_list_provok_vtx_sel :2;
+ unsigned int line_list_provok_vtx_sel_mod_en :1;
+ unsigned int texkill_3d4d :1;
+ unsigned int texkill_3d4d_mod_en :1;
+ unsigned int :1;
+ unsigned int snake_walk_dis :1;
+ unsigned int point_raster_rule :2;
+ unsigned int point_raster_rule_mod_en :1;
+ unsigned int zero_pixel_tri_filter_dis :1;
+ unsigned int zero_pixel_tri_filter_dis_mod_en :1;
+ unsigned int tri_2x2_filter_dis :1;
+ unsigned int tri_2x2_filter_dis_mod_en :1;
+ unsigned int :12;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_rasterization_rules_plb_t;
+#define STATE3D_RASTERIZATION_RULES_UPDATED_PLB 1
+#define STATE3D_RASTERIZATION_RULES_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_sampler_state_samp_plb {
+ union {
+ struct {
+ unsigned int shadow_func :3;
+ unsigned int max_anisotropy :1;
+ unsigned int shadow_en :1;
+ unsigned int tex_lod_bias :9;
+ unsigned int min_mode_filter :3;
+ unsigned int mag_mode_filter :3;
+ unsigned int mip_mode_filter :2;
+ unsigned int base_mip_level :5;
+ unsigned int chroma_index :2;
+ unsigned int color_space_conv_en :1;
+ unsigned int planar_to_packed_en :1;
+ unsigned int reverse_gamma_en :1;
+ };
+ unsigned int ts_dw0;
+ };
+ union {
+ struct {
+ unsigned int east_deinterlace_en:1;
+ unsigned int map_index:4;
+ unsigned int normalized_coord:1;
+ unsigned int tcz_addr_ctrl_mode:3;
+ unsigned int tcy_addr_ctrl_mode:3;
+ unsigned int tcx_addr_ctrl_mode:3;
+ unsigned int chroma_en:1;
+ unsigned int keyed_tex_filter_mode:1;
+ unsigned int kill_pixel_en:1;
+ unsigned int :6;
+ unsigned int min_lod:8;
+ };
+ unsigned int ts_dw1;
+ };
+ union {
+ unsigned int default_color;
+ unsigned int ts_dw2;
+ };
+} state3d_sampler_state_samp_plb_t;
+
+typedef struct _state3d_sampler_state_plb {
+ union {
+ struct {
+ unsigned int samp_num :6;
+ unsigned int :26;
+ };
+ unsigned int dw0;
+ };
+ union {
+ struct {
+ unsigned int samp_mask :16;
+ unsigned int :16;
+ };
+ unsigned int dw1;
+ };
+ state3d_sampler_state_samp_plb_t samp[16]; /* Napa support up to 16 sampler */
+ unsigned int updated;
+} state3d_sampler_state_plb_t;
+/* FIXME: Need to refine smaller enable flags */
+#define STATE3D_SAMPLER_STATE_UPDATED_PLB 1
+#define STATE3D_SAMPLER_STATE_MAX_DWORD_COUNT_PLB 50
+#define STATE3D_SAMPLER_STATE_HEADER_DWORD_COUNT_PLB 2
+#define STATE3D_SAMPLER_STATE_SINGLE_TS_DWORD_COUNT_PLB 3
+
+typedef struct _state3d_scissor_enable_plb {
+ union {
+ struct {
+ unsigned int enable :1;
+ unsigned int enable_mod_en :1;
+ unsigned int :30;
+ };
+ unsigned int dw0;
+ };
+ unsigned int updated;
+} state3d_scissor_enable_plb_t;
+#define STATE3D_SCISSOR_ENABLE_UPDATED_PLB 1
+#define STATE3D_SCISSOR_ENABLE_DWORD_COUNT_PLB 1
+
+typedef struct _state3d_scissor_rectangle_plb {
+ union {
+ struct {
+ unsigned int x_min :16;
+ unsigned int y_min :16;
+ };
+ unsigned int dw1;
+ };
+ union {
+ struct {
+ unsigned int x_max :16;
+ unsigned int y_max :16;
+ };
+ unsigned int dw2;
+ };
+ unsigned int updated;
+
+} state3d_scissor_rectangle_plb_t;
+#define STATE3D_SCISSOR_RECTANGLE_UPDATED_PLB 1
+#define STATE3D_SCISSOR_RECTANGLE_DWORD_COUNT_PLB 3
+
+typedef struct _state3d_span_stipple_plb {
+ union {
+ struct {
+ unsigned int pattern :16;
+ unsigned int enable :1;
+ unsigned int :15;
+ };
+ unsigned int dw1;
+ };
+ unsigned int updated;
+} state3d_span_stipple_plb_t;
+#define STATE3D_SPAN_STIPPLE_UPDATED_PLB 1
+#define STATE3D_SPAN_STIPPLE_DWORD_COUNT_PLB 2
+
+#define COLOR_BUFFER_INDEX 0
+#define DEPTH_BUFFER_INDEX 1
+#define AUX0_BUFFER_INDEX 2
+#define AUX1_BUFFER_INDEX 3
+#define INTRA_BUFFER_INDEX 4
+
+#define ZONE_INIT_CLEARPARAM_INDEX 0
+#define CLEAR_RECT_CLEARPARAM_INDEX 1
+
+typedef struct _state3d_plb {
+ igd_surface_t color_buffer;
+ igd_surface_t depth_buffer;
+ state3d_anti_aliasing_plb_t anti_alias;
+ state3d_backface_stencil_ops_plb_t bface_stencil_ops;
+ state3d_backface_stencil_masks_plb_t bface_stencil_masks;
+ state3d_bin_control_plb_t bin_control;
+/*
+ state3d_buffer_info_plb_t dest_buffer_info;
+ state3d_buffer_info_plb_t depth_buffer_info;
+*/
+ state3d_buffer_info_plb_t buffer_info[5];
+ state3d_chroma_key_plb_t chroma_key[4];
+ state3d_clear_parameters_plb_t clear_param[2];
+ state3d_constant_blend_color_plb_t const_blend_color;
+ state3d_coord_set_bindings_plb_t coord_set_bind;
+ state3d_default_diffuse_plb_t default_diffuse;
+ state3d_default_specular_plb_t default_specular;
+ state3d_default_z_plb_t default_z;
+ state3d_depth_offset_scale_plb_t depth_offset_scale;
+ state3d_depth_subrectangle_enable_plb_t depth_subrect_en;
+ state3d_dest_buffer_variables_plb_t dest_buf_vars;
+ state3d_drawing_rectangle_plb_t draw_rect;
+ state3d_filter_coefficients_4x4_plb_t filter_coef_4x4;
+ state3d_filter_coefficients_6x5_plb_t filter_coef_6x5;
+ state3d_fog_color_plb_t fog_color;
+ state3d_fog_mode_plb_t fog_mode;
+ state3d_independent_alpha_blend_plb_t indep_alpha_blend;
+ state3d_load_indirect_plb_t load_indirect;
+ state3d_load_state_immediate_1_plb_t lsi1;
+ state3d_map_deinterlacer_parameters_plb_t map_deinterlace_param;
+ state3d_map_palette_load_32_plb_t map_pal_load_32;
+ state3d_map_state_plb_t map_state;
+ state3d_modes_4_plb_t modes_4;
+ state3d_modes_5_plb_t modes_5;
+ state3d_pixel_shader_constants_plb_t pixel_shader_const;
+ state3d_pixel_shader_program_plb_t pixel_shader_program;
+/* state3d_pixel_shader_program_dcl_instr_plb_t pixel_shader_dcl;
+ state3d_pixel_shader_program_ari_instr_plb_t pixel_shader_ari;
+ state3d_pixel_shader_program_tex_instr_plb_t pixel_shader_tex;*/
+ state3d_rasterization_rules_plb_t raster_rules;
+ state3d_sampler_state_plb_t sampler_state;
+ state3d_scissor_enable_plb_t scissor_en;
+ state3d_scissor_rectangle_plb_t scissor_rect;
+ state3d_span_stipple_plb_t span_stipple;
+} state3d_plb_t;
+
+int state3d_update_plb(igd_command_t ** in, state3d_plb_t *state, int load_all);
+int state3d_update_size_plb(state3d_plb_t *state);
+
+#define STATE3D_PLB(ac) ((state3d_plb_t*)((appcontext_plb_t*)ac)->state3d)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/psb_regs.h b/drivers/gpu/drm/emgd/emgd/include/psb_regs.h
new file mode 100644
index 0000000..01edb09
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/psb_regs.h
@@ -0,0 +1,658 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: psb_regs.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the register definition file for the SGX and MSVDX cores.
+ * These registers were formerly part of the plb/regs.h. They are taken out
+ * because Atom E6xx shares the same core as PLB. This file is included in tnc/regs.h
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PSB_REGS_H_
+#define _PSB_REGS_H_
+
+extern unsigned long _sgx_base;
+/*-----------------------------------------------------------------------------
+ * SGX and MSVDX registers
+ ----------------------------------------------------------------------------*/
+#define SGX_BASE _sgx_base
+
+/* bits in PSB_EUR_CR_EVENT_STATUS */
+#define PSB_DPM_3D_MEM_FREE (1<<0)
+#define PSB_OUT_OF_MEM_MT (1<<1)
+#define PSB_OUT_OF_MEM_GBL (1<<2)
+#define PSB_REACHED_MEM_THRESH (1<<3)
+#define PSB_TA_TERMINATE (1<<12)
+#define PSB_TA_FINISHED (1<<13)
+#define PSB_PIXELBE_END_RENDER (1<<18)
+#define PSB_DPM_TA_MEM_FREE (1<<24)
+#define PSB_DPM_OUT_OF_MEM_ZLS (1<<25)
+#define PSB_TWOD_COMPLETE (1<<27)
+#define PSB_TA_DPM_FAULT (1<<28)
+
+/* PSB Registers */
+#define PSB_SGX_2D_CMD_SLAVE_PORT (SGX_BASE + 0x4000)
+
+/* 0x000-0x0ff */
+/* CORE CLOCK GATING register definitions */
+#define PSB_CR_CLKGATECTL (SGX_BASE + 0x0000)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED 0x0
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED 0x1
+#define _PSB_C_CLKGATECTL_CLKG_AUTO 0x2
+
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0)
+
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0)
+
+#define PSB_CR_CORE_ID (SGX_BASE + 0x0010)
+#define _PSB_CC_ID_ID_SHIFT (16)
+#define _PSB_CC_ID_ID_MASK (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT (0)
+#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION (SGX_BASE + 0x0014)
+#define _PSB_CC_REVISION_DESIGNER_SHIFT (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT (16)
+#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT (8)
+#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0)
+
+#define PSB_CR_SOFT_RESET (SGX_BASE + 0x0080)
+#define _PSB_CS_RESET_TSP_RESET (1 << 6)
+#define _PSB_CS_RESET_ISP_RESET (1 << 5)
+#define _PSB_CS_RESET_USE_RESET (1 << 4)
+#define _PSB_CS_RESET_TA_RESET (1 << 3)
+#define _PSB_CS_RESET_DPM_RESET (1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET (1 << 1)
+#define _PSB_CS_RESET_BIF_RESET (1 << 0)
+
+/* 0x100-0x200 */
+
+#define PSB_CR_EVENT_HOST_ENABLE2 (SGX_BASE + 0x0110)
+#define PSB_CR_EVENT_HOST_CLEAR2 (SGX_BASE + 0x0114)
+#define PSB_CR_EVENT_STATUS2 (SGX_BASE + 0x0118)
+#define PSB_TRIG_TA (1 << 7)
+#define PSB_TRIG_3D (1 << 6)
+#define PSB_TRIG_DL (1 << 5)
+#define PSB_BIF_REQ_FAULT (1 << 4)
+#define _PSB_CE_BIF_REQUESTER_FAULT (1 << 4)
+#define _PSB_CE_DPM_DHOST_FREE_LOAD (1 << 3)
+#define _PSB_CE_DPM_HOST_FREE_LOAD (1 << 2)
+#define _PSB_CE_DPM_3D_FREE_LOAD (1 << 1)
+#define _PSB_CE_DPM_TA_FREE_LOAD (1 << 0)
+
+#define PSB_EUR_CR_EVENT_STATUS (SGX_BASE + 0x012c)
+
+#define PSB_CR_EVENT_STATUS (SGX_BASE + 0x012C)
+
+#define PSB_EUR_CR_EVENT_HOST_ENABLE (SGX_BASE + 0x0130)
+
+#define PSB_CR_EVENT_HOST_CLEAR (SGX_BASE + 0x0134)
+#define _PSB_CE_MASTER_INTERRUPT (1 << 31)
+#define _PSB_CE_TIMER (1 << 29)
+#define _PSB_CE_TA_DPM_FAULT (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE (1 << 27)
+#define _PSB_CE_MADD_CACHE_INVALCOMPLETE (1 << 26)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24)
+#define _PSB_CE_ISP_END_TILE (1 << 23)
+#define _PSB_CE_DPM_INITEND (1 << 22)
+#define _PSB_CE_OTPM_LOADED (1 << 21)
+#define _PSB_CE_OTPM_INV (1 << 20)
+#define _PSB_CE_OTPM_FLUSHED (1 << 19)
+#define _PSB_CE_PIXELBE_END_RENDER (1 << 18)
+#define _PSB_CE_ISP_HALT (1 << 17)
+#define _PSB_CE_ISP_VISIBILITY_FAIL (1 << 16)
+#define _PSB_CE_BREAKPOINT (1 << 15)
+#define _PSB_CE_SW_EVENT (1 << 14)
+#define _PSB_CE_TA_FINISHED (1 << 13)
+#define _PSB_CE_TA_TERMINATE (1 << 12)
+#define _PSB_CE_TPC_CLEAR (1 << 11)
+#define _PSB_CE_TPC_FLUSH (1 << 10)
+#define _PSB_CE_DPM_CONTROL_CLEAR (1 << 9)
+#define _PSB_CE_DPM_CONTROL_LOAD (1 << 8)
+#define _PSB_CE_DPM_CONTROL_STORE (1 << 7)
+#define _PSB_CE_DPM_STATE_CLEAR (1 << 6)
+#define _PSB_CE_DPM_STATE_LOAD (1 << 5)
+#define _PSB_CE_DPM_STATE_STORE (1 << 4)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0)
+
+#define PSB_CR_PDS_CACHE_STATUS (SGX_BASE + 0x0138)
+
+#define PSB_CR_PDS_CACHE_HOST_ENABLE (SGX_BASE + 0x013C)
+
+#define PSB_CR_PDS_CACHE_HOST_CLEAR (SGX_BASE + 0x0140)
+#define _PSB_CPC_DSC1_INV3 (1 << 8)
+#define _PSB_CPC_DSC1_INV2 (1 << 7)
+#define _PSB_CPC_DSC1_INV1 (1 << 6)
+#define _PSB_CPC_DSC1_INV0 (1 << 5)
+#define _PSB_CPC_DSC0_INV3 (1 << 4)
+#define _PSB_CPC_DSC0_INV2 (1 << 3)
+#define _PSB_CPC_DSC0_INV1 (1 << 2)
+#define _PSB_CPC_DSC0_INV0 (1 << 1)
+#define _PSB_CPC_CSC_INV (1 << 0)
+
+/* 0x200 - 0x300 */
+#define PSB_CR_VDM_START (SGX_BASE + 0x0200)
+#define _PSB_CV_START_PULSE (1 << 0)
+
+#define PSB_CR_TE_TPCCONTROL (SGX_BASE + 0x0224)
+#define _PSB_CT_TPCCONTROL_CLEAR (1 << 31)
+#define _PSB_CT_TPCCONTROL_FLUSH (1 << 30)
+
+#define PSB_CR_TE_RGNBBOX_X (SGX_BASE + 0x0228)
+#define _PSB_CT_RGNBOX_X_MAX_SHIFT (16)
+#define _PSB_CT_RGNBOX_X_MAX_MASK (0x1FF << 16)
+#define _PSB_CT_RGNBOX_X_MIN_SHIFT (0)
+#define _PSB_CT_RGNBOX_X_MIN_MASK (0x1FF << 0)
+
+#define PSB_CR_TE_RGNBBOX_Y (SGX_BASE + 0x022C)
+#define _PSB_CT_RGNBOX_Y_MAX_SHIFT (16)
+#define _PSB_CT_RGNBOX_Y_MAX_MASK (0x1FF << 16)
+#define _PSB_CT_RGNBOX_Y_MIN_SHIFT (0)
+#define _PSB_CT_RGNBOX_Y_MIN_MASK (0x1FF << 0)
+
+#define PSB_CR_MTE_OTPM_OP (SGX_BASE + 0x024C)
+#define _PSB_CMO_OP_CSM_FLUSH (1 << 2)
+#define _PSB_CMO_OP_CSM_LOAD (1 << 1)
+#define _PSB_CMO_OP_CSM_INV (1 << 0)
+
+#define PSB_CR_TE_DIAG1 (SGX_BASE + 0x0280)
+#define _PSB_CT_DIAG1_PRERGNPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG2 (SGX_BASE + 0x0284)
+#define _PSB_CT_DIAG2_POSTRGNPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG3 (SGX_BASE + 0x0288)
+#define _PSB_CT_DIAG3_PREPTEPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG4 (SGX_BASE + 0x028C)
+#define _PSB_CT_DIAG4_POSTPTEPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG5 (SGX_BASE + 0x0290)
+#define _PSB_CT_DIAG5_PSGCTLDWORD_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG6 (SGX_BASE + 0x0294)
+#define _PSB_CT_DIAG6_PSGRGNHDR_COUNT_MASK (0xFFFF << 0)
+
+#define PSB_CR_TE_DIAG7 (SGX_BASE + 0x0298)
+#define _PSB_CT_DIAG7_TPCREADREQ_COUNT_SHIFT (16)
+#define _PSB_CT_DIAG7_TPCREADREQ_COUNT_MASK (0xFFFF << 16)
+#define _PSB_CT_DIAG7_TPCREADHIT_COUNT_SHIFT (0)
+#define _PSB_CT_DIAG7_TPCREADHIT_COUNT_MASK (0xFFFF << 0)
+
+#define PSB_CR_TE_DIAG8 (SGX_BASE + 0x029C)
+#define _PSB_CT_DIAG8_TPCSTATEINV_COUNT_SHIFT (16)
+#define _PSB_CT_DIAG8_TPCSTATEINV_COUNT_MASK (0xFFFF << 16)
+#define _PSB_CT_DIAG8_TPCWRITEHIT_COUNT_SHIFT (0)
+#define _PSB_CT_DIAG8_TPCWRITEHIT_COUNT_MASK (0xFFFF << 0)
+
+/* 0x400 - 0x500 */
+#define PSB_CR_ISP_START_RENDER (SGX_BASE + 0x0428)
+#define _PSB_CI_START_RENDER_PULSE (1 << 0)
+
+#define PSB_CR_TSP_PARAMETER_CACHE (SGX_BASE + 0x043C)
+#define _PSB_CTP_CACHE_INVALIDATE (1 << 0)
+
+/* 0x600 - 0x700 */
+
+#define PSB_CR_DPM_3D_PAGE_TABLE_BASE (SGX_BASE + 0x0600)
+#define _PSB_CD3PT_BASE_ADDR_SHIFT (4)//128-bit aligned address
+
+#define PSB_CR_DPM_3D_FREE_LIST (SGX_BASE + 0x0604)
+#define _PSB_CD3F_LIST_TAIL_SHIFT (16)
+#define _PSB_CD3F_LIST_TAIL_MASK (0xFFFF << 16)
+#define _PSB_CD3F_LIST_HEAD_SHIFT (0)
+#define _PSB_CD3F_LIST_HEAD_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_HOST_DALLOC_PAGE_TABLE_BASE (SGX_BASE + 0x0608)
+#define _PSB_CDHDPT_BASE_ADDR_SHIFT (4)//128-bit aligned address
+
+#define PSB_CR_DPM_HOST_DALLOC_FREE_LIST (SGX_BASE + 0x060C)
+#define _PSB_CDHDF_LIST_TAIL_SHIFT (16)
+#define _PSB_CDHDF_LIST_TAIL_MASK (0xFFFF << 16)
+#define _PSB_CDHDF_LIST_HEAD_SHIFT (0)
+#define _PSB_CDHDF_LIST_HEAD_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_HOST_ALLOC_PAGE_TABLE_BASE (SGX_BASE + 0x0610)
+#define _PSB_CDHAPT_BASE_ADDR_SHIFT (4)//128-bit aligned address
+
+#define PSB_CR_DPM_HOST_ALLOC_FREE_LIST (SGX_BASE + 0x0614)
+#define _PSB_CDHAF_LIST_TAIL_SHIFT (16)
+#define _PSB_CDHAF_LIST_TAIL_MASK (0xFFFF << 16)
+#define _PSB_CDHAF_LIST_HEAD_SHIFT (0)
+#define _PSB_CDHAF_LIST_HEAD_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_ALLOC_PAGE_TABLE_BASE (SGX_BASE + 0x0618)
+#define _PSB_CDTAPT_BASE_ADDR_SHIFT (4)//128-bit aligned address
+
+#define PSB_CR_DPM_TA_ALLOC_FREE_LIST (SGX_BASE + 0x061C)
+#define _PSB_CDTAF_LIST_TAIL_SHIFT (16)
+#define _PSB_CDTAF_LIST_TAIL_MASK (0xFFFF << 16)
+#define _PSB_CDTAF_LIST_HEAD_SHIFT (0)
+#define _PSB_CDTAF_LIST_HEAD_MASK (0xFFFF << 0)
+
+
+#define PSB_CR_DPM_TA_PAGE_THRESHOLD (SGX_BASE + 0x0620)
+#define _PSB_CDTP_THRESHOLD_VALUE_SHIFT (0)
+#define _PSB_CDTP_THRESHOLD_VALUE_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_ZLS_PAGE_THRESHOLD (SGX_BASE + 0x0624)
+#define _PSB_CDZP_THRESHOLD_VALUE_SHIFT (0)
+#define _PSB_CDZP_THRESHOLD_VALUE_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_GLOBAL_LIST (SGX_BASE + 0x0628)
+#define _PSB_CDTG_LIST_POLICY (1 << 16)
+#define _PSB_CDTG_LIST_SIZE_SHIFT (0)
+#define _PSB_CDTG_LIST_SIZE_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_STATE_CONTEXT_ID (SGX_BASE + 0x0630)
+#define _PSB_CDSC_ID_ALLOC (1 << 2)
+#define _PSB_CDSC_ID_DALLOC (1 << 1)
+#define _PSB_CDSC_ID_LS (1 << 0)
+
+#define PSB_CR_DPM_3D_DEALLOCATE (SGX_BASE + 0x063C)
+#define _PSB_CD3_DEALLOCATE_ENABLE (1 << 1)
+#define _PSB_CD3_DEALLOCATE_GLOBAL (1 << 0)
+
+#define PSB_CR_DPM_ALLOC (SGX_BASE + 0x0640)
+#define _PSB_CD_ALLOC_PAGE_OUTOFMEMORY (1 << 17)
+#define _PSB_CD_ALLOC_PAGE_VALID (1 << 16)
+#define _PSB_CD_ALLOC_PAGE_SHIFT (0)
+#define _PSB_CD_ALLOC_PAGE_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_DALLOC (SGX_BASE + 0x0644)
+#define _PSB_CD_DALLOC_PAGE_FREE (1 << 16)
+#define _PSB_CD_DALLOC_PAGE_SHIFT (0)
+#define _PSB_CD_DALLOC_PAGE_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_ALLOC (SGX_BASE + 0x0648)
+#define _PSB_CDT_ALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDT_ALLOC_FREE_LIST_PREVIOUS_MASK (0xFFFF << 16)
+
+#define PSB_CR_DPM_3D (SGX_BASE + 0x064C)
+#define _PSB_CD_3D_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CD_3D_FREE_LIST_PREVIOUS_MASK (0xFFFF << 16)
+
+#define PSB_CR_DPM_HOST_DALLOC (SGX_BASE + 0x0650)
+#define _PSB_CDH_DALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDH_DALLOC_FREE_LIST_PREVIOUS_MASK (0xFFFF << 16)
+
+#define PSB_CR_DPM_HOST_ALLOC (SGX_BASE + 0x0654)
+#define _PSB_CDH_ALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDH_ALLOC_FREE_LIST_PREVIOUS_MASK (0xFFFF << 16)
+
+#define PSB_CR_DPM_TASK_3D_FREE (SGX_BASE + 0x0680)
+#define _PSB_CDT3_FREE_LOAD (1 << 0)
+
+#define PSB_CR_DPM_TASK_TA_FREE (SGX_BASE + 0x0684)
+#define _PSB_CDTT_FREE_LOAD (1 << 0)
+
+#define PSB_CR_DPM_TASK_HOST_FREE (SGX_BASE + 0x0688)
+#define _PSB_CDTH_FREE_LOAD (1 << 0)
+
+#define PSB_CR_DPM_TASK_DHOST_FREE (SGX_BASE + 0x0690)
+#define _PSB_CDTD_FREE_LOAD (1 << 0)
+
+#define PSB_CR_DPM_TASK_STATE (SGX_BASE + 0x0694)
+#define _PSB_CDT_STATE_LOAD (1 << 2)
+#define _PSB_CDT_STATE_CLEAR (1 << 1)
+#define _PSB_CDT_STATE_STORE (1 << 0)
+
+#define PSB_CR_DPM_TASK_CONTROL (SGX_BASE + 0x0698)
+#define _PSB_CDT_CONTROL_LOAD (1 << 2)
+#define _PSB_CDT_CONTROL_CLEAR (1 << 1)
+#define _PSB_CDT_CONTROL_STORE (1 << 0)
+
+#define PSB_CR_DPM_OUTOFMEM (SGX_BASE + 0x069C)
+#define _PSB_CD_OUTOFMEM_ABORTALL (1 << 2)
+#define _PSB_CD_OUTOFMEM_ABORT (1 << 1)
+#define _PSB_CD_OUTOFMEM_RESTART (1 << 0)
+
+#define PSB_CR_DPM_FREE_CONTEXT (SGX_BASE + 0x06A0)
+#define _PSB_CDF_CONTEXT_NOW (1 << 0)
+
+#define PSB_CR_DPM_3D_TIMEOUT (SGX_BASE + 0x06A4)
+#define _PSB_CD3_TIMEOUT_NOW (1 << 0)
+
+#define PSB_CR_DPM_TA_EVM (SGX_BASE + 0x06A8)
+#define _PSB_CDT_EVM_INIT (1 << 0)
+
+/* 0x700 - 0x800 */
+
+#define PSB_CR_DPM_HOST_DALLOC_FREE_LIST_STATUS1 (SGX_BASE + 0x0708)
+#define _PSB_CDHDFL_STATUS1_TAIL_SHIFT (16)
+#define _PSB_CDHDFL_STATUS1_TAIL_MASK (0xFFFF << 16)
+#define _PSB_CDHDFL_STATUS1_HEAD_SHIFT (0)
+#define _PSB_CDHDFL_STATUS1_HEAD_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_PAGE_STATUS (SGX_BASE + 0x0724)
+#define _PSB_CDP_STATUS_TA_SHIFT (16)
+#define _PSB_CDP_STATUS_TA_MASK (0xFFFF << 16)
+#define _PSB_CDP_STATUS_TOTAL_SHIFT (0)
+#define _PSB_CDP_STATUS_TOTAL_MASK (0xFFFF << 0)
+
+#define PSB_CR_DPM_GLOBAL_PAGE_STATUS (SGX_BASE + 0x072C)
+#define _PSB_CDGP_STATUS_TA_SHIFT (16)
+#define _PSB_CDGP_STATUS_TA_MASK (0xFFFF << 16)
+#define _PSB_CDGP_STATUS_TOTAL_SHIFT (0)
+#define _PSB_CDGP_STATUS_TOTAL_MASK (0xFFFF << 0)
+
+#define PSB_CR_CACHE_CTRL (SGX_BASE + 0x0804)
+#define _PSB_CC_CTRL_L0P1OFF (1 << 30)
+#define _PSB_CC_CTRL_L0P0OFF (1 << 29)
+#define _PSB_CC_CTRL_INVALIDATE (1 << 28)
+#define _PSB_CC_CTRL_L1P1OFF (1 << 26)
+#define _PSB_CC_CTRL_L1P0OFF (1 << 25)
+#define _PSB_CC_CTRL_L2OFF (1 << 24)
+#define _PSB_CC_CTRL_PARTDM3_SHIFT (12)
+#define _PSB_CC_CTRL_PARTDM3_MASK (0xF << 12)
+#define _PSB_CC_CTRL_PARTDM2_SHIFT (8)
+#define _PSB_CC_CTRL_PARTDM2_MASK (0xF << 8)
+#define _PSB_CC_CTRL_PARTDM1_SHIFT (4)
+#define _PSB_CC_CTRL_PARTDM1_MASK (0xF << 4)
+#define _PSB_CC_CTRL_PARTDM0_SHIFT (0)
+#define _PSB_CC_CTRL_PARTDM0_MASK (0xF << 0)
+
+/* 0xa00 - 0xb00 */
+#define PSB_CR_USE_CACHE (SGX_BASE + 0x0A08)
+#define _PSB_CU_CACHE_INVALIDATE (1 << 0)
+
+/* USSE register definitions */
+
+/* USSE/PDS - 0xA00-0xBFF */
+
+#define PSB_CR_USE_CTRL (SGX_BASE + 0x0A00)
+#define _PSB_CU_CTRL_REGBOUND_ZERO (1 << 19)
+#define _PSB_CU_CTRL_REGBOUND_ZERO_R1 (0 << 19)
+#define _PSB_CU_CTRL_INSTLIMIT_SHIFT (14)
+#define _PSB_CU_CTRL_INSTLIMIT_MASK (0x1F << 14)
+#define _PSB_CU_CTRL_ST_TTE_SCALE_SHIFT (12)
+#define _PSB_CU_CTRL_ST_TTE_SCALE_MASK (0x3 << 12)
+#define _PSB_CU_CTRL_CACHE_TTE_SHIFT (4)
+#define _PSB_CU_CTRL_CACHE_TTE_MASK (0xFF << 4)
+#define _PSB_CU_CTRL_KILL_MODE_SHIFT (2)
+#define _PSB_CU_CTRL_KILL_MODE_MASK (0x3 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_OFF (0 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_FLUSH (1 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_KILL (2 << 2)
+#define _PSB_CU_CTRL_KILL_DM_SHIFT (0)
+#define _PSB_CU_CTRL_KILL_DM_MASK (0x3 << 0)
+
+
+#define PSB_CR_USE_CODE_BASE(i) (SGX_BASE + (0x0A0C + ((i) << 2)))
+#define _PSB_CUC_BASE_DM_SHIFT (25)
+#define _PSB_CUC_BASE_DM_MASK (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT (0) // 1024-bit aligned address?
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7)
+#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX (0)
+#define _PSB_CUC_DM_PIXEL (1)
+#define _PSB_CUC_DM_RESERVED (2)
+#define _PSB_CUC_DM_EDM (3)
+
+#define SGX_MAX_USSE_THRDS 16
+#define PSB_USE_OFFSET_MASK 0x0007FFFF
+#define PSB_USE_OFFSET_SIZE (SGX_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0 (SGX_BASE + 0x0A0C)
+#define PSB_CR_USE_CODE_BASE1 (SGX_BASE + 0x0A10)
+#define PSB_CR_USE_CODE_BASE2 (SGX_BASE + 0x0A14)
+#define PSB_CR_USE_CODE_BASE3 (SGX_BASE + 0x0A18)
+#define PSB_CR_USE_CODE_BASE4 (SGX_BASE + 0x0A1C)
+#define PSB_CR_USE_CODE_BASE5 (SGX_BASE + 0x0A20)
+#define PSB_CR_USE_CODE_BASE6 (SGX_BASE + 0x0A24)
+#define PSB_CR_USE_CODE_BASE7 (SGX_BASE + 0x0A28)
+#define PSB_CR_USE_CODE_BASE8 (SGX_BASE + 0x0A2C)
+#define PSB_CR_USE_CODE_BASE9 (SGX_BASE + 0x0A30)
+#define PSB_CR_USE_CODE_BASE10 (SGX_BASE + 0x0A34)
+#define PSB_CR_USE_CODE_BASE11 (SGX_BASE + 0x0A38)
+#define PSB_CR_USE_CODE_BASE12 (SGX_BASE + 0x0A3C)
+#define PSB_CR_USE_CODE_BASE13 (SGX_BASE + 0x0A40)
+#define PSB_CR_USE_CODE_BASE14 (SGX_BASE + 0x0A44)
+#define PSB_CR_USE_CODE_BASE15 (SGX_BASE + 0x0A48)
+
+#define PSB_CR_EVENT_PDS_ENABLE (SGX_BASE + 0x0A58)
+#define _PSB_CEP_ENABLE_TIMER (1 << 29)
+#define _PSB_CEP_ENABLE_TA_DPM_FAULT (1 << 28)
+#define _PSB_CEP_ENABLE_TWOD_COMPLETE (1 << 27)
+#define _PSB_CEP_ENABLE_MADD_CACHE_INVALCOMPLETE (1 << 26)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_ZLS (1 << 25)
+#define _PSB_CEP_ENABLE_DPM_TA_MEM_FREE (1 << 24)
+#define _PSB_CEP_ENABLE_ISP_END_PASS (1 << 23)
+#define _PSB_CEP_ENABLE_DPM_INITEND (1 << 22)
+#define _PSB_CEP_ENABLE_OTPM_LOADED (1 << 21)
+#define _PSB_CEP_ENABLE_OTPM_INV (1 << 20)
+#define _PSB_CEP_ENABLE_OTPM_FLUSHED (1 << 19)
+#define _PSB_CEP_ENABLE_PIXELBE_END_RENDER (1 << 18)
+#define _PSB_CEP_ENABLE_ISP_HALT (1 << 17)
+#define _PSB_CEP_ENABLE_ISP_VISIBILITY_FAIL (1 << 16)
+#define _PSB_CEP_ENABLE_BREAKPOINT (1 << 15)
+#define _PSB_CEP_ENABLE_SW_EVENT (1 << 14)
+#define _PSB_CEP_ENABLE_TA_FINISHED (1 << 13)
+#define _PSB_CEP_ENABLE_TA_TERMINATE (1 << 12)
+#define _PSB_CEP_ENABLE_TPC_CLEAR (1 << 11)
+#define _PSB_CEP_ENABLE_TPC_FLUSH (1 << 10)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_CLEAR (1 << 9)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_LOAD (1 << 8)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_STORE (1 << 7)
+#define _PSB_CEP_ENABLE_DPM_STATE_CLEAR (1 << 6)
+#define _PSB_CEP_ENABLE_DPM_STATE_LOAD (1 << 5)
+#define _PSB_CEP_ENABLE_DPM_STATE_STORE (1 << 4)
+#define _PSB_CEP_ENABLE_DPM_REACHED_MEM_THRESH (1 << 3)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_GBL (1 << 2)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_MT (1 << 1)
+#define _PSB_CEP_ENABLE_DPM_3D_MEM_FREE (1 << 0)
+
+#define PSB_CR_DMS_CTRL (SGX_BASE + 0x0A74)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_PARTITIONS_SHIFT (25)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_PARTITIONS_MASK (0x7 << 25)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_PARTITIONS_SHIFT (22)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_PARTITIONS_MASK (0x7 << 22)
+#define _PSB_CD_CTRL_MAX_NUM_EDM_TASKS_SHIFT (16)
+#define _PSB_CD_CTRL_MAX_NUM_EDM_TASKS_MASK (0x3F << 16)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_TASKS_SHIFT (10)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_TASKS_MASK (0x3F << 10)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_TASKS_SHIFT (4)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_TASKS_MASK (0x3F << 4)
+#define _PSB_CD_CTRL_DISABLE_DM_SHIFT (0)
+#define _PSB_CD_CTRL_DISABLE_DM_MASK (0xF << 0)
+#define _PSB_CD_CTRL_DISABLE_DM_VERTEX (1 << 0)
+#define _PSB_CD_CTRL_DISABLE_DM_PIXEL (1 << 1)
+#define _PSB_CD_CTRL_DISABLE_DM_EVENT (1 << 2)
+#define _PSB_CD_CTRL_DISABLE_DM_LOOPBACK (1 << 3)
+
+#define PSB_CR_DMS_AGE (SGX_BASE + 0x0A78)
+#define _PSB_CD_AGE_ENABLE (1 << 16)
+#define _PSB_CD_AGE_VALUE_SHIFT (0)
+#define _PSB_CD_AGE_VALUE_MASK (0xFFFF << 0)
+
+#define PSB_CR_USE_G0 (SGX_BASE + 0x0A7C)
+#define _PSB_CU_G0_VALUE_SHIFT (0)
+#define _PSB_CU_G0_VALUE_MASK (0xFF << 0)
+
+#define PSB_CR_USE_G1 (SGX_BASE + 0x0A80)
+#define _PSB_CU_G1_VALUE_SHIFT (0)
+#define _PSB_CU_G1_VALUE_MASK (0xFF << 0)
+
+#define PSB_CR_PDS_EXEC_BASE (SGX_BASE + 0x0AB8)
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20)/* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
+
+#define PSB_CR_USE0_DM_SLOT (SGX_BASE + 0x0AA4)
+
+#define PSB_CR_USE1_DM_SLOT (SGX_BASE + 0x0AA8)
+
+#define PSB_CR_USE_TMPREG (SGX_BASE + 0x0AAC)
+#define _PSB_CU_TMPREG_INIT_SHIFT (3)
+#define _PSB_CU_TMPREG_INIT_MASK (0x1F << 3)
+#define _PSB_CU_TMPREG_SIZE_SHIFT (0)
+#define _PSB_CU_TMPREG_SIZE_MASK (0x7 << 0)
+
+#define PSB_CR_EVENT_TIMER (SGX_BASE + 0x0ACC)
+#define _PSB_CE_TIMER_ENABLE (1 << 24)
+#define _PSB_CE_TIMER_VALUE_SHIFT (0)
+#define _PSB_CE_TIMER_VALUE_MASK (0xFFFFFF << 0)
+
+#define PSB_CR_PDS (SGX_BASE + 0x0ABC)
+#define _PSB_C_PDS_DOUT_TIMEOUT_DISABLE (1 << 6)
+#define _PSB_C_PDS_ATTRIBUTE_CHUNK_START_SHIFT (0)
+#define _PSB_C_PDS_ATTRIBUTE_CHUNK_START_MASK (0x3F << 0)
+
+#define PSB_CR_PDS_INV0 (SGX_BASE + 0x0AD0)
+
+#define PSB_CR_PDS_INV1 (SGX_BASE + 0x0AD4)
+
+#define PSB_CR_PDS_INV2 (SGX_BASE + 0x0AD8)
+
+#define PSB_CR_PDS_INV3 (SGX_BASE + 0x0ADC)
+#define _PSB_CP_INV_DSC (1 << 0)
+
+#define PSB_CR_PDS_INV_CSC (SGX_BASE + 0x0AE0)
+#define _PSB_CPI_CSC_KICK (1 << 0)
+
+/* 0xb00 - 0xc00 */
+#define PSB_CR_USE0_SERV_PIXEL (SGX_BASE + 0x0B08)
+#define _PSB_CUS_PIXEL_EMPTY (1 << 16)
+#define _PSB_CUS_PIXEL_COUNT_SHIFT (0)
+#define _PSB_CUS_PIXEL_COUNT_MASK (0xFFFF << 0)
+
+#define PSB_CR_USE0_SERV_VERTEX (SGX_BASE + 0x0B0C)
+#define _PSB_CUS_VERTEX_EMPTY (1 << 16)
+#define _PSB_CUS_VERTEX_COUNT_SHIFT (0)
+#define _PSB_CUS_VERTEX_COUNT_MASK (0xFFFF << 0)
+
+#define PSB_CR_USE0_SERV_EVENT (SGX_BASE + 0x0B10)
+#define _PSB_CUS_EVENT_EMPTY (1 << 16)
+#define _PSB_CUS_EVENT_COUNT_SHIFT (0)
+#define _PSB_CUS_EVENT_COUNT_MASK (0xFFFF << 0)
+
+#define PSB_CR_USE1_SERV_PIXEL (SGX_BASE + 0x0B14)
+
+#define PSB_CR_USE1_SERV_VERTEX (SGX_BASE + 0x0B18)
+
+#define PSB_CR_USE1_SERV_EVENT (SGX_BASE + 0x0B1C)
+
+/* 0xc00 - 0xd00 */
+/* BIF register definitions */
+#define PSB_CR_BIF_CTRL (SGX_BASE + 0x0C00)
+#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4)
+#define _PSB_CB_CTRL_INVALDC (1 << 3)
+#define _PSB_CB_CTRL_FLUSH (1 << 2)
+#define _PSB_MMU_ER_MASK 0x0001FF00
+#define _PSB_MMU_ER_HOST (1 << 16)
+
+#define PSB_CR_BIF_INT_STAT (SGX_BASE + 0x0C04)
+
+#define PSB_CR_BIF_FAULT (SGX_BASE + 0x0C08)
+#define _PSB_CBI_STAT_PF_N_RW (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT (0)
+#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST (1 << 9)
+
+#define PSB_CR_BIF_BANK_SET (SGX_BASE + 0x0C74)
+#define _PSB_CBB_SET_SELECT_SHIFT (0)
+#define _PSB_CBB_SET_SELECT_MASK (0x3FF << 0)
+#define _PSB_CBB_SET_SELECT_DPM_TA (0 << 9)
+#define _PSB_CBB_SET_SELECT_DPM_3D (1 << 9)
+#define _PSB_CBB_SET_SELECT_EDM_B0 (0 << 8)
+#define _PSB_CBB_SET_SELECT_EDM_B1 (1 << 8)
+#define _PSB_CBB_SET_SELECT_TA_B0 (0 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B0B1 (1 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B1B0 (2 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B1 (3 << 6)
+#define _PSB_CBB_SET_SELECT_HOST_B0 (0 << 4)
+#define _PSB_CBB_SET_SELECT_HOST_B1 (3 << 4)
+#define _PSB_CBB_SET_SELECT_3D_B0 (0 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B0B1 (1 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B1B0 (2 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B1 (3 << 2)
+#define _PSB_CBB_SET_SELECT_2D_B0 (0 << 0)
+#define _PSB_CBB_SET_SELECT_2D_B1 (3 << 0)
+
+#define PSB_CR_BIF_BANK0 (SGX_BASE + 0x0C78)
+#define PSB_CR_BIF_BANK1 (SGX_BASE + 0x0C7C)
+
+#define _PSB_CB_BANK_INDEX_2D_SHIFT (16)
+#define _PSB_CB_BANK_INDEX_2D_MASK (0xF << 16)
+#define _PSB_CB_BANK_INDEX_3D_SHIFT (12)
+#define _PSB_CB_BANK_INDEX_3D_MASK (0xF << 12)
+#define _PSB_CB_BANK_INDEX_HOST_SHIFT (8)
+#define _PSB_CB_BANK_INDEX_HOST_MASK (0xF << 8)
+#define _PSB_CB_BANK_INDEX_TA_SHIFT (4)
+#define _PSB_CB_BANK_INDEX_TA_MASK (0xF << 4)
+#define _PSB_CB_BANK_INDEX_EDM_SHIFT (0)
+#define _PSB_CB_BANK_INDEX_EDM_MASK (0xF << 0)
+
+#define PSB_CR_BIF_DIR_LIST_BASE0 (SGX_BASE + 0x0C84)
+#define PSB_CR_BIF_DIR_LIST_BASE1 (SGX_BASE + 0x0C38)
+#define PSB_CR_BIF_TWOD_REQ_BASE (SGX_BASE + 0x0C88)
+
+#define PSB_CR_BIF_TA_REQ_BASE (SGX_BASE + 0x0C90)
+#define _PSB_CBTR_BASE_ADDR_SHIFT (20) // 1MB aligned address
+
+#define PSB_CR_BIF_MEM_ARB_CONFIG (SGX_BASE + 0x0CA0)
+#define _PSB_CBMA_CONFIG_TTE_THRESH_SHIFT (12)
+#define _PSB_CBMA_CONFIG_TTE_THRESH_MASK (0xFFF << 12)
+#define _PSB_CBMA_CONFIG_BEST_CNT_SHIFT (4)
+#define _PSB_CBMA_CONFIG_BEST_CNT_MASK (0xFF << 4)
+#define _PSB_CBMA_CONFIG_PAGE_SIZE_SHIFT (0)
+#define _PSB_CBMA_CONFIG_PAGE_SIZE_MASK (0xF << 0)
+
+#define PSB_CR_BIF_3D_REQ_BASE (SGX_BASE + 0x0CAC)
+#define _PSB_CB3R_BASE_ADDR_ALIGNSHIFT (20)
+#define _PSB_CB3R_BASE_ADDR_SHIFT (20) // 1MB aligned address
+
+/* 0xe00 - 0xf00 */
+#define PSB_EUR_CR_2D_SOCIF (SGX_BASE + 0x0e18)
+
+#define PSB_EUR_CR_2D_BLIT_STATUS (SGX_BASE + 0x0e04)
+
+#endif /* _REGS_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/rb.h b/drivers/gpu/drm/emgd/emgd/include/rb.h
new file mode 100644
index 0000000..8e0c166
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/rb.h
@@ -0,0 +1,186 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: rb.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This header file describes the inter-module interface for using the
+ * ring buffer. This is a legacy interface that is not strictly
+ * device-independent. It is kept here because many legacy chipsets use
+ * this interface.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _RB_H
+#define _RB_H
+
+#include <igd_rb.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <module_init.h>
+#include <mode.h>
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+
+/*
+ * The rb_buffer contents should be treated as opaque but are defined
+ * here for the use in the inline functions below.
+ */
+typedef struct _rb_buffer {
+ unsigned int id; /* ring index */
+ unsigned long size; /* size of rb in bytes */
+ unsigned long tail_off;
+ unsigned long dead_off;
+ unsigned long avail;
+ unsigned long addr; /* starting address of rb */
+ unsigned char *virt; /* virt starting address of rb */
+ unsigned char *start; /* ring buffer start register offset */
+ unsigned char *head; /* ring buffer head register offset */
+ unsigned char *tail; /* ring buffer tail register offset */
+ unsigned char *ctrl; /* ring buffer ctrl register offset */
+ unsigned char *sync; /* used to synchronize s/w interface
+ * code via rb_sync() */
+ unsigned long next_sync;
+ int state; /* on or off state */
+ unsigned long last_head_value; /* used for checking ring buf lockup,
+ * keeps last head value*/
+ os_alarm_t last_head_time; /* used for checking ring buf lockup,
+ * keeps last head time*/
+ unsigned long reservation; /* increments upon each rb_reserver(),
+ * reset to zero upon rb_update() */
+ unsigned long sync_wrap; /* Sync number to wrap at */
+ igd_context_t * context_ptr; /*back pointer to the main driver context */
+ igd_appcontext_h appcontext; /* Appcontext that is current on the ring */
+ unsigned int skip_timeout; /* skip the timeout check */
+ unsigned int force_reset_rb; /* force a rb reset */
+} rb_buffer_t;
+
+
+#define MODE_GET_RING(d, p) \
+ ((rb_buffer_t *)((igd_display_pipe_t *)((igd_display_context_t *)d)->pipe)->queue[p])
+
+/*
+ * Flags used exclusively by rb_reserve()
+ */
+#define RB_RESERVE_BLOCK 0x00000000
+#define RB_RESERVE_NONBLOCK 0x00000001
+
+
+/*
+ * Determine how much space is available in the ring buffer.
+ */
+unsigned long rb_avail(rb_buffer_t *buffer);
+
+
+#define MODE_PIPE_ALLOCED(d) \
+ ((igd_display_pipe_t *)((igd_display_context_t *)d)->pipe)
+
+extern igd_command_t *rb_slow_reserve(rb_buffer_t *buffer,
+ unsigned long size,
+ unsigned long flags);
+/*
+ * For Debug do not use the inline ring functions. It makes it hard
+ * to add breakpoints.
+ */
+#ifdef DEBUG_BUILD_TYPE
+extern igd_command_t *rb_reserve(rb_buffer_t *buffer,
+ unsigned long size,
+ unsigned long flags);
+
+extern int rb_update(rb_buffer_t *buffer,
+ igd_command_t *addr);
+
+#else
+#ifdef CONFIG_CMD
+static __inline igd_command_t *rb_reserve(rb_buffer_t *buffer,
+ unsigned long size,
+ unsigned long flags)
+{
+ if (buffer->state == CMD_CONTROL_OFF) {
+ /* ring buffer is turned off, so don't allow a rb_reserve() */
+ buffer->context_ptr->igd_device_error_no = -IGD_ERROR_PWRDOWN;
+ return(NULL);
+ }
+
+ /*
+ * Change size to bytes for efficiency.
+ */
+ size = ((size<<2) + 7) & ~7;
+
+ if(buffer->reservation) {
+ buffer->avail += buffer->reservation;
+ }
+ buffer->reservation = size;
+
+ if(buffer->avail > size) {
+ buffer->avail -= size;
+ return (igd_command_t *)(buffer->virt + buffer->tail_off);
+ }
+
+ return rb_slow_reserve(buffer, size, flags);
+}
+
+
+static __inline int rb_update(rb_buffer_t *buffer,
+ igd_command_t *addr)
+{
+ unsigned long tail_off;
+/* tail_off = (addr - buffer->virt); */
+ tail_off = (unsigned long)((unsigned char *)(addr) - buffer->virt);
+
+ buffer->reservation = 0;
+ buffer->tail_off = tail_off;
+
+ if(buffer->tail_off & 0x7) {
+ EMGD_WRITE32(0, buffer->virt + buffer->tail_off);
+ buffer->tail_off += 4;
+ buffer->avail -= 4;
+ }
+
+ EMGD_WRITE32(buffer->tail_off, buffer->tail);
+
+ return 0;
+}
+#else
+static __inline igd_command_t *rb_reserve(rb_buffer_t *buffer,
+ unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+static __inline int rb_update(rb_buffer_t *buffer,
+ igd_command_t *addr)
+{
+ return 0;
+}
+#endif /* CONFIG_CMD */
+#endif
+
+#endif /* _RB_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/reset.h b/drivers/gpu/drm/emgd/emgd/include/reset.h
new file mode 100644
index 0000000..809cb52
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/reset.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reset.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for the reset module. It should be included
+ * by ssigd HAL modules that need to access the reset module for initialization
+ * and shutdown
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_RESET_INIT_H
+#define _IGD_RESET_INIT_H
+
+#define RESET_FLAG_CAPTURE_SNAPSHOT 0x00000001
+#define RESET_FLAG_EXECUTE_SOFT_RESET 0x00000002
+#define RESET_FLAG_EXECUTE_HARD_RESET 0x00000003
+
+
+#endif /*_IGD_RESET_H*/
diff --git a/drivers/gpu/drm/emgd/emgd/include/sched.h b/drivers/gpu/drm/emgd/emgd/include/sched.h
new file mode 100644
index 0000000..9b33a1a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/sched.h
@@ -0,0 +1,197 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sched.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains Linux User-space implementations for the OAL io.h
+ * abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_LINUX_USER_SCHED_H
+#define _OAL_LINUX_USER_SCHED_H
+
+#include <config.h>
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+typedef unsigned long os_alarm_t;
+
+static __inline os_alarm_t _linux_kernel_set_alarm(unsigned long t)
+{
+ return (msecs_to_jiffies(t) + jiffies);
+}
+
+static __inline int _linux_kernel_test_alarm(os_alarm_t t)
+{
+ return (jiffies >= t) ? 1 : 0;
+}
+
+#define OS_SET_ALARM(t) _linux_kernel_set_alarm(t)
+#define OS_TEST_ALARM(t) _linux_kernel_test_alarm(t)
+
+
+/*----------------------------------------------------------------------------
+ * Function: OS_INIT_INTERRUPT
+ *
+ * Description:
+ * This function establishes the communication for sending requests for interrupt
+ *
+ * int OS_INIT_INTERRUPT( did, mmadr )
+ *---------------------------------------------------------------------------*/
+#ifdef CONFIG_INTERRUPT
+#define OS_INIT_INTERRUPT(did, mmadr) _OS_INIT_INTERRUPT(did, mmadr)
+#else
+#define OS_INIT_INTERRUPT(did, mmadr) 0
+#endif
+
+
+
+/*----------------------------------------------------------------------------
+ * Function: OS_SCHEDULE
+ *
+ * Description:
+ * This function can be called with the caller wished to give up processor
+ * control until the next available timeslice. This will allow other OS tasks
+ * to run before returning to the current context. This function should be
+ * used with caution and observation of reentrant coding principals.
+ *
+ * void OS_SCHEDULE( void );
+ *---------------------------------------------------------------------------*/
+
+#define OS_SCHEDULE() { \
+ __set_current_state(TASK_INTERRUPTIBLE); \
+ schedule_timeout(1); }
+
+#if 0
+#define OS_DELAY(usec) { \
+ unsigned long j_timeout = usecs_to_jiffies(usec); \
+ unsigned long j_start = jiffies; \
+ unsigned long j_current; \
+ do { \
+ j_current = jiffies; \
+ }while((j_current - j_start) < j_timeout); \
+}
+#else
+#define OS_DELAY(usec) udelay(usec);
+#endif
+
+#if 0
+// Implement _OS_SLEEP at a wait-loop
+#define _OS_SLEEP(usec) { \
+ unsigned long j_timeout = usecs_to_jiffies(usec); \
+ unsigned long j_start = jiffies; \
+ unsigned long j_current; \
+ do { \
+ j_current = jiffies; \
+ }while((j_current - j_start) < j_timeout); \
+}
+#else
+// Implement _OS_SLEEP as a true sleep
+
+/* We could also try TASK_UNINTERRUPTIBLE here */
+/*----------------------------------------------------------------------------
+ * Function: OS_SLEEP
+ *
+ * Parameters:
+ * time_val: Unsigned long time value in Micro-seconds (1/1000000 of a second)
+ * for the task to sleep.
+ *
+ * Description:
+ * This function causes the caller to delay further processing
+ * for the number of micro-seconds ( 1/1000000 or a second ) requested.
+ * This function should only be used with small time values
+ * ( < 1/100 of a second ) as lengthy sleeps could degrade the kernel
+ * response time.
+ *
+ * void OS_SLEEP( unsigned long time_val );
+ *---------------------------------------------------------------------------*/
+
+#define OS_SLEEP(usec) { \
+ __set_current_state(TASK_KILLABLE); \
+ schedule_timeout(usecs_to_jiffies(usec)); }
+#endif
+
+/*----------------------------------------------------------------------------
+ * Function: OS_UISLEEP
+ *
+ * Parameters:
+ * time_val: Unsigned long time value in Micro-seconds (1/1000000 of a second)
+ * for the task to sleep.
+ *
+ * Description:
+ * This function causes the caller to delay further processing
+ * for the number of micro-seconds ( 1/1000000 or a second ) requested.
+ * This sleep is uninterrruptable.
+ * This function should only be used with small time values
+ * ( < 1/100 of a second ) as lengthy sleeps could degrade the kernel
+ * response time.
+ *
+ * void OS_UISLEEP( unsigned long time_val );
+ *---------------------------------------------------------------------------*/
+
+/* un interuuptable sleep */
+#define OS_UISLEEP(usec) { \
+ __set_current_state(TASK_UNINTERRUPTIBLE); \
+ schedule_timeout(usecs_to_jiffies(usec)); \
+}
+
+#ifndef OS_PTHREAD_CREATE
+typedef int os_pthread_t;
+// This function is not being used.
+// #define OS_PTHREAD_CREATE(t, a, f, p) (-1)
+#endif
+
+#ifndef OS_PTHREAD_JOIN
+// This function is not being used.
+// #define OS_PTHREAD_JOIN(t, p) (0)
+#endif
+
+/*
+ * Note, the POSIX pthread implementation does not take the thread as a
+ * parameter but it makes porting easier.
+ */
+#define UNREFERENCED_PARAMETER(parm) ((parm)=(parm))
+
+#ifndef OS_PTHREAD_EXIT
+// This function is not being used.
+// #define OS_PTHREAD_EXIT(t, r)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_INIT
+typedef struct mutex os_pthread_mutex_t;
+#define OS_PTHREAD_MUTEX_INIT(m, a) mutex_init(m)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_LOCK
+#define OS_PTHREAD_MUTEX_LOCK(m) mutex_lock_interruptible(m)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_UNLOCK
+#define OS_PTHREAD_MUTEX_UNLOCK(m) mutex_unlock(m)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/state2d.h b/drivers/gpu/drm/emgd/emgd/include/state2d.h
new file mode 100644
index 0000000..af04e47
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/state2d.h
@@ -0,0 +1,69 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state2d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is the header file for manipulating the 2D State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE2D_H
+#define _STATE2D_H
+
+/* IGD */
+#include <igd_render.h>
+
+typedef struct _state2d {
+ igd_rect_t dest_rect;
+ unsigned int clip_status;
+} state2d_t;
+
+#define STATE2D(ac) ((state2d_t *)ac->state2d)
+
+#define STATE2D_SET_CLIP(ac, rect) \
+if(ac) { \
+ OS_MEMCPY(&((state2d_t *)(ac)->state2d)->dest_rect, rect, \
+ sizeof(igd_rect_t)); \
+}
+ /*
+ * Checking for the 2D appcontext instead of the appcontext
+ * pointer because the state2d could be null during botched
+ * allocation.
+ */
+#define STATE2D_GET_CLIP(ac) \
+ (((ac) && ((state2d_t *)(ac)->state2d))? \
+ (&((state2d_t *)(ac)->state2d)->dest_rect):NULL)
+
+#define STATE2D_GET_CLIP_STATUS(ac) \
+ (((ac) && ((state2d_t *)(ac)->state2d))? \
+ (((state2d_t *)(ac)->state2d)->clip_status):0)
+
+#define STATE2D_SET_CLIP_STATUS(ac, s) \
+ (((ac) && ((state2d_t *)(ac)->state2d))? \
+ (((state2d_t *)(ac)->state2d)->clip_status = s):0)
+
+#endif /*_STATE2D_H */
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h b/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
new file mode 100644
index 0000000..0c76cf1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
@@ -0,0 +1,40 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the inter-module header file for the client context module.
+ * It contains data structures needed for modules to use and manipulate
+ * the device state including hardware context switching.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _APPCONTEXT_TNC_H
+#define _APPCONTEXT_TNC_H
+
+/* reusing pouslbo structures */
+#include<plb/appcontext.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h b/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
new file mode 100644
index 0000000..731c86a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
@@ -0,0 +1,39 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Device dependent header file for the command interface for poulsbo
+ * devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _TNC_CMD_H
+#define _TNC_CMD_H
+
+/* reusing pouslbo codes */
+#include<plb/cmd.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/context.h b/drivers/gpu/drm/emgd/emgd/include/tnc/context.h
new file mode 100644
index 0000000..bcd73ee
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/context.h
@@ -0,0 +1,37 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: context.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_TNC_CONTEXT_H
+#define _HAL_TNC_CONTEXT_H
+
+#include<plb/context.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h b/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
new file mode 100644
index 0000000..7cd4aa7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
@@ -0,0 +1,133 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_tnc_wa.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This header file contains the Device Dependent information used with
+ * the IEGD HAL for the Atom E6xx family of supported chips.
+ * Note: This file should be included into a C file as <tnc/igd_tnc_wa.h> and
+ * not <igd_tnc_wa.h> this will insure that multiple device dependent
+ * igd_cmd.h files can be included into a single C source.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_TNC_WA_H
+#define _IGD_TNC_WA_H
+
+#define LNC_CLOCK 199500
+#define LNC_B1_OPTIMUM_MARGIN 2000
+#define LIMIT_TOTAL_CHECK_DISPLAY 10
+#define T0 0
+#define T1 1
+#define WA_TUNE \
+ ((tnc_wa_timing_t *)&tune)
+/* Graphic core Revision ID for Atom E6xx stepping */
+#define TNC_A0_RID 0x2
+#define TNC_B0_RID 0x3
+#define TNC_B0_DEV3_RID 0x1
+#define TNC_B1_DEV3_RID 0x2
+#define SDVO_CRC_CTRL_REG 0x61050
+#define SDVO_BUFF_CTRL_REG 0x61170
+#define TNC_HTOTAL_TUNED 0x8000
+
+/* flag to enable clipping hardware fix in TNC B1 */
+#define IGD_CLIP_FIX_DISABLE 0x0000
+ /* Completely disable throttling */
+#define IGD_CLIP_FIX_DISABLE_THROTTLE 0x0001
+/* Replaces the original stall_pixel from FSM with external stall from cDVO */
+#define IGD_CLIP_FIX_REPLACE_STALL 0x0002
+#define IGD_CLIP_FIX_GLOBAL_ENABLE 0x8000
+#define CLIP_HW_FIX_DEFAULT 0x8001
+
+/*
+ * These are the register default settings for TC B1
+ * They are used for the undocumented register override feature
+ * when en_reg_override=1
+ */
+#define DISP_ARB 0x00003232
+#define FIFO_WATERMARK_1 0x3f8f0404
+#define FIFO_WATERMARK_2 0x04040f04
+#define FIFO_WATERMARK_3 0x00000000
+#define FIFO_WATERMARK_4 0x04040404
+#define FIFO_WATERMARK_5 0x04040404
+#define FIFO_WATERMARK_6 0x00000078
+#define GVD_HP_CONTROL 0x102003f2
+#define DISP_CHICKENBITS 0x0000c040
+#define BCHICKENBITS 0xffe32004
+#define BWFLUSH 0x00000408
+
+typedef struct _tnc_wa_timing_t{
+ short htotal;
+ short delta;
+ short flag;
+ short counter;
+ unsigned int crc_red;
+ unsigned int crc_green;
+ unsigned int crc_blue;
+}tnc_wa_timing_t;
+
+typedef union
+{
+ unsigned int pixel;
+ struct
+ {
+ unsigned int bit0 :1;
+ unsigned int bit1 :1;
+ unsigned int bit2 :1;
+ unsigned int bit3 :1;
+ unsigned int bit4 :1;
+ unsigned int bit5 :1;
+ unsigned int bit6 :1;
+ unsigned int bit7 :1;
+ unsigned int bit8 :1;
+ unsigned int bit9 :1;
+ unsigned int bit10 :1;
+ unsigned int bit11 :1;
+ unsigned int bit12 :1;
+ unsigned int bit13 :1;
+ unsigned int bit14 :1;
+ unsigned int bit15 :1;
+ unsigned int bit16 :1;
+ unsigned int bit17 :1;
+ unsigned int bit18 :1;
+ unsigned int bit19 :1;
+ unsigned int bit20 :1;
+ unsigned int bit21 :1;
+ unsigned int bit22 :1;
+ unsigned int bitExtra :1;
+ unsigned int bitRest :8;
+ } bit;
+} pixel_crc_t;
+
+
+/*
+* CDVO regs structure. This is mainly used to move the CDVO reset sequence
+* to the data segment for VBIOS.
+*/
+typedef struct _cdvo_regs_t{
+ unsigned long reg;
+ unsigned long value;
+}cdvo_regs_t;
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h b/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
new file mode 100644
index 0000000..14bf85f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
@@ -0,0 +1,40 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+#ifndef _INSTR_TNC_H
+#define _INSTR_TNC_H
+
+#include<plb/instr.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h b/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
new file mode 100644
index 0000000..2bb8c23
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
@@ -0,0 +1,41 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is a header file for the Intel GFX commands.
+ * This includes commands specific to Intel hardware and structures specific
+ * to Intel hardware. All other commands and structures are available
+ * through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _TNC_MI_H
+#define _TNC_MI_H
+
+#include<plb/mi.h>
+
+
+#endif /* _MI_H */
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h b/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
new file mode 100644
index 0000000..218722c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
@@ -0,0 +1,889 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: regs.h
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the register definition file for the Atom E6xx platform. This should
+ * contain device dependent register definitions. Standard register
+ * definitions (VGA, PCI, etc) should not be put in this file. For those
+ * see pci.h or vga.h.
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * Note: Use _REGS_H_ instead of _TNC_REGS_H_ to insure that no file can
+ * include 2 device dependent register files.
+ */
+#ifndef _REGS_H_
+#define _REGS_H_
+
+#include <pci.h>
+#include <psb_regs.h>
+#include <msvdx.h>
+#include <topaz.h>
+
+/*-----------------------------------------------------------------------------
+ * PCI Register Definitions
+ *---------------------------------------------------------------------------*/
+#define TNC_PCI_MMADR PCI_BAR_0
+#define TNC_PCI_IOBAR PCI_BAR_1
+#define TNC_PCI_GMADR PCI_BAR_2
+#define TNC_PCI_GTTADR PCI_BAR_3
+
+/*
+ * GVD.MGGC
+ * Device: 2 Offset:50h
+ * [22:20] Graphics mode select
+ * [17] VGA Disable
+ */
+#define TNC_PCI_GC 0x52
+#define TNC_PCI_BSM 0x5C
+
+/* Atom E6xx Device 31 GPIO base address offset */
+#define TNC_PCI_GBA 0x44
+
+#define TNC_D2_MMIO_SIZE (1024*1024)
+#define TNC_D3_MMIO_SIZE (512*1024)
+#define TNC_ST_SDVO_MMIO_SIZE (10*1024)
+
+#define TNC_GTT_SIZE (128*1024)
+
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG 0x3DA /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA /* Feature Control Register (Read) */
+#define MSR_PORT 0x3C2 /* Miscellaneous Output Port */
+#define MSR_PORT_LSB 0xC2 /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT 0x3CC /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00 0x3C2 /* Input Status Register 0 */
+#define STATUS_REG_01 0x3DA /* Input Status Register 1 */
+#define STATUS_REG_01_MONO 0x3BA /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK 0x3C6 /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX 0x3C7 /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE 0x3C7 /* Color Palette State Register */
+#define DAC_WRITE_INDEX 0x3C8 /* Color Palette Index Register */
+#define DAC_DATA_REG 0x3C9 /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Attribute Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define AR_PORT_LSB 0xC0 /*Attribute Controller Index Port LSB */
+
+#define AR00 0x00 /* Color Data Register */
+#define AR01 0x01 /* Color Data Register */
+#define AR02 0x02 /* Color Data Register */
+#define AR03 0x03 /* Color Data Register */
+#define AR04 0x04 /* Color Data Register */
+#define AR05 0x05 /* Color Data Register */
+#define AR06 0x06 /* Color Data Register */
+#define AR07 0x07 /* Color Data Register */
+#define AR08 0x08 /* Color Data Register */
+#define AR09 0x09 /* Color Data Register */
+#define AR0A 0x0A /* Color Data Register */
+#define AR0B 0x0B /* Color Data Register */
+#define AR0C 0x0C /* Color Data Register */
+#define AR0D 0x0D /* Color Data Register */
+#define AR0E 0x0E /* Color Data Register */
+#define AR0F 0x0F /* Color Data Register */
+#define AR10 0x10 /* Mode Control Register */
+#define AR11 0x11 /* Overscan Color Register */
+#define AR12 0x12 /* Color Plane Enable Register */
+#define AR13 0x13 /* Horizontal Pixel Panning Register */
+#define AR14 0x14 /* Pixel Pad Register */
+
+
+/*-----------------------------------------------------------------------------
+ * CRT Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define CR_PORT_LSB 0xD4 /* CRT Controller Index Port LSB */
+#define CRT_3D4 0x3D4 /* Color CRTC Index Port */
+#define CRT_3B4 0x3B4 /* Monochrome CRTC Index Port */
+
+#define CR00 0x00 /* Horizontal Total Register */
+#define CR01 0x01 /* Horizontal Display Enable End Reg */
+#define CR02 0x02 /* Horizontal Blank Start Register */
+#define CR03 0x03 /* Horizontal Blank End Register */
+#define CR04 0x04 /* Horizontal Sync Start Register */
+#define CR05 0x05 /* Horizontal Sync End Register */
+#define CR06 0x06 /* Vertical Total Register */
+#define CR07 0x07 /* Overflow Register */
+#define CR08 0x08 /* Preset Row Scan Register */
+#define CR09 0x09 /* Maximum Scan Line Register */
+#define DOUBLE_SCANLINE BIT7 /* Double scan ( 1 = Enable ) */
+#define LCOMP_BIT9 BIT6 /* Bit 9 of line compare register */
+#define VBLANK_BIT9 BIT5 /* Bit 9 of vertical blank start */
+#define CR0A 0x0A /* Cursor Start Scan Line Register */
+#define CR0B 0x0B /* Cursor End Scan Line Register */
+#define CR0C 0x0C /* Start Address High Register */
+#define CR0D 0x0D /* Start Address Low Register */
+#define CR0E 0x0E /* Cursor Location High Register */
+#define CR0F 0x0F /* Cursor Location Low Register */
+#define CR10 0x10 /* Vertical Sync Start Register */
+#define CR11 0x11 /* Vertical Sync End Register */
+#define CR12 0x12 /* Vertical Display Enable End Reg */
+#define CR13 0x13 /* Offset Register */
+#define CR14 0x14 /* Underline Row Register */
+#define CR15 0x15 /* Vertical Blank Start Register */
+#define CR16 0x16 /* Vertical Blank End Register */
+#define CR17 0x17 /* CRT Mode Control Register */
+#define CR18 0x18 /* Line Compare Register */
+#define CR22 0x22 /* Memory Data Latches Register */
+#define CR24 0x24 /* Attribute Controller Toggle Reg */
+
+
+/*-----------------------------------------------------------------------------
+ * Graphics Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define GR_PORT_LSB 0xCE /* Graphics Controller Index Port LSB */
+
+#define GR00 0x00 /* Set/Reset Register */
+#define GR01 0x01 /* Enable Set/Reset Register */
+#define GR02 0x02 /* Color Compare Register */
+#define GR03 0x03 /* Data Rotate Register */
+#define GR04 0x04 /* Read Map Select Register */
+#define GR05 0x05 /* Graphics Mode Register */
+#define GR06 0x06 /* Micsellaneous Register */
+#define RANGE_MAP_MASK BIT3 + BIT2 /* Address range to map mask */
+#define A0_BF_RANGE 000h /* Map to A0000h-BFFFFh range */
+#define GRAF_MODE BIT0 /* 1 = Grahics mode, 0 = Text mode */
+#define GR07 0x07 /* Color Don't Care Register */
+#define GR08 0x08 /* Bit Mask Register */
+#define GR10 0x10 /* Address Mapping */
+#define PAGING_TARGET BIT2 + BIT1 /* 00 = Local/Stolen, 01 = Mem mapped regs */
+#define PAGE_MODE BIT0 /* Page Map allow access to all FB mem */
+#define GR11 0x11 /* Page Selector */
+#define GR18 0x18 /* Software Flag */
+
+
+/*-----------------------------------------------------------------------------
+ * Sequencer Register Definitions
+ *---------------------------------------------------------------------------*/
+#define SR_PORT_DATA 0x3C5 /* Sequencer Data Port */
+#define SR_PORT_LSB 0xC4 /* Sequencer Index Port LSB */
+
+#define SR00 0x00 /* Reset Register */
+#define SR01 0x01 /* Clocking Mode Register */
+#define DOT_CLOCK_DIVIDE BIT3 /* Divide pixel clock by 2 */
+#define SR02 0x02 /* Plane/Map Mask Register */
+#define SR03 0x03 /* Character Font Register */
+#define SR04 0x04 /* Memory Mode Register */
+#define SR07 0x07 /* Horizontal Character Counter Reset */
+
+/*-----------------------------------------------------------------------------
+ * Platform specific PCI Config Register
+ *---------------------------------------------------------------------------*/
+#define TNC_OFFSET_VGA_MSAC 0x62
+
+/* FIXME: Core Clock should be obtained from the Message Control Register*/
+#define INTEL_OFFSET_VGA_CORECLK 0xF0
+
+/* #define INTEL_OFFSET_BRIDGE_CAPREG 0xE0 Not needed for Atom E6xx */
+
+#define PCI_GMS_MASK BIT6 + BIT5 + BIT4 /* GFX Mode Select Bits Mask */
+#define PCI_LOCAL BIT4 /* Local memory enabled */
+#define PCI_DVMT_512K BIT5 /* 512KB DVMT */
+#define PCI_DVMT_1M BIT5 + BIT4 /* 1MB DVMT */
+#define PCI_DVMT_8M BIT6 /* 8MB DVMT */
+
+#define PCI_DRB_REG 0x60 /* DRAM row boundary Register */
+#define PCI_DRC_REG 0x7C /* DRAM Controller Mode Register */
+#define PCI_DT_MASK BIT0 + BIT1 /* Select SDRAM types.
+ * = 00: Single data rate SDRAM
+ * = 01: Dual data rate SDRAM
+ * = Other: Reserved
+ */
+#define DT_SDR_SDRAM 00 /* Single data rate SDRAM */
+#define DT_DDR_SDRAM 01 /* Dual data rate SDRAM */
+
+#define PCI_ESMRAMC_REG 0x91 /* Extended System Management RAM Reg */
+#define PCI_TSEG_SZ BIT1 /* TSEG size bit */
+#define PCI_TSEG_512K 0 /* 512K TSEG */
+#define PCI_TSEG_1M BIT1 /* 1MB TSEG */
+
+#define PCI_GCLKIO_REG 0xC0 /* GMCH Clock and IO Control Register */
+#define PCI_AGP_Bit BIT9 /* AGP/DVO Mux Select:
+ * = 0, DVO/ZV
+ * = 1, AGP
+ */
+#define PCI_GMCHCFG_REG 0xC6 /* GMCH Configuration Register */
+#define PCI_SMFREQ_MASK BIT10 + BIT11
+ /* System Mem Frequency Select
+ * = 00: Intel Reserved
+ * = 01: System Memory Frequency is 166Mhz (DDR333) - Intel Reserved
+ * = 10: System Memory Frequency is 133Mhz (SDR133, DDR266)
+ * = 11: System Memory Frequency is 100Mhz (DDR200)
+ */
+#define SYS_MEM_FREQ_166 1 /* System Memory Frequency is 166Mhz */
+#define SYS_MEM_FREQ_133 2 /* System Memory Frequency is 133Mhz */
+#define SYS_MEM_FREQ_100 3 /* System Memory Frequency is 100Mhz */
+#define PCI_SMFREQ_POS 10 /* System Memory Frequency position */
+
+#define PCI_CONFIG_LMINT 0xE0
+#define PREALLOCATED_SIZE (8 * 1024 * 1024)
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG 0x3DA /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA /* Feature Control Register (Read) */
+#define MSR_PORT 0x3C2 /* Miscellaneous Output Port */
+#define MSR_PORT_LSB 0xC2 /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT 0x3CC /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00 0x3C2 /* Input Status Register 0 */
+#define STATUS_REG_01 0x3DA /* Input Status Register 1 */
+#define STATUS_REG_01_MONO 0x3BA /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK 0x3C6 /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX 0x3C7 /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE 0x3C7 /* Color Palette State Register */
+#define DAC_WRITE_INDEX 0x3C8 /* Color Palette Index Register */
+#define DAC_DATA_REG 0x3C9 /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Memory mapped I/O Registers Definitions
+ *---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Instruction and Interrupt Control Registers (01000h - 02FFFh)
+ *---------------------------------------------------------------------------*/
+#define PGTBL_CTL 0x02020 /* Page Table Control Register */
+#define HWS_PGA 0x02080 /* Hardware Status Page Address register */
+#define HWSTAM 0x02098 /* Hardware Status Mask */
+#define SCPD0 0x0209C /* Scratch Pad 0 (Debug) */
+#define IER 0x020A0 /* Interrupt Enable */
+#define IIR 0x020A4 /* Interrupt Identity */
+#define IMR 0x020A8 /* Interrupt Mask */
+#define ISR 0x020AC /* Interrupt Status */
+#define EIR 0x020B0 /* Error Identity */
+#define EMR 0x020B4 /* Error Mask */
+#define ESR 0x020B8 /* Error Status */
+#define FW_BLC_SELF 0x020E0 /* Display FIFO Watermark */
+#define MI_ARB_STATE 0x020E4 /* Memory Interface Arbitration State */
+#define G_DEBUG 0x020FC /* G-UNIT Debug enable register */
+
+#if 0
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (02000h - 031FFh)
+ * --------------------------------------------------------------------------*/
+#define FENCE0 0x02000 /* Fence table registers */
+#define FENCE1 0x02004
+#define FENCE2 0x02008
+#define FENCE3 0x0200C
+#define FENCE4 0x02010
+#define FENCE5 0x02014
+#define FENCE6 0x02018
+#define FENCE7 0x0201C
+#define FENCE8 0x03000
+#define FENCE9 0x03004
+#define FENCE10 0x03008
+#define FENCE11 0x0300C
+#define FENCE12 0x03010
+#define FENCE13 0x03014
+#define FENCE14 0x03018
+#define FENCE15 0x0301C
+#endif
+/*-----------------------------------------------------------------------------
+ * FIXME: For TNC, we were not able to find specs detailing the FENCE registers
+ * Use the GN4 FENCE Registers for the time being as a placeholder till we can
+ * nail down the FENCE registers
+ * --------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (03000h - 031FFh)
+ *
+ * The FENCE registers are now 64-bits but we can only read/write 32-bits
+ * at a time. As a result, each register has aliases for the whole 64-bits,
+ * the low DWORD, and the high DWORD.
+ *
+ * This is important for restoring the registers, since we must always write
+ * the high DWORD first.
+ * --------------------------------------------------------------------------*/
+#define FENCE0 0x03000 /* Fence table registers */
+#define FENCE0l 0x03000
+#define FENCE0h 0x03004
+#define FENCE1 0x03008
+#define FENCE1l 0x03008
+#define FENCE1h 0x0300C
+#define FENCE2 0x03010
+#define FENCE2l 0x03010
+#define FENCE2h 0x03014
+#define FENCE3 0x03018
+#define FENCE3l 0x03018
+#define FENCE3h 0x0301C
+#define FENCE4 0x03020
+#define FENCE4l 0x03020
+#define FENCE4h 0x03024
+#define FENCE5 0x03028
+#define FENCE5l 0x03028
+#define FENCE5h 0x0302C
+#define FENCE6 0x03030
+#define FENCE6l 0x03030
+#define FENCE6h 0x03034
+#define FENCE7 0x03038
+#define FENCE7l 0x03038
+#define FENCE7h 0x0303C
+#define FENCE8 0x03040
+#define FENCE8l 0x03040
+#define FENCE8h 0x03044
+#define FENCE9 0x03048
+#define FENCE9l 0x03048
+#define FENCE9h 0x0304C
+#define FENCE10 0x03050
+#define FENCE10l 0x03050
+#define FENCE10h 0x03054
+#define FENCE11 0x03058
+#define FENCE11l 0x03058
+#define FENCE11h 0x0305C
+#define FENCE12 0x03060
+#define FENCE12l 0x03060
+#define FENCE12h 0x03064
+#define FENCE13 0x03068
+#define FENCE13l 0x03068
+#define FENCE13h 0x0306C
+#define FENCE14 0x03070
+#define FENCE14l 0x03070
+#define FENCE14h 0x03074
+#define FENCE15 0x03078
+#define FENCE15l 0x03078
+#define FENCE15h 0x0307C
+
+/*-----------------------------------------------------------------------------
+ * MISC I/0 Contol Register ( 05000h - 05FFFh )
+ *---------------------------------------------------------------------------*/
+#define IO_OFF 0x05000 /* Register group offset */
+
+#define IO00 0x05000 /* Hsync / Vsync control register */
+#define GPIO0 0x05010 /* GPIO register 0 (DDC1) */
+#define DDC1_SCL_PIN GPIO0_SCL_PIN /* DDC1 SCL GPIO pin # */
+#define DDC1_SDA_PIN GPIO0_SDA_PIN /* DDC1 SDA CPIO pin # */
+#define GPIO1 0x05014 /* GPIO register 1 (I2C) */
+#define I2C_SCL_PIN GPIO1_SCL_PIN /* I2C SCL GPIO pin # */
+#define I2C_SDA_PIN GPIO1_SDA_PIN /* I2C SDA CPIO pin # */
+#define GPIO2 0x05018 /* GPIO register 2 (DDC2) */
+#define DDC2_SCL_PIN GPIO2_SCL_PIN /* DDC2 SCL GPIO pin # */
+#define DDC2_SDA_PIN GPIO2_SDA_PIN /* DDC2 SDA CPIO pin # */
+#define GPIO3 0x0501C /* GPIO register 3 (AGP mux DVI DDC) */
+#define GPIO4 0x05020 /* GPIO register 4 (AGP mux I2C) */
+#define GPIO5 0x05024 /* GPIO register 5 (AGP mux DDC2/I2C) */
+
+#define GPIOPIN0 GPIO0
+#define GPIOPIN1 GPIO0+1
+#define GPIOPIN2 GPIO1
+#define GPIOPIN3 GPIO1+1
+#define GPIOPIN4 GPIO2
+#define GPIOPIN5 GPIO2+1
+#define GPIOPIN6 GPIO3
+#define GPIOPIN7 GPIO3+1
+#define GPIOPIN8 GPIO4
+#define GPIOPIN9 GPIO4+1
+#define GPIOPIN10 GPIO5
+#define GPIOPIN11 GPIO5+1
+#define GPIOPINMAX 12
+
+#define GMBUS0 0x5100 /* GMBUS clock/device select register */
+#define GMBUS1 0x5104 /* GMBUS command/status register */
+#define GMBUS2 0x5108 /* GMBUS status register */
+#define GMBUS3 0x510c /* GMBUS data buffer register */
+#define GMBUS4 0x5110 /* GMBUS REQUEST_INUSE register */
+#define GMBUS5 0x5120 /* GMBUS 2-Byte Index register */
+#define GMBUS6 0x5124 /* GMBUS Clock divider */
+
+/* GMBUS1 Bits */
+#define SW_CLR_INT BIT31
+#define SW_RDY BIT30
+#define ENT BIT29
+#define STO BIT27
+#define ENIDX BIT26
+#define STA BIT25
+
+/* GMBUS2 Bits */
+#define INUSE BIT15
+#define HW_WAIT BIT14
+#define HW_TMOUT BIT13
+#define HW_INT BIT12
+#define HW_RDY BIT11
+#define HW_BUS_ERR BIT10
+#define GA BIT9
+
+/*-----------------------------------------------------------------------------
+ * Clock Control and PM Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define VGA0_DIVISOR 0x06000 /* VGA 0 Divisor */
+#define VGA1_DIVISOR 0x06004 /* VGA 1 Divisor */
+#define VGA_PD 0x06010 /* VGA Post Divisor Select */
+#define DPLLAMD 0x0601C /* Display PLL A SDVO Multiplier/Divisor */
+#define DPLLBMD 0x06020 /* Display PLL B SDVO Multiplier/Divisor */
+
+/*-----------------------------------------------------------------------------
+ * DPLL A Control Register ( 0F000h - 0FFFFh )
+ *---------------------------------------------------------------------------*/
+#define DPLLACNTR 0x0F014 /* Display PLL A Control */
+#define FPA0 0x0F040 /* DPLL A Divisor 0 */
+#define FPA1 0x0F044 /* DPLL A Divisor 1 */
+#define DPLL_TEST 0x0F06C /* DPLLA Test Register */
+
+/*-----------------------------------------------------------------------------
+ * DPLL B Control Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define DPLLBCNTR 0x06018 /* Display PLL B Control */
+#define FPB0 0x06048 /* DPLL B Divisor 0 */
+#define FPB1 0x0604C /* DPLL B Divisor 1 */
+#define TNC_DPLL_TEST 0x0606C /* DPLL A and DPLL B test register */
+
+#define DREFCLK 0x0
+#define TVCLKINBC 0x4000
+#define CLOCK_2X 0x40000000
+
+#define P2D_CG_DIS 0x06200 /* Clock Gating Disable */
+/* Not available in Atom E6xx */
+/* #define P3D_CG_DIS 0x06204 */ /* Clock Gating Disable */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Palette Register Definitions (0A000h - 0AFFFh)
+ *---------------------------------------------------------------------------*/
+#define DPALETTE_A 0x0A000 /* Display Pipe A Palette */
+#define DPALETTE_B 0x0A800 /* Display Pipe B Palette */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline / Port Register Definitions (60000h - 6FFFFh)
+ *---------------------------------------------------------------------------*/
+#define DP_OFFSET 0x60000 /* register group offset */
+#define PIPEA_TIMINGS 0x60000
+#define HTOTAL_A 0x60000 /* Pipe A Horizontal Total Register */
+#define ACTIVE_DISPLAY 0x7FF /* bit [ 10:0 ] */
+#define HBLANK_A 0x60004 /* Pipe A Horizontal Blank Register */
+#define HSYNC_A 0x60008 /* Pipe A Horizontal Sync Register */
+#define VTOTAL_A 0x6000C /* Pipe A Vertical Total Register */
+#define VBLANK_A 0x60010 /* Pipe A Vertical Blank Register */
+#define VSYNC_A 0x60014 /* Pipe A Vertical Sync Register */
+#define PIPEASRC 0x6001C /* Pipe A Source Image Size Register */
+#define BCLRPAT_A 0x60020 /* Pipe A Border Color Pattern Register */
+#define CRCCTRLREDA 0x60050 /* Pipe A CRC Red Control Register */
+#define CRCCTRLGREENA 0x60054 /* Pipe A CRC Green Control Register */
+#define CRCCTRLBLUEA 0x60058 /* Pipe A CRC Blue Control Register */
+#define CRCCTRLRESA 0x6005C /* Pipe A CRC Alpha Control Register */
+
+/*-----------------------------------------------------------------------------
+ * Pipe B registers are shared between Device 2 and Device 3
+ * Atom E6xx silicon design specifies that both device 2 and device 3
+ * Pipe B registers need to be set sequencially. Device 2, followed by
+ * Device 3
+ *---------------------------------------------------------------------------*/
+#define PIPEB_TIMINGS 0x61000
+#define HTOTAL_B 0x61000 /* Pipe B Horizontal Total Register */
+#define HBLANK_B 0x61004 /* Pipe B Horizontal Blank Register */
+#define HSYNC_B 0x61008 /* Pipe B Horizontal Sync Register */
+#define VTOTAL_B 0x6100C /* Pipe B Vertical Total Register */
+#define VBLANK_B 0x61010 /* Pipe B Vertical Blank Register */
+#define VSYNC_B 0x61014 /* Pipe B Vertical Sync Register */
+#define PIPEBSRC 0x6101C /* Pipe B Source Image Size Register */
+#define BCLRPAT_B 0x61020 /* Pipe B Border Color Pattern Register */
+#define VSYNCSHIFT_B 0x61028 /* Pipe B Vertical Sync Shift Register */
+#define CRCCTRLREDB 0x61050 /* Pipe B CRC Red Control Register */
+#define CRCCTRLGREENB 0x61054 /* Pipe B CRC Green Control Register */
+#define CRCCTRLBLUEB 0x61058 /* Pipe B CRC Blue Control Register */
+#define CRCCTRLRESB 0x6105C /* Pipe B CRC Alpha Control Register */
+
+/* These registers are in Device 3 */
+#define PORT_HPLUG_EN 0x61110 /* Port Hot Plug Enable */
+#define PORT_HPLUG_STAT 0x61114 /* Port Hot Plug Status */
+#define SDVOBCNTR 0x61140 /* Digital Display Port B Control */
+#define LVDSCNTR 0x61180 /* Digital Display Port Control */
+#define SDVO_BUFF_CTRL_REG 0x61170 /* SDVO Buffer Control */
+
+/* Panel Power Sequencing */
+#define LVDS_PNL_PWR_STS 0x61200 /* LVDS Panel Power Status Register */
+#define LVDS_PNL_PWR_CTL 0x61204 /* LVDS Panel Power Control Register */
+#define PP_ON_DELAYS 0x61208 /* Panel Power On Sequencing Delays */
+#define PP_OFF_DELAYS 0x6120C /* Panel Power Off Sequencing Delays */
+#define PP_DIVISOR 0x61210 /* Panel Power Cycle Delay and Reference */
+
+/* Panel Fitting */
+#define PFIT_CONTROL 0x61230 /* Panel Fitting Control */
+#define PFIT_PGM_RATIOS 0x61234 /* Programmed Panel Fitting Ratios */
+
+/* Backlight control */
+#define BLC_PWM_CTL2 0x61250 /* Backlight PWM Control 2 */
+#define BLC_PWM_CTL 0x61254 /* Backlight PWM Control */
+#define BLM_HIST_CTL 0x61260 /* Image BLM Histogram Control */
+
+#define PORT_EN BIT31
+#define PORT_PIPE_SEL BIT30
+#define PORT_PIPE_SEL_POS 30
+#define PORT_PIPE_A 0 /* 0 = Pipe A */
+#define PORT_PIPE_B BIT30 /* 1 = Pipe B */
+#define STALL_MASK BIT29 + BIT28
+#define STALL_ENABLE BIT28
+#define SYNC_MASK BIT15 + BIT11 + BIT10 + BIT4 + BIT3
+#define SYNC_POLARITY BIT15 /* 1 = Use VGA register */
+#define VSYNC_OUTPUT BIT11
+#define HSYNC_OUTPUT BIT10
+#define VSYNC_POLARITY BIT4
+#define HSYNC_POLARITY BIT3
+#define FP_DATA_ORDER BIT14
+#define SUBDATA_ORDER BIT6
+#define BORDER_EN BIT7
+#define DISPLAY_EN BIT2
+#define INTERLACED_BIT 0x00100000
+#define RGBA_BITS 0x00030000
+
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline A Register ( 70000h - 70024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEA_SCANLINE_COUNT 0x70000 /* Pipe A Scan Line Count (RO) */
+#define PIPEA_SCANLINE_COMPARE 0x70004 /* Pipe A SLC Range Compare (RO) */
+#define PIPEA_CONF 0x70008 /* Pipe A Configuration */
+#define PIPE_STATUS_OFFSET 0x1C
+#define PIPEAGCMAXRED 0x70010 /* Pipe A Gamma Correct. Max Red */
+#define PIPEAGCMAXGRN 0x70014 /* Pipe A Gamma Correct. Max Green */
+#define PIPEAGCMAXBLU 0x70018 /* Pipe A Gamma Correct. Max Blue */
+#define PIPEA_STAT 0x70024 /* Pipe A Display Status */
+#define PIPEA_DISP_ARB_CTRL 0x70030 /* Display Arbitration Control */
+#define FW_1 0x70034
+#define FW_2 0x70038
+#define FW_3 0x7003C
+#define PIPEA_FRAME_HIGH 0x70040 /* Pipe A Frame Count High */
+#define PIPEA_FRAME_PIXEL 0x70044 /* Pipe A Frame Cnt Low & pixel count */
+#define FW_4 0x70050
+#define FW_5 0x70054
+#define FW_6 0x70058
+
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline B Register ( 71000h - 71024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEB_SCANLINE_COUNT 0x71000 /* Pipe B Disp Scan Line Count Reg */
+#define PIPEB_SCANLINE_COMPARE 0x71004 /* Pipe B Disp Scan Line Cnt Range Cmp */
+#define PIPEB_CONF 0x71008 /* Pipe B Pixel Pipeline Config Reg */
+#define PIPEBGCMAXRED 0x71010 /* Pipe B Gamma Correct. Max Red */
+#define PIPEBGCMAXGRN 0x71014 /* Pipe B Gamma Correct. Max Green */
+#define PIPEBGCMAXBLU 0x71018 /* Pipe B Gamma Correct. Max Blue */
+#define PIPEB_STAT 0x71024 /* Display Status Select Register */
+#define PROG_STALL 0x6102C /* Programmable cDVO Stall Register */
+#define PIPEB_FRAME_HIGH 0x71040 /* Pipe B Frame Count High */
+#define PIPEB_FRAME_PIXEL 0x71044 /* Pipe B Frame Cnt Low and pixel cnt */
+
+
+#define VBLANK_EVN_STS_EN BIT20
+#define VBLANK_ODD_STS_EN BIT21
+#define VBLANK_EVN_STS BIT4
+#define VBLANK_ODD_STS BIT5
+
+
+/* following bit flag defs can be re-used for Pipe-B */
+#define PIPE_ENABLE BIT31
+#define PIPE_LOCK BIT29
+#define GAMMA_MODE BIT24
+#define HOT_PLUG_EN BIT26
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical sync interrupts.
+ */
+#define VSYNC_STS_EN BIT25
+#define INTERLACE_EN BIT23|BIT22
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical blank interrupts.
+ */
+#define VBLANK_STS_EN BIT17
+#define HOT_PLUG_STS BIT10
+#define VSYNC_STS BIT9
+#define VBLANK_STS BIT1
+/* The following are "sticky" status bits in the PIPE{A|B}_STAT register. They
+ * are cleared by writing a 1 to them. Theres is code that reads a
+ * PIPE{A|B}_STAT register into a variable, then modifies the variable, and
+ * writes it back to the register. These bits should be treated specially, so
+ * as not to inadvertantly clear the status bits, so that other code looking
+ * for those bits to be set won't miss it.
+ */
+#define PIPESTAT_STS_BITS ((unsigned long) BIT31 | BIT13 | BIT12 | BIT11 | \
+ VSYNC_STS | BIT8 | BIT5 | BIT4 | VBLANK_STS | BIT0)
+
+/*-----------------------------------------------------------------------------
+ * cDVO Registers
+ * --------------------------------------------------------------------------*/
+#define CDVO_CTRL 0x07000 /* cDVO Control Register */
+#define CDVO_SLEW_RATE 0x07004 /* cDVO Slew Rate Register */
+#define CDVO_STRENGTH 0x07008 /* cDVO Strength Register */
+#define CDVO_RCOMP_UPDATE 0x0700C /* cDVO RCOMP update Register */
+
+/*-----------------------------------------------------------------------------
+ * TNC_SDVOFAM Registers
+ * --------------------------------------------------------------------------*/
+#define DPLL_ANACORE_CTRL 0x06300
+#define DPLL_MISC 0x06304
+#define DPLL_MONITOR 0x06308
+#define DPLL_MONITOR2 0x0630C
+#define DPLL_TEST_COMPARATOR 0x06310
+#define SDVOB_TX_LSKEW 0x06314
+
+/*-----------------------------------------------------------------------------
+ * Hardware Cursor Register Definitions (70080h - 7009Ch)
+ *---------------------------------------------------------------------------*/
+#define CUR_A_CNTR 0x70080 /*Cursor A Control */
+#define CUR_B_CNTR 0x700C0
+#define CUR_BASE_OFFSET 0x4
+#define CUR_POS_OFFSET 0x8
+#define CUR_PAL0_OFFSET 0x10
+#define CUR_PAL1_OFFSET 0x14
+#define CUR_PAL2_OFFSET 0x18
+#define CUR_PAL3_OFFSET 0x1C
+
+/* Define these for ease of reference */
+#define CURSOR_A_BASE CUR_A_CNTR + CUR_BASE_OFFSET
+#define CURSOR_A_POS CUR_A_CNTR + CUR_POS_OFFSET
+#define CURSOR_A_PAL0 CUR_A_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_A_PAL1 CUR_A_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_A_PAL2 CUR_A_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_A_PAL3 CUR_A_CNTR + CUR_PAL3_OFFSET
+#define CURSOR_B_BASE CUR_B_CNTR + CUR_BASE_OFFSET
+#define CURSOR_B_POS CUR_B_CNTR + CUR_POS_OFFSET
+#define CURSOR_B_PAL0 CUR_B_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_B_PAL1 CUR_B_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_B_PAL2 CUR_B_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_B_PAL3 CUR_B_CNTR + CUR_PAL3_OFFSET
+
+/*-----------------------------------------------------------------------------
+ * Display Plane A Register Definitions (70180h - 70188h)
+ *---------------------------------------------------------------------------*/
+#define DSPAAFLIP 0x7017C
+#define DSPACNTR 0x70180 /* Display Plane A */
+#define DSPALINOFF 0x70184 /* Display A Linear Offset */
+#define DSPASTRIDE 0x70188 /* Display A Stride */
+#define DSPAKEYVAL 0x70194 /* Sprite color key value */
+#define DSPAKEYMASK 0x70198 /* Sprite color key mask */
+#define DSPASURF 0x7019C /* Display A Suface base address */
+#define DSPATILEOFF 0x701A4 /* Display A Tiled Offset */
+
+/*-----------------------------------------------------------------------------
+ * Display Plane B Register Definitions (71180h - 71188h)
+ *---------------------------------------------------------------------------*/
+#define DSPBFLIP 0x7117C /* Display B Async flip */
+#define DSPBCNTR 0x71180 /* Display Plane B */
+#define DSPBLINOFF 0x71184 /* Display B Linear Offset */
+#define DSPBSTRIDE 0x71188 /* Display B Stride */
+#define DSPBKEYVAL 0x71194 /* Sprite color key value */
+#define DSPBKEYMASK 0x71198 /* Sprite color key mask */
+#define DSPBSURF 0x7119C /* Display B Suface base address */
+#define DSPBTILEOFF 0x711A4 /* Display B Tiled Offset */
+
+/*-----------------------------------------------------------------------------
+ * Source Format Definition for DSPxCNTR
+ *---------------------------------------------------------------------------*/
+#define DSPxCNTR_ARGB_8888 0x1C000000
+#define DSPxCNTR_RGB_8888 0x18000000
+#define DSPxCNTR_RGB_565 0x14000000
+#define DSPxCNTR_RGB_555 0x10000000
+#define DSPxCNTR_RGB_8 0x08000000
+#define DSPxCNTR_SRC_FMT_MASK 0x3C000000 /*mask for above*/
+
+/*-----------------------------------------------------------------------------
+ * Display Plane C Register Definitions (72180h - 72188h)
+ *---------------------------------------------------------------------------*/
+#define DSPCCNTR 0x72180 /* Display Plane C */
+#define DSPCLINOFF 0x72184 /* Display C Linear Offset */
+#define DSPCSTRIDE 0x72188 /* Display C Stride */
+#define DSPCPOS 0x7218C /* Display C Position */
+#define DSPCSIZE 0x72190 /* Display C Size */
+#define DSPCKEYMINVAL 0x72194 /* Sprite color key Min */
+#define DSPCKEYMASK 0x72198 /* Sprite color key mask */
+#define DSPCSURF 0x7219C /* Display C Suface base address */
+#define DSPCKEYMAXVAL 0x721A0 /* Display C Sprint color key Max */
+#define DSPCTILEOFF 0x721A4 /* Display C Tiled Offset */
+#define DSPCCONTALPHA 0x721A8 /* Display C Constant Alpha */
+
+#define DCLRC0 0x721D0 /* Display C Color Correction 0 */
+#define DCLRC1 0x721D4 /* Display C Color Correction 1 */
+#define DPYC_GAMC5 0x721E0 /* Display C Gamma Correction 5 */
+#define DPYC_GAMC4 0x721E4 /* Display C Gamma Correction 4 */
+#define DPYC_GAMC3 0x721E8 /* Display C Gamma Correction 3 */
+#define DPYC_GAMC2 0x721EC /* Display C Gamma Correction 2 */
+#define DPYC_GAMC1 0x721F0 /* Display C Gamma Correction 1 */
+#define DPYC_GAMC0 0x721F4 /* Display C Gamma Correction 0 */
+
+#define PLANE_ENABLE BIT31
+#define GAMMA_ENABLE BIT30
+#define BPP_MASK BIT29 + BIT28 + BIT27 + BIT26
+#define BPP_POS 26
+#define STEREO_ENABLE BIT25
+#define PIPE_SEL BIT24
+#define PIPE_SEL_POS 24
+#define PIXEL_MULTIPLY BIT21 + BIT20
+#define STEREO_POLARITY BIT18
+
+/* Common offsets for all Display Pipeline registers */
+#define DSP_LINEAR_OFFSET 0x04 /* Offset from the control reg */
+#define DSP_STRIDE_OFFSET 0x08 /* Offset from the control reg */
+#define DSP_SIZE_OFFSET 0x10 /* Offset from the control reg */
+#define DSP_START_OFFSET 0x1c /* Offset from the control reg */
+#define DSP_TOFF_OFFSET 0x24 /* Offset from the control reg */
+
+/*-----------------------------------------------------------------------------
+ * VGA Display Plane Control Register Definitions (71400h)
+ *---------------------------------------------------------------------------*/
+#define VP00 0x71400
+#define VGACNTRL 0x71400 /* VGA Display Plane Control Register */
+#define VGA_DOUBLE BIT30
+#define VGA_PIPE BIT29
+#define VGA_CENTER_MASK BIT25 + BIT24
+#define VGA_CENTER_1 BIT25
+#define VGA_CENTER_0 BIT24
+#define VGA_PAL_READ BIT23
+#define VGA_PAL_MASK BIT22 + BIT21
+#define VGA_PALA_DISABLE BIT22
+#define VGA_PALB_DISABLE BIT21
+#define DAC_8_BIT BIT20
+#define VGA_8_DOT BIT18
+
+#define ADD_ID 0x71408 /* ADD Card ID Register*/
+
+/*-----------------------------------------------------------------------------
+ * Overlay Plane Control Register Definitions (30000h)
+ *---------------------------------------------------------------------------*/
+#define OVADD 0x30000 /* Overlay Control */
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags 00h - 0Fh
+ *---------------------------------------------------------------------------*/
+#define DSP_CHICKENBITS 0x70400 /* Chicken Bit */
+#define SWFABASE 0x70410 /* Software flags A Base Addr */
+#define SWF00 0x70410
+#define SWF01 0x70414
+#define SWF02 0x70418
+#define SWF03 0x7041C
+#define SWF04 0x70420
+#define SWF05 0x70424
+#define SWF06 0x70428
+#define SWF07 0x7042C
+#define SWF08 0x70430
+#define SWF09 0x70434
+#define SWF0A 0x70438
+#define SWF0B 0x7043C
+#define SWF0C 0x70440
+#define SWF0D 0x70444
+#define SWF0E 0x70448
+#define SWF0F 0x7044C
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags 10h - 1Fh
+ *---------------------------------------------------------------------------*/
+#define SWFBBASE 0x71410 /* Software flags B Base Addr */
+#define SWF10 0x71410
+#define SWF11 0x71414
+#define SWF12 0x71418
+#define SWF13 0x7141C
+#define SWF14 0x71420
+#define SWF15 0x71424
+#define SWF16 0x71428
+#define SWF17 0x7142C
+#define SWF18 0x71430
+#define SWF19 0x71434
+#define SWF1A 0x71438
+#define SWF1B 0x7143C
+#define SWF1C 0x71440
+#define SWF1D 0x71444
+#define SWF1E 0x71448
+#define SWF1F 0x7144C
+
+#define SWF30 0x72414
+#define SWF31 0x72418
+#define SWF32 0x7241C
+
+/*-----------------------------------------------------------------------------
+ * Software Flag Registers (71410h - 71428h)
+ *---------------------------------------------------------------------------*/
+/* Map old software flag names to their new Gen4 names */
+#define SF00 SWF10
+#define SF01 SWF11
+#define SF02 SWF12
+#define SF03 SWF13
+#define SF04 SWF14
+#define SF05 SWF15
+#define SF06 SWF16
+
+/*-----------------------------------------------------------------------------
+ * GPIO Control Registers(05000h - 05023h)
+ *---------------------------------------------------------------------------*/
+/* GPIO registers 0x0500 - 0x500C is reserved */
+#define GPIOCTL_1 0x05014
+#define GPIOCTL_2 0x05018
+#define GPIOCTL_4 0x05020
+
+/*-----------------------------------------------------------------------------
+ * Scratch register to be used as additional parameter in SMI
+ *---------------------------------------------------------------------------*/
+#define SCRATCH_SWF6 0x71428
+
+/*-----------------------------------------------------------------------------
+ * Miscellaneous registers
+ ----------------------------------------------------------------------------*/
+#define HW_ST_PAGE_ADDR 0x02080
+
+/*-----------------------------------------------------------------------------
+ * GMBUS : I2C Bus Types
+ ----------------------------------------------------------------------------*/
+//#define GMBUS_ANALOG_DDC 1
+
+//#define GMBUS_INT_LVDS_DDC 2
+#define I2C_INT_LVDS_DDC 2
+
+#define GMBUS_DVO_REG 3
+
+#define GMBUS_DVOB_DDC 4
+//#define GMBUS_DVOC_DDC 5
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS GPIO Bit Bashing. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN 0x20
+#define RGIO 0x24
+#define RGLVL 0x28
+#define RGTPE 0x2C
+#define RGTNE 0x30
+#define RGGPE 0x34
+#define RGSMI 0x38
+#define RGTS 0x3C
+
+
+#endif /* _REGS_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h b/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
new file mode 100644
index 0000000..c43d490
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
@@ -0,0 +1,36 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sgx.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * These are the defines specific to the SGX engine code.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _TNC_SGX_H
+#define _TNC_SGX_H
+
+#include<plb/sgx.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
new file mode 100644
index 0000000..b32aea2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is an inter-module header file for manipulating the 3D
+ * State variables.
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * This is referenced from Napa code. For Poulsbo, the HW spec may be
+ * different. Be ready for the new change.
+ */
+
+#ifndef _TNC_STATE3D_H
+#define _TNC_STATE3D_H
+
+#include <plb/state3d.h>
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
new file mode 100644
index 0000000..fd5e628
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
@@ -0,0 +1,38 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is an inter-module header file for manipulating the 3D
+ * State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE3D_TNC_H
+#define _STATE3D_TNC_H
+
+#include <plb/state3d_plb.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/topaz.h b/drivers/gpu/drm/emgd/emgd/include/topaz.h
new file mode 100755
index 0000000..b4057f4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/topaz.h
@@ -0,0 +1,212 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: topaz.h
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * These are the defines specific to the Topaz engine code.
+ *-----------------------------------------------------------------------------
+ */
+extern unsigned long _topaz_base;
+#define TOPAZ_BASE _topaz_base
+
+#ifndef _TOPAZ_H
+#define _TOPAZ_H
+
+/* MTX registers */
+#define TNC_TOPAZ_MTX_ENABLE (TOPAZ_BASE + 0x0000)
+#define TNC_TOPAZ_MTX_STATUS (TOPAZ_BASE + 0x0008)
+#define TNC_TOPAZ_MTX_KICK (TOPAZ_BASE + 0x0080)
+#define TNC_TOPAZ_MTX_KICKI (TOPAZ_BASE + 0x0088)
+#define TNC_TOPAZ_MTX_FAULT0 (TOPAZ_BASE + 0x0090)
+#define TNC_TOPAZ_MTX_REGISTER_READ_WRITE_DATA (TOPAZ_BASE + 0x00f8)
+#define TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST (TOPAZ_BASE + 0x00fc)
+#define TNC_TOPAZ_MTX_RAM_ACCESS_DATA_EXCHANGE (TOPAZ_BASE + 0x0100)
+#define TNC_TOPAZ_MTX_RAM_ACCESS_DATA_TRANSFER (TOPAZ_BASE + 0x0104)
+#define TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL (TOPAZ_BASE + 0x0108)
+#define TNC_TOPAZ_MTX_RAM_ACCESS_STATUS (TOPAZ_BASE + 0x010c)
+#define TNC_TOPAZ_MTX_SOFT_RESET (TOPAZ_BASE + 0x0200)
+#define TNC_TOPAZ_MTX_SYSC_CDMAC (TOPAZ_BASE + 0x0340)
+#define TNC_TOPAZ_MTX_SYSC_CDMAA (TOPAZ_BASE + 0x0344)
+#define TNC_TOPAZ_MTX_SYSC_CDMAS0 (TOPAZ_BASE + 0x0348)
+#define TNC_TOPAZ_MTX_SYSC_CDMAS1 (TOPAZ_BASE + 0x034c)
+#define TNC_TOPAZ_MTX_SYSC_CDMAT (TOPAZ_BASE + 0x0350)
+/* Topaz Registers */
+#define TNC_START_OFFSET (0x02000)
+#define TNC_IMG_TOPAZ_REG_BASE (TOPAZ_BASE + TNC_START_OFFSET)
+#define TNC_TOPAZ_IMG_TOPAZ_SRST (TNC_IMG_TOPAZ_REG_BASE + 0x0000)
+#define TNC_TOPAZ_IMG_TOPAZ_INTSTAT (TNC_IMG_TOPAZ_REG_BASE + 0x0004)
+#define TNC_TOPAZ_IMG_TOPAZ_INTENAB (TNC_IMG_TOPAZ_REG_BASE + 0x0008)
+#define TNC_TOPAZ_IMG_TOPAZ_INTCLEAR (TNC_IMG_TOPAZ_REG_BASE + 0x000c)
+#define TNC_TOPAZ_IMG_TOPAZ_MAN_CLK_GATE (TNC_IMG_TOPAZ_REG_BASE + 0x0010)
+#define TNC_TOPAZ_IMG_TOPAZ_AUTO_CLK_GATE (TNC_IMG_TOPAZ_REG_BASE + 0x0014)
+#define TNC_TOPAZ_IMG_TOPAZ_RSVD0 (TNC_IMG_TOPAZ_REG_BASE + 0x03b0)
+#define TNC_TOPAZ_TOPAZ_MTX_C_RATIO (TNC_IMG_TOPAZ_REG_BASE + 0x0018)
+#define TNC_TOPAZ_IMG_TOPAZ_CORE_ID (TNC_IMG_TOPAZ_REG_BASE + 0x03c0)
+#define TNC_TOPAZ_IMG_TOPAZ_CORE_REV (TNC_IMG_TOPAZ_REG_BASE + 0x03d0)
+#define TNC_TOPAZ_IMG_TOPAZ_CORE_DES1 (TNC_IMG_TOPAZ_REG_BASE + 0x03e0)
+#define TNC_TOPAZ_IMG_TOPAZ_CORE_DES2 (TNC_IMG_TOPAZ_REG_BASE + 0x03f0)
+#define TNC_TOPAZ_MMU_STATUS (TNC_IMG_TOPAZ_REG_BASE + 0x001c)
+#define TNC_TOPAZ_MMU_MEM_REQ (TNC_IMG_TOPAZ_REG_BASE + 0x0020)
+#define TNC_TOPAZ_MMU_CONTROL0 (TNC_IMG_TOPAZ_REG_BASE + 0x0024)
+#define TNC_TOPAZ_MMU_CONTROL1 (TNC_IMG_TOPAZ_REG_BASE + 0x0028)
+#define TNC_TOPAZ_MMU_DIR_LIST_BASE0 (TNC_IMG_TOPAZ_REG_BASE + 0x0030)
+#define TNC_TOPAZ_MMU_TILE0 (TNC_IMG_TOPAZ_REG_BASE + 0x0034)
+#define TNC_TOPAZ_MMU_BANK_INDEX (TNC_IMG_TOPAZ_REG_BASE + 0x0038)
+#define TNC_TOPAZ_MTX_DEBUG (TNC_IMG_TOPAZ_REG_BASE + 0x003c)
+#define TNC_TOPAZ_IMG_TOPAZ_DMAC_MODE (TNC_IMG_TOPAZ_REG_BASE + 0x0040)
+#define TNC_TOPAZ_RTM (TNC_IMG_TOPAZ_REG_BASE + 0x0044)
+#define TNC_TOPAZ_RTM_VALUE (TNC_IMG_TOPAZ_REG_BASE + 0x0048)
+/* MVEA Registers */
+#define TNC_MVEA_START_OFFSET (0x03000)
+#define TNC_IMG_MVEA_REG_BASE (TOPAZ_BASE + TNC_MVEA_START_OFFSET)
+#define TNC_TOPAZ_IMG_MVEA_SRST (TNC_IMG_MVEA_REG_BASE + 0x0000)
+#define TNC_TOPAZ_IMG_MVEA_INTSTAT (TNC_IMG_MVEA_REG_BASE + 0x0004)
+#define TNC_TOPAZ_IMG_MVEA_INTENAB (TNC_IMG_MVEA_REG_BASE + 0x0008)
+#define TNC_TOPAZ_IMG_MVEA_INTCLEAR (TNC_IMG_MVEA_REG_BASE + 0x000c)
+#define TNC_TOPAZ_IMG_MVEA_INT_COMB_SEL (TNC_IMG_MVEA_REG_BASE + 0x0010)
+#define TNC_TOPAZ_IMG_MVEA_RSVD0 (TNC_IMG_MVEA_REG_BASE + 0x03b0)
+#define TNC_TOPAZ_IMG_MVEA_CORE_ID (TNC_IMG_MVEA_REG_BASE + 0x03c0)
+#define TNC_TOPAZ_IMG_MVEA_CORE_REV (TNC_IMG_MVEA_REG_BASE + 0x03d0)
+#define TNC_TOPAZ_MVEA_START (TNC_IMG_MVEA_REG_BASE + 0x0014)
+#define TNC_TOPAZ_MVEA_BUSY (TNC_IMG_MVEA_REG_BASE + 0x0018)
+#define TNC_TOPAZ_MVEA_DMACMDFIFO_WAIT (TNC_IMG_MVEA_REG_BASE + 0x001c)
+#define TNC_TOPAZ_MVEA_DMACMDFIFO_STATUS (TNC_IMG_MVEA_REG_BASE + 0x0020)
+#define TNC_TOPAZ_MVEA_AUTO_CLOCK_GATING (TNC_IMG_MVEA_REG_BASE + 0x0024)
+#define TNC_TOPAZ_MVEA_MAN_CLOCK_GATING (TNC_IMG_MVEA_REG_BASE + 0x0028)
+#define TNC_TOPAZ_MB_PERFORMANCE_RESULT (TNC_IMG_MVEA_REG_BASE + 0x002c)
+#define TNC_TOPAZ_MB_PERFORMANCE_MB_NUMBER (TNC_IMG_MVEA_REG_BASE + 0x0030)
+#define TNC_TOPAZ_HW_MB_PERFORMANCE_RESULT (TNC_IMG_MVEA_REG_BASE + 0x0034)
+#define TNC_TOPAZ_HW_MB_PERFORMANCE_MB_NUMBER (TNC_IMG_MVEA_REG_BASE + 0x0038)
+/* VLC Registers */
+#define TNC_VLC_START_OFFSET (0x05000)
+#define TNC_IMG_VLC_REG_BASE (TOPAZ_BASE + TNC_VLC_START_OFFSET)
+#define TNC_TOPAZ_VLC_CONTROL (TNC_IMG_VLC_REG_BASE + 0x0000)
+#define TNC_TOPAZ_VLC_STATUS (TNC_IMG_VLC_REG_BASE + 0x0004)
+#define TNC_TOPAZ_VLC_INFO_0 (TNC_IMG_VLC_REG_BASE + 0x0008)
+#define TNC_TOPAZ_VLC_INFO_1 (TNC_IMG_VLC_REG_BASE + 0x000c)
+#define TNC_TOPAZ_VLC_INFO_2 (TNC_IMG_VLC_REG_BASE + 0x0010)
+#define TNC_TOPAZ_VLC_STUFF_HEAD_CTRL (TNC_IMG_VLC_REG_BASE + 0x0014)
+#define TNC_TOPAZ_VLC_HEADER_FIFO (TNC_IMG_VLC_REG_BASE + 0x0018)
+#define TNC_TOPAZ_VLC_HEADER_CTRL (TNC_IMG_VLC_REG_BASE + 0x001c)
+#define TNC_TOPAZ_VLC_HEADER_STATUS (TNC_IMG_VLC_REG_BASE + 0x0020)
+#define TNC_TOPAZ_VLC_RATE_CTRL_0 (TNC_IMG_VLC_REG_BASE + 0x0024)
+#define TNC_TOPAZ_VLC_RATE_CTRL_1 (TNC_IMG_VLC_REG_BASE + 0x002c)
+#define TNC_TOPAZ_VLC_BUFFER_SIZE (TNC_IMG_VLC_REG_BASE + 0x0034)
+#define TNC_TOPAZ_VLC_SIGNATURE_0 (TNC_IMG_VLC_REG_BASE + 0x0038)
+#define TNC_TOPAZ_VLC_SIGNATURE_1 (TNC_IMG_VLC_REG_BASE + 0x003c)
+#define TNC_TOPAZ_VLC_SIGNATURE_2 (TNC_IMG_VLC_REG_BASE + 0x0040)
+#define TNC_TOPAZ_VLC_SIGNATURE_3 (TNC_IMG_VLC_REG_BASE + 0x0044)
+#define TNC_TOPAZ_VLC_SIGNATURE_4 (TNC_IMG_VLC_REG_BASE + 0x0048)
+#define TNC_TOPAZ_VLC_JPEG_CFG (TNC_IMG_VLC_REG_BASE + 0x004c)
+#define TNC_TOPAZ_VLC_PERFORMANCE_0 (TNC_IMG_VLC_REG_BASE + 0x0050)
+#define TNC_TOPAZ_VLC_PERFORMANCE_1 (TNC_IMG_VLC_REG_BASE + 0x0054)
+#define TNC_TOPAZ_VLC_PERFORMANCE_2 (TNC_IMG_VLC_REG_BASE + 0x0058)
+#define TNC_TOPAZ_VLC_IPCM_0 (TNC_IMG_VLC_REG_BASE + 0x005c)
+#define TNC_TOPAZ_VLC_IPCM_1 (TNC_IMG_VLC_REG_BASE + 0x0060)
+#define TNC_TOPAZ_VLC_MPEG4_CFG (TNC_IMG_VLC_REG_BASE + 0x0064)
+#define TNC_TOPAZ_VLC_MB_PARAMS (TNC_IMG_VLC_REG_BASE + 0x0068)
+#define TNC_TOPAZ_VLC_RESET (TNC_IMG_VLC_REG_BASE + 0x006c)
+
+#define WRITEBACK_MEM_SIZE (4 * 1024)
+
+#define TOPAZ_MTX_PC (0x00000005)
+#define PC_START_ADDRESS (0x80900000)
+#define MTX_CODE_BASE (0x80900000)
+#define MTX_DATA_BASE (0x82880000)
+#define MTX_CORE_CODE_MEM (0x10)
+#define MTX_CORE_DATA_MEM (0x18)
+
+#define MTX_CCB_CTRL_CCB_SIZE (8)
+#define MTX_CCB_CTRL_INIT_QP (24)
+
+#define MVEA_BASE 0xA3000
+#define VLC_BASE 0xA5000
+
+#define TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK 0x00010000
+#define TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK 0x80000000
+
+enum tnc_topaz_encode_fw {
+ FW_JPEG = 0,
+ FW_H264_NO_RC,
+ FW_H264_VBR,
+ FW_H264_CBR,
+ FW_H263_NO_RC,
+ FW_H263_VBR,
+ FW_H263_CBR,
+ FW_MPEG4_NO_RC,
+ FW_MPEG4_VBR,
+ FW_MPEG4_CBR,
+ FW_NUM
+};
+
+typedef struct _enc_fw_info {
+ enum tnc_topaz_encode_fw idx;
+ unsigned long *text_size;
+ unsigned long *data_size;
+ unsigned long *data_offset;
+ unsigned long *text;
+ unsigned long *data;
+ char *fw_version;
+}enc_fw_info_t;
+
+struct topaz_cmd_header {
+ union {
+ struct {
+ unsigned long enable_interrupt:1;
+ unsigned long id:7;
+ unsigned long size:8;
+ unsigned long seq:16;
+ };
+ unsigned int val;
+ };
+};
+
+/* commands for topaz,shared with user space driver */
+enum drm_lnc_topaz_cmd {
+ MTX_CMDID_NULL = 0,
+ MTX_CMDID_DO_HEADER = 1,
+ MTX_CMDID_ENCODE_SLICE = 2,
+ MTX_CMDID_WRITEREG = 3,
+ MTX_CMDID_START_PIC = 4,
+ MTX_CMDID_END_PIC = 5,
+ MTX_CMDID_SYNC = 6,
+ MTX_CMDID_ENCODE_ONE_ROW = 7,
+ MTX_CMDID_FLUSH = 8,
+ MTX_CMDID_SW_LEAVE_LOWPOWER = 0x7c,
+ MTX_CMDID_SW_ENTER_LOWPOWER = 0x7e,
+ MTX_CMDID_SW_NEW_CODEC = 0x7f
+};
+
+extern int topaz_setup_fw(igd_context_t *context, enum tnc_topaz_encode_fw codec);
+int process_video_encode_tnc(igd_context_t *context, unsigned long offset,
+ void *mem_handle, unsigned long *fence_id);
+int topaz_init_tnc(unsigned long wb_offset, void* mem_handle_writeback,
+ void *mem_handle_enc_fw);
+int topaz_get_fence_id(igd_context_t *context, unsigned long *fence_id);
+int topaz_flush_tnc(igd_context_t *context);
+int topaz_get_frame_skip(igd_context_t *context, unsigned long *frame_skip);
+int topaz_shutdown_tnc(igd_context_t *context);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/utils.h b/drivers/gpu/drm/emgd/emgd/include/utils.h
new file mode 100644
index 0000000..18fe9c3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/utils.h
@@ -0,0 +1,174 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: utils.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <config.h>
+#include <igd_mode.h>
+#include <general.h>
+#include <mode.h>
+
+/* Get the MMIO pointer for a display context */
+#define MMIO(dsp) \
+ EMGD_MMIO((((igd_display_context_t *)dsp)->context->device_context.virt_mmadr))
+
+/* Get the 2nd MMIO pointer for a display context */
+#define MMIO_SDVO(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo)
+
+/* Get the STMicro SDVO MMIO pointer for a display context */
+#define MMIO_SDVO_ST(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo_st)
+#define MMIO_SDVO_ST_GPIO(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo_st_gpio)
+
+/* Definition: value = READ_MMIO_REG(igd_display_context_t *, reg) */
+#define READ_MMIO_REG(dsp, reg) \
+ EMGD_READ32( MMIO(dsp) +(reg) )
+
+/* Definition: WRITE_MMIO_REG(igd_display_context_t *, reg, value) */
+#define WRITE_MMIO_REG(dsp, reg, value) \
+ EMGD_WRITE32(value, ( MMIO(dsp) + (reg) ) )
+
+/* Definition:WRITE_MMIO_REG_BITS(igd_display_context_t *, reg, value, mask) */
+#define WRITE_MMIO_REG_BITS(dsp, reg, data, mask) \
+{ \
+ unsigned long tmp; \
+ tmp = READ_MMIO_REG((dsp), (reg)); \
+ tmp &= (~(mask)); \
+ tmp |= ((data) & (mask)); \
+ WRITE_MMIO_REG((dsp), (reg), (tmp)); \
+}
+
+#define PORT_TYPE(d) (PORT(d, (d->port_number))->port_type)
+#define PORT_TYPE_DH(dh) \
+ (PORT(dh, (((igd_display_context_t *)dh)->port_number))->port_type)
+
+#ifdef CONFIG_TNC
+/* Based on display port determine which mmio base to use:
+ * port_type == SDVO ==> use 0:3:0 device mmio
+ * port_type == LVDS ==> use 0:2:0 device mmio
+ * port_type == LPC ==> use 0:31:0 device mmio
+ */
+#define MMIO_TNC(port_type) EMGD_MMIO(get_mmio_tnc(port_type))
+
+#define READ_MMIO_REG_TNC(pt, reg) read_mmio_reg_tnc(pt, reg)
+#define WRITE_MMIO_REG_TNC(pt, reg, value) write_mmio_reg_tnc(pt, reg, value)
+
+/* Defined in micro_mode_tnc.c */
+extern unsigned char *get_mmio_tnc(unsigned long port_type);
+extern unsigned long read_mmio_reg_tnc(unsigned long port_type,
+ unsigned long reg);
+extern void write_mmio_reg_tnc(unsigned long port_type, unsigned long reg,
+ unsigned long value);
+#endif
+
+
+/*
+ * These are temporary macros used only within this header.
+ * Individual config options use these macros to generate macros that look
+ * like this:
+ *
+ * If CONFIG_FOO is defined
+ * OPT_FOO_SYMBOL(a)
+ * OPT_FOO_VALUE(a, b)
+ * OPT_FOO_VOID_CALL(fn)
+ * OPT_FOO_CALL(fn)
+ */
+#define OPTIONAL_VOID_CALL(fn) fn
+#define OPTIONAL_CALL(fn) \
+ { \
+ int __ret; \
+ __ret = fn; \
+ if(__ret) { \
+ EMGD_ERROR_EXIT("EXIT"); \
+ return __ret; \
+ } \
+ }
+
+#define OPTIONAL_CALL_RET(ret, fn) (ret) = (fn)
+
+/*
+ * Debug call macro should be used to call debug printing functions
+ * that will only exist in debug builds.
+ */
+#ifdef DEBUG_BUILD_TYPE
+#define OPT_DEBUG_SYMBOL(sym) sym
+#define OPT_DEBUG_VALUE(val, alt) val
+#define OPT_DEBUG_VOID_CALL(fn) OPTIONAL_VOID_CALL(fn)
+#define OPT_DEBUG_CALL(fn) OPTIONAL_CALL(fn)
+#define OPT_DEBUG_INLINE
+#else
+#define OPT_DEBUG_SYMBOL(sym)
+#define OPT_DEBUG_VALUE(val, alt) alt
+#define OPT_DEBUG_VOID_CALL(fn)
+#define OPT_DEBUG_CALL(fn)
+#define OPT_DEBUG_INLINE static __inline
+#endif
+
+/*
+ * Micro Symbols are only used when CONFIG_MICRO is not defined.
+ */
+#ifndef CONFIG_MICRO
+#define OPT_MICRO_SYMBOL(sym) sym
+#define OPT_MICRO_VALUE(val, alt) val
+#define OPT_MICRO_VOID_CALL(fn) OPTIONAL_VOID_CALL(fn)
+#define OPT_MICRO_CALL(fn) OPTIONAL_CALL(fn)
+#define OPT_MICRO_CALL_RET(ret, fn) OPTIONAL_CALL_RET(ret, fn)
+#else
+#define OPT_MICRO_SYMBOL(sym)
+#define OPT_MICRO_VALUE(val, alt) alt
+#define OPT_MICRO_VOID_CALL(fn)
+#define OPT_MICRO_CALL(fn)
+#define OPT_MICRO_CALL_RET(ret, fn)
+#endif
+
+
+#ifdef CONFIG_PLB
+#define DISPATCH_PLB(p) {PCI_DEVICE_ID_VGA_PLB, p},
+#else
+#define DISPATCH_PLB(p)
+#endif
+#ifdef CONFIG_TNC
+#define DISPATCH_TNC(p) {PCI_DEVICE_ID_VGA_TNC, p},
+#define DISPATCH_TNC_A0(p) {PCI_DEVICE_ID_VGA_TNC_A0, p},
+#define DISPATCH_LNC(p) {PCI_DEVICE_ID_VGA_LNC, p},
+#else
+#define DISPATCH_TNC(p)
+#define DISPATCH_TNC_A0(p)
+#define DISPATCH_LNC(p)
+#endif
+#define DISPATCH_END {0, NULL}
+
+
+#endif // _UTILS_H_
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/vga.h b/drivers/gpu/drm/emgd/emgd/include/vga.h
new file mode 100644
index 0000000..1c9b782
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/vga.h
@@ -0,0 +1,116 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: vga.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Header file for common VGA registers and macros.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_VGA_H
+#define _HAL_VGA_H
+
+#include <igd_vga.h>
+#include <io.h>
+#include "drm_emgd_private.h"
+
+extern void program_pipe_vga(
+ igd_display_context_t *display,
+ igd_timing_info_t *timings);
+
+extern void kms_program_pipe_vga(
+ emgd_crtc_t *emgd_crtc,
+ igd_timing_info_t *timings);
+
+extern void program_plane_vga(
+ igd_display_context_t *display,
+ igd_timing_info_t *timings);
+
+extern void kms_program_plane_vga(
+ unsigned char *mmio,
+ igd_timing_info_t *timings);
+
+extern unsigned long get_vga_color(int i);
+
+extern void set_256_palette(unsigned char *mmio);
+
+extern unsigned char vga_port_offset;
+
+#define READ_VGA(mmio, port, index, data) \
+ EMGD_WRITE8((unsigned char)index, EMGD_MMIO(mmio) + port); \
+ data = EMGD_READ8(EMGD_MMIO(mmio) + port + 1);
+
+#define WRITE_VGA(mmio, port, index, data) \
+ EMGD_WRITE8(index, EMGD_MMIO(mmio) + port); \
+ EMGD_WRITE8(data, EMGD_MMIO(mmio) + port + 1); \
+ EMGD_DEBUG("0x%lx (0x%lx): 0x%lx", (unsigned long) port, \
+ (unsigned long) index, (unsigned long) data);
+
+#define READ_AR(mmio, index, data) \
+ { \
+ unsigned char tmp; \
+ tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+ EMGD_WRITE8(index, EMGD_MMIO(mmio) + AR_PORT); \
+ data = EMGD_READ8(EMGD_MMIO(mmio) + ARX_DATA_R); \
+ tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+ }
+
+#define WRITE_AR(mmio, index, data) \
+ { \
+ unsigned char tmp; \
+ tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+ EMGD_WRITE8(index, EMGD_MMIO(mmio) + AR_PORT); \
+ EMGD_WRITE8(data, EMGD_MMIO(mmio) + AR_PORT); \
+ EMGD_WRITE8(0x20, EMGD_MMIO(mmio) + AR_PORT); \
+ tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+}
+
+/* Status registers */
+#define ST00 0x3C2
+#define ST01 (0x3BA + vga_port_offset)
+
+/* Sequencer Registers */
+#define SR_PORT 0x3c4
+#define SRX_INDEX 0x3C4 /* Index port */
+#define SRX_DATA 0x3C5 /* Data port */
+
+/* Graphics Registers */
+#define GR_PORT 0x3ce
+#define GRX_INDEX 0x3CE /* Index port */
+#define GRX_DATA 0x3CF /* Data port */
+
+/* Attribute Controlller Registers */
+#define AR_PORT 0x3c0
+#define ARX_INDEX 0x3C0 /* Index port */
+#define ARX_DATA_R 0x3C1 /* Data port read */
+#define ARX_DATA_W 0x3C0 /* Data port write */
+
+/* CRTC Registers */
+#define CR_PORT (0x3b4 + vga_port_offset)
+#define CRX_INDEX (0x3b4 + vga_port_offset) /* Index port */
+#define CRX_DATA (0x3b5 + vga_port_offset) /* Data port */
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c b/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
new file mode 100644
index 0000000..84e5811
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
@@ -0,0 +1,138 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains fixed point implementations of math functions
+ *-----------------------------------------------------------------------------
+ */
+
+
+/******************************************************************************
+ * This is a look-up table for natural log for integer values 1 - 255 in
+ * 24i.8f fixed point format.
+ *
+ * This table returns 0 or ln(0), but it is technically undefined.
+ *****************************************************************************/
+static const int ln_table[] =
+ {
+ 0, 0, 177, 281, 355, 412, 459, 498, 532, 562, 589, 614,
+ 636, 657, 676, 693, 710, 725, 740, 754, 767, 779, 791, 803,
+ 814, 824, 834, 844, 853, 862, 871, 879, 887, 895, 903, 910,
+ 917, 924, 931, 938, 944, 951, 957, 963, 969, 975, 980, 986,
+ 991, 996, 1001, 1007, 1012, 1016, 1021, 1026, 1030, 1035, 1039, 1044,
+ 1048, 1052, 1057, 1061, 1065, 1069, 1073, 1076, 1080, 1084, 1088, 1091,
+ 1095, 1098, 1102, 1105, 1109, 1112, 1115, 1119, 1122, 1125, 1128, 1131,
+ 1134, 1137, 1140, 1143, 1146, 1149, 1152, 1155, 1158, 1160, 1163, 1166,
+ 1168, 1171, 1174, 1176, 1179, 1181, 1184, 1186, 1189, 1191, 1194, 1196,
+ 1199, 1201, 1203, 1206, 1208, 1210, 1212, 1215, 1217, 1219, 1221, 1223,
+ 1226, 1228, 1230, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248,
+ 1250, 1252, 1254, 1256, 1258, 1260, 1261, 1263, 1265, 1267, 1269, 1270,
+ 1272, 1274, 1276, 1278, 1279, 1281, 1283, 1284, 1286, 1288, 1289, 1291,
+ 1293, 1294, 1296, 1298, 1299, 1301, 1302, 1304, 1306, 1307, 1309, 1310,
+ 1312, 1313, 1315, 1316, 1318, 1319, 1321, 1322, 1324, 1325, 1327, 1328,
+ 1329, 1331, 1332, 1334, 1335, 1336, 1338, 1339, 1341, 1342, 1343, 1345,
+ 1346, 1347, 1349, 1350, 1351, 1353, 1354, 1355, 1356, 1358, 1359, 1360,
+ 1361, 1363, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1372, 1374, 1375,
+ 1376, 1377, 1378, 1380, 1381, 1382, 1383, 1384, 1385, 1387, 1388, 1389,
+ 1390, 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1402,
+ 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1415,
+ 1416, 1417, 1418, 1419
+ };
+
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: os_pow_fix()
+ *
+ * Parameters:
+ * [IN] base: the base, should be between 0 and 255.
+ * [IN] power: this must be in 24i.8f format.
+ *
+ * Description:
+ * This function uses the Taylor Series to approximate the power function
+ * using fixed-point math. See this website for the math background
+ * http://www.efunda.com/math/taylor_series/exponential.cfm
+ *
+ * This function was originally designed for gamma correction. When the
+ * base value is between 1 - 255 and the power is between 0.1 and 2, this
+ * function will produce an approximation that is within 2% of the "real"
+ * function.
+ *
+ * Returns:
+ * The result in 24i.8f format
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned int os_pow_fix( const int base, const int power )
+{
+ /* For some reason using "const unsigned int" causes a compiler error
+ * when I use it below when I declare "result[APPROXIMATE_TERMS]". So
+ * switched these from "const unsigned .." to #define
+ */
+ #define APPROXIMATE_TERMS 40
+#define FRACTION_BITS 8 /* num of bits for fraction */
+
+ unsigned int result[APPROXIMATE_TERMS];
+ unsigned int i, power_loop;
+ unsigned int total = 0;
+ int ln_x = ln_table[base]; /* ln_x is in 24i.8f format */
+
+
+ /* nothing to do if we get 0 */
+ if (0 == base) {
+ return 0;
+ } else {
+ ln_x = ln_table[base];
+ }
+
+ /* We approximate the result using APPROXIMATE_TERMS terms */
+ for (i = 0; i < APPROXIMATE_TERMS; i++) {
+
+ result[i] = 1 << FRACTION_BITS;
+
+ /* Need to be very careful about the order in which we are multiplying
+ * multiplying and dividing because we don't want any overflow. In
+ * addition, every time we multiply 2 fixed point numbers, we need to
+ * shift the result by FRACTION_BITS to maintain the radix point.
+ */
+ for( power_loop = 0; power_loop < i; power_loop++ ) {
+ result[i] *= ln_x;
+ result[i] /= (power_loop + 1);
+ result[i] >>=FRACTION_BITS;
+ result[i] *= power;
+ result[i] >>=FRACTION_BITS;
+
+ }
+
+ total += result[i];
+
+ }
+
+ return total;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c b/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
new file mode 100644
index 0000000..2ee0812
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the XFree86 implementations of the OAL
+ * memory.h abstractions.
+ *-----------------------------------------------------------------------------
+ */
+#include <io.h>
+
+#ifndef _OAL_LINUX_KERNEL_IO_MEMMAP_H
+#define _OAL_LINUX_KERNEL_IO_MEMMAP_H
+
+
+void * os_map_io_to_mem_nocache(
+ unsigned long base_address,
+ unsigned long size
+ )
+{
+ return ioremap(base_address, size);
+}
+
+void os_unmap_io_from_mem(
+ void * virt_addr,
+ unsigned long size
+ )
+{
+ iounmap(virt_addr);
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/pci.c b/drivers/gpu/drm/emgd/emgd/oal/src/pci.c
new file mode 100644
index 0000000..ff8a28c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/pci.c
@@ -0,0 +1,277 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains Linux kernel space PCI API for the OAL abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <memory.h>
+#include <pci.h>
+#include <linux/pci.h>
+#include <io.h>
+
+#if defined(CONFIG_VGA_ARB)
+#include <linux/vgaarb.h>
+#endif
+
+
+//
+// This is our local representation of a PCI device.
+// This struct is private to this file, and exposed to calling functions
+// only through an opaque "os_pci_dev_t" handle.
+//
+typedef struct _linuxkernel_pci {
+ struct pci_dev *dev;
+ unsigned int bus;
+ unsigned int slot;
+ unsigned int func;
+}linuxkernel_pci_t;
+
+/*----------------------------------------------------------------------
+ * Function:
+ *pci_find_device_generic
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *os_pci_dev_t os_pci_dev
+ * Description:
+ *This function finds a PCI device by going through 255 buses, 32 devices
+ *and 8 functions and tries to match each ones vendor and device ids with
+ *the ones given to it as parameters. Stops for the first device it finds
+ *with a matching vendor and device, so it will not find multiple devices.
+ *This is _NOT_ an exported OAL
+ *function.
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+static os_pci_dev_t pci_find_device_generic(
+ unsigned short vendor_id,
+ unsigned short device_id,
+ os_pci_dev_t pci_dev_handle
+ )
+{
+ struct pci_dev *our_device; // Kernel struct for a PCI device
+ linuxkernel_pci_t *pdev; // Our struct for a PCI device.
+
+ // Locate the device, and lock it. Start search at the start of the list.
+ our_device = pci_get_device(vendor_id, device_id, NULL);
+ // If we didn't find it, return an error.
+ if (!our_device){
+ return (os_pci_dev_t)NULL;
+ }
+
+ // Get the pointer to the destination for the data.
+ // pci_dev_handle is an opaque pointer to a linuxkernel_pci_t struct
+ // If there isn't one, allocate it.
+ pdev = (linuxkernel_pci_t *)pci_dev_handle;
+ if(!pdev) {
+
+ // Caller did not supply a handle to a PCI device struct.
+ // Allocate one.
+ pdev = (linuxkernel_pci_t *)OS_ALLOC(sizeof(linuxkernel_pci_t));
+ if(!pdev) {
+ return (os_pci_dev_t)NULL;
+ }
+ // Zero the destination memory
+ memset(pdev, 0, sizeof(linuxkernel_pci_t));
+ }
+
+ // Copy over from the kernel struct to our struct.
+ // It is safe to copy a pointer to the pci_dev, since we
+ // have a lock on it.
+ pdev->dev = our_device;
+ pdev->bus = our_device->bus->number;
+ pdev->slot = PCI_SLOT(our_device->devfn);
+ pdev->func = PCI_FUNC(our_device->devfn);
+
+ return (os_pci_dev_t)pdev;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *os_pci_find_device
+ *
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *unsigned short bus,
+ *unsigned short dev,
+ *unsigned short func,
+ *os_pci_dev_t os_pci_dev
+ *
+ * Description:
+ * This function finds a PCI device by scanning the specified bus, dev, func
+ *and tries to match vendor and device ids with the ones given to it as
+ *parameters.
+ *
+ * Notes: If the bus number is 0xFFFF, then the function searches for that
+ * vendor_id, device_id pair in the whole PCI topology of the system i.e
+ * it goes through all the buses, devices, functions in the system
+ *
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+os_pci_dev_t os_pci_find_device(
+ unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short bus,
+ unsigned short dev,
+ unsigned short func,
+ os_pci_dev_t pci_dev)
+{
+ /* TODO: Right now, Just fallback to pci_find_device_generic
+ * But we need to implement this
+ */
+ return pci_find_device_generic(vendor_id, device_id, pci_dev);
+}
+
+int os_pci_get_slot_address(
+ os_pci_dev_t pci_dev,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *func)
+{
+
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+ if(bus) {
+ *bus = pdev->bus;
+ }
+ if(slot) {
+ *slot = pdev->slot;
+ }
+ if(func) {
+ *func = pdev->func;
+ }
+ return 0;
+}
+
+int os_pci_read_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_read_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_word(pdev->dev, offset,val);
+}
+
+int os_pci_read_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_dword(pdev->dev, offset, (u32*)val);
+}
+
+int os_pci_write_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_word(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_dword(pdev->dev, offset, val);
+}
+
+int os_pci_disable_legacy_vga_decoding(
+ os_pci_dev_t pci_dev
+ )
+{
+#if defined(CONFIG_VGA_ARB)
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+ vga_set_legacy_decoding(pdev->dev, VGA_RSRC_NONE);
+#else
+ /* Noop if the VGA arbiter isn't compiled into the kernel */
+#endif
+
+ return 0;
+}
+
+
+void os_pci_free_device(
+ os_pci_dev_t pci_dev
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+
+ // Release the lock on our PCI device struct
+ pci_dev_put(pdev->dev);
+
+ // Free our local structure.
+ OS_FREE(pdev);
+
+ return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/Makefile.include b/drivers/gpu/drm/emgd/emgd/pal/Makefile.include
new file mode 100644
index 0000000..c312c51
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/Makefile.include
@@ -0,0 +1,50 @@
+#----------------------------------------------------------------------------
+# Filename: Makefile.include
+# $Revision: 1.3 $
+#----------------------------------------------------------------------------
+# Copyright (c) 2002-2010, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#----------------------------------------------------------------------------
+
+ifeq ($(origin EGD_CFG), undefined)
+$(error EGD_CFG environment variable is required for compilation)
+endif
+
+EGD_ROOT := $(subst \,/,$(EGD_ROOT))
+
+#
+# PAL overrides the include paths because the HAL get access to more
+# headers that the port drivers cannot use.
+#
+PROJECT_INCLUDES := \
+ $(EGD_ROOT)/hal/include \
+ $(EGD_ROOT)/$(EGD_CFG)/include \
+ $(EGD_ROOT)/$(EGD_CFG)/oal/include \
+ $(EGD_ROOT)/$(EGD_CFG)/oal \
+ $(EGD_ROOT)/$(EGD_CFG)/pal/lpd
+
+PROJECT_LIBS=\
+ $(EGD_ROOT)/$(EGD_CFG)/cfg/lib/liblpd
+
+PROJECT_BUILD_OPTS = -DMODULE_NAME=hal.dpd
+
+PROJECT_OUTPUT_PATH = $(EGD_ROOT)/$(EGD_CFG)/cfg/dpd
+
+include $(EGD_ROOT)/$(EGD_CFG)/build/Makefile.include
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu b/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
new file mode 100644
index 0000000..adc8199
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
@@ -0,0 +1,43 @@
+#----------------------------------------------------------------------------
+# Copyright (c) 2002-2010, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#----------------------------------------------------------------------------
+
+DRV = ch7036
+SOURCES = \
+ ch7036_port.c \
+ ch7036_intf.c \
+ ch7036_attr.c \
+ ch7036_fw.c \
+ ch7036.c \
+ ch7036_iic.c \
+ ch7036_pm.c \
+ ch7036_reg_table.c \
+ lvds.c
+
+
+include ../Makefile.include
+
+#----------------------------------------------------------------------------
+# File Revision History
+# $Id: Makefile.gnu,v 1.1.2.1 2011/09/13 08:50:22 nanuar Exp $
+# $Source: /nfs/fm/proj/eia/cvsroot/koheo/linux.nonredistributable/ch7036/ch7036pd_src/Attic/Makefile.gnu,v $
+#----------------------------------------------------------------------------
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
new file mode 100755
index 0000000..3b588a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
@@ -0,0 +1,2366 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036.c
+* @version 1.2.2.1
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_intf.h"
+
+
+static uint32 g_nLastError;
+
+
+
+static ch_bool convert_pll1n1_div(ch_bool pll1n1_to_div, uint8* pll1n1_addr, uint8* div_addr);
+static ch_bool convert_pll1n2_div(ch_bool pll1n2_to_div, uint8* pll1n2_addr, uint8* div_addr);
+static ch_bool convert_pll1n3_div(ch_bool pll1n3_to_div, uint8* pll1n3_addr, uint8* div_addr);
+static ch_bool convert_pll2n5_div(ch_bool pll2n5_to_div, uint8* pll2n5_addr, uint8* div_addr);
+static ch_bool convert_pll2n6_div(ch_bool pll2n6_to_div, uint8* pll2n6_addr, uint8* div_addr);
+static ch_bool convert_pll2n7_div(ch_bool pll2n7_to_div, uint8* pll2n7_addr, uint8* div_addr);
+static ch_bool convert_pll3n8_div(ch_bool pll3n8_to_div, uint8* pll3n8_addr, uint8* div_addr);
+static ch_bool convert_dmxtal_div(ch_bool dmxtal_to_div, uint8* dmxtal_addr, uint8* div_addr);
+
+
+static ch_bool set_input_info(INPUT_INFO* pInput_Info);
+
+
+static ch_bool set_output_info(OUTPUT_INFO* pOutput_Info);
+
+
+static ch_bool set_prefer_info(PREFER_INFO* pPrefer_Info);
+
+
+static ch_bool cal_and_set_clk_pll(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool cal_and_set_scaler(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool cal_and_set_power(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool post_cal_and_set(DEV_CONTEXT* pDevContext);
+
+
+extern void ch7036_set_power_lvds(DEV_CONTEXT* pDevContext);
+extern void ch7036_set_power_hdmi(DEV_CONTEXT* pDevContext);
+extern void ch7036_set_power_crt(DEV_CONTEXT* pDevContext);
+
+
+#define DOUBLE_TO_INT 1000
+
+
+
+
+
+
+
+ch_bool DeviceSetPower(DEV_CONTEXT* pDevContext, unsigned long flags)
+{
+
+ switch (flags) {
+ default:
+ ch7036_set_power_crt(pDevContext);
+ ch7036_set_power_hdmi(pDevContext);
+ ch7036_set_power_lvds(pDevContext);
+ break;
+ }
+
+ return ch_true;
+
+}
+
+ch_bool DevicePrepare(DEV_CONTEXT* pDevContext)
+{
+ uint32 C;
+ uint32 hao_t, vao_t, vai_t, val_t;
+ uint32 hai_down;
+ uint32 hai_sdram;
+ uint32 lnsel;
+ uint32 intlc = 0;
+ uint32 blk_h;
+ uint32 fba_inc;
+ uint32 bandwidth;
+
+ uint32 frame_rate_in, frame_rate_out;
+ uint32 r;
+
+ INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+ OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+
+ g_nLastError = ERR_NO_ERROR;
+
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ pDevContext->DeviceID = I2CRead(pDevContext,0x50);
+ if(pDevContext->DeviceID != 0x56)
+ {
+ g_nLastError = ERR_DEVICE_NO_EXIST;
+ return ch_false;
+ }
+
+
+
+ if(pInput_Info->timing.ha % 2)
+ {
+ pInput_Info->timing.ha--;
+ }
+ if(pInput_Info->timing.va % 2)
+ {
+ pInput_Info->timing.va--;
+ }
+
+
+
+ if(pPrefer_Info->dat16_32b)
+ {
+ C = 100;
+ }
+ else if(pPrefer_Info->true24)
+ {
+ C = 100;
+ }
+ else
+ {
+ C = (pPrefer_Info->true_com) ? 75 : 50;
+ }
+ if(pOutput_Info->ds_percent_h)
+ {
+ hao_t = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+ }
+ else
+ {
+ hao_t = pOutput_Info->timing.ha;
+ }
+ if(pOutput_Info->ds_percent_v)
+ {
+ vao_t = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+ }
+ else
+ {
+ vao_t = pOutput_Info->timing.va;
+ }
+ hao_t = hao_t + (hao_t % 2);
+ vao_t = vao_t + (vao_t % 2);
+ hai_down = pInput_Info->timing.ha;
+ if(hai_down > hao_t && pOutput_Info->rotate != ROTATE_90 && pOutput_Info->rotate != ROTATE_270)
+ {
+ hai_down = hao_t;
+ }
+
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ val_t = 720;
+ }
+ else
+ {
+ if(pPrefer_Info->dat16_32b)
+ {
+ val_t = 720;
+ }
+ else
+ {
+ val_t = pPrefer_Info->true24 ? 720 : 1440;
+ }
+ }
+ if(hai_down > val_t && (pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip))
+ {
+ hai_down = val_t;
+ }
+
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ {
+
+ switch(pOutput_Info->hdmi_fmt.format_index)
+ {
+ case 5:
+ case 6:
+ case 7:
+ case 10:
+ case 11:
+ case 20:
+ case 21:
+ case 22:
+ case 25:
+ case 26:
+ intlc = 1;
+ break;
+ default:
+ intlc = 0;
+ break;
+ }
+ }
+
+
+ if(pOutput_Info->channel & CHANNEL_VGA)
+ {
+ intlc = 0;
+ }
+
+ val_t = intlc ? (vao_t / 2) : vao_t;
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ if(hai_down <= val_t)
+ lnsel = 3;
+ else
+ lnsel = 1;
+ }
+ else
+ {
+ if(pInput_Info->timing.va <= val_t)
+ lnsel = 3;
+ else
+ lnsel = 1;
+ }
+ bandwidth = (pInput_Info->rx_clk_khz + pOutput_Info->uclk_khz * pInput_Info->timing.ha / hao_t * (4 - lnsel)) / 85 * C;
+ if(bandwidth > MEM_CLK_FREQ_MAX)
+ {
+ if(lnsel >= 2)
+ {
+ g_nLastError = ERR_BANDWIDTH_OVERFLOW;
+ return ch_false;
+ }
+
+ lnsel++;
+
+
+
+
+
+
+ if(pInput_Info->rx_clk_khz >= 75428 && pOutput_Info->uclk_khz >= 94500)
+ lnsel++;
+
+ bandwidth = (pInput_Info->rx_clk_khz + pOutput_Info->uclk_khz * pInput_Info->timing.ha / hao_t * (4 - lnsel)) / 85 * C;
+ if(bandwidth > MEM_CLK_FREQ_MAX)
+ {
+ g_nLastError = ERR_BANDWIDTH_OVERFLOW;
+ return ch_false;
+ }
+ pPrefer_Info->scale_line_adjust = 1;
+ }
+
+
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ val_t = 100;
+ }
+ else
+ {
+ if(pPrefer_Info->dat16_32b)
+ {
+ val_t = 100;
+ }
+ else if(pPrefer_Info->true24)
+ {
+ val_t = 100;
+ }
+ else
+ {
+ val_t = pPrefer_Info->true_com ? 75 : 50;
+ }
+ }
+ if(val_t == 75)
+ {
+ hai_sdram = (hai_down / 4) * 3 + (hai_down % 4);
+ }
+ else
+ {
+ hai_sdram = hai_down * val_t / 100;
+ }
+ if(pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip)
+ {
+ blk_h = 45;
+ }
+ else if(hai_sdram <= 720 && pInput_Info->timing.va <= 720)
+ {
+ blk_h = 45;
+ }
+ else
+ {
+ blk_h = hai_sdram / 16;
+ blk_h = (hai_sdram % 16) ? (blk_h + 1) : blk_h;
+ }
+
+
+ if((pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270) && pPrefer_Info->true24 == 0 && pPrefer_Info->true_com == 0 && pPrefer_Info->dat16_32b == 0)
+ {
+ vai_t = pInput_Info->timing.va / 2;
+ }
+ else
+ {
+ vai_t = pInput_Info->timing.va;
+ }
+ val_t = (vai_t % 16) ? (vai_t / 16 + 1) : (vai_t / 16);
+ fba_inc = blk_h * val_t;
+
+
+ frame_rate_in = ((pInput_Info->rx_clk_khz * 10000) / pInput_Info->timing.ht) * 10 / pInput_Info->timing.vt;
+ frame_rate_out = ((pOutput_Info->uclk_khz * 10000) / pOutput_Info->timing.ht) * 10 / pOutput_Info->timing.vt;
+ r = DOUBLE_TO_INT*frame_rate_in / frame_rate_out;
+
+
+ if(pPrefer_Info->dat16_32b)
+ {
+ if(pPrefer_Info->true24)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUE24;
+ return ch_false;
+ }
+ if(pPrefer_Info->true_com)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+ return ch_false;
+ }
+ if(pOutput_Info->rotate == ROTATE_NO && pOutput_Info->h_flip == 0 && pOutput_Info->v_flip == 0)
+ {
+ if(fba_inc > FBA_INC_MAX)
+ {
+
+
+
+ if (( (DOUBLE_TO_INT/2) <= r) && ( r <= DOUBLE_TO_INT))
+ {
+ if( ((4096*DOUBLE_TO_INT) / fba_inc) < (2*DOUBLE_TO_INT-r) )
+ {
+ g_nLastError = ERR_RESOLUTION_OVERFLOW;
+ return ch_false;
+ }
+ }
+
+ if (( DOUBLE_TO_INT < r) && ( r <= (2*DOUBLE_TO_INT)))
+ {
+ if( ((4096*DOUBLE_TO_INT) / fba_inc) <
+ (2*DOUBLE_TO_INT - (DOUBLE_TO_INT*DOUBLE_TO_INT)/r) )
+ {
+ g_nLastError = ERR_RESOLUTION_OVERFLOW;
+ return ch_false;
+ }
+ }
+
+ }
+ }
+ else if(pOutput_Info->rotate != ROTATE_NO)
+ {
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_ROTATION_WITH_VAI;
+ return ch_false;
+ }
+ }
+ else
+ {
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_FLIP_WITH_VAI;
+ return ch_false;
+ }
+ }
+ }
+
+
+ if(pPrefer_Info->dat16_32b == 0)
+ {
+ if(pOutput_Info->rotate == ROTATE_NO && pOutput_Info->h_flip == 0 && pOutput_Info->v_flip == 0)
+ {
+ if(fba_inc > FBA_INC_MAX)
+ {
+
+ if (( (DOUBLE_TO_INT/2) <= r) && ( r <= DOUBLE_TO_INT))
+ {
+ if( ((4096*DOUBLE_TO_INT) / fba_inc) < (2*DOUBLE_TO_INT-r) )
+ {
+ g_nLastError = ERR_RESOLUTION_OVERFLOW;
+ return ch_false;
+ }
+ }
+
+ if (( DOUBLE_TO_INT < r) && ( r <= (2*DOUBLE_TO_INT)))
+ {
+ if( ((4096*DOUBLE_TO_INT) / fba_inc) <
+ (2*DOUBLE_TO_INT - (DOUBLE_TO_INT*DOUBLE_TO_INT)/r) )
+ {
+ g_nLastError = ERR_RESOLUTION_OVERFLOW;
+ return ch_false;
+ }
+ }
+
+
+ if(pPrefer_Info->true24)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUE24;
+ return ch_false;
+ }
+ if(pPrefer_Info->true_com)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+ return ch_false;
+ }
+ g_nLastError = ERR_RESOLUTION_OVERFLOW;
+ return ch_false;
+ }
+ }
+ if(pOutput_Info->rotate == ROTATE_180)
+ {
+ if(pPrefer_Info->true_com)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+ return ch_false;
+ }
+ if(pPrefer_Info->true24)
+ {
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUE24;
+ return ch_false;
+ }
+ }
+ else
+ {
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_ROTATION_WITH_VAI;
+ return ch_false;
+ }
+ }
+ }
+ if(pOutput_Info->h_flip || pOutput_Info->v_flip)
+ {
+ if(pPrefer_Info->true_com)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+ return ch_false;
+ }
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_FLIP_WITH_VAI;
+ return ch_false;
+ }
+ }
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ if(pPrefer_Info->true_com)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+ return ch_false;
+ }
+ if(pPrefer_Info->true24)
+ {
+ if(pInput_Info->timing.va > 720)
+ {
+ g_nLastError = ERR_NO_SUPPORT_TRUE24;
+ return ch_false;
+ }
+ }
+ else
+ {
+ if(pInput_Info->timing.va > 1440)
+ {
+ g_nLastError = ERR_ROTATION_WITH_VAI;
+ return ch_false;
+ }
+ }
+ }
+ }
+
+
+
+ if(pPrefer_Info->true24 || pPrefer_Info->true_com)
+ {
+ pPrefer_Info->dither_filter_enable = 0;
+ }
+
+
+
+
+ iic_reset();
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA)
+ {
+
+ iic_write(0x03, 0x01);
+ iic_write(0x07, 0x7E);
+ iic_write(0x09, 0x0B);
+ iic_write(0x03, 0x00);
+ iic_write_ex(STOP, 1);
+ }
+
+ return ch_true;
+}
+
+ch_bool DeviceConfig(DEV_CONTEXT* pDevContext)
+{
+ if(!set_input_info(pDevContext->pInput_Info))
+ return ch_false;
+
+ if(!set_output_info(pDevContext->pOutput_Info))
+ return ch_false;
+
+ if(!set_prefer_info(pDevContext->pPrefer_Info))
+ return ch_false;
+
+ if(!cal_and_set_clk_pll(pDevContext))
+ return ch_false;
+
+ if(!cal_and_set_scaler(pDevContext))
+ return ch_false;
+
+ if(!cal_and_set_power(pDevContext))
+ return ch_false;
+
+ return ch_true;
+}
+
+ch_bool DeviceRunning(DEV_CONTEXT* pDevContext)
+{
+ uint8 val_t;
+ uint8 reg = 0x00;
+ OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+ uint8 REFDLY = pPrefer_Info->pll_ref_dly;
+ uint8 FBDLY = pPrefer_Info->pll_ref_fbdly;
+ uint8 TXDRV_IT = pPrefer_Info->lvds_txdrv_ctrl;
+
+
+ DeviceReset(pDevContext);
+
+
+
+ DeviceSetup(pDevContext);
+
+
+ I2CWrite(pDevContext,0x03, 0x01);
+
+
+
+
+ reg = I2CRead(pDevContext,0x24) & 0xFD;
+ I2CWrite(pDevContext,0x24, reg);
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ reg = I2CRead(pDevContext,0x66);
+ reg = reg & 0x1F;
+ reg = reg | ((uint8)REFDLY << 5);
+ I2CWrite(pDevContext,0x66, reg);
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ reg = I2CRead(pDevContext,0x66);
+ reg = reg & 0xE3;
+ reg = reg | ((uint8)FBDLY << 2);
+ I2CWrite(pDevContext,0x66, reg);
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ reg = I2CRead(pDevContext,0x68) & 0xF0;
+ reg = reg | ((uint8)TXDRV_IT);
+ I2CWrite(pDevContext,0x68, reg);
+
+
+
+
+
+
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0D);
+ if((pPrefer_Info->eye_dri_pll_rlf >= 0) && (pPrefer_Info->eye_dri_pll_rlf <= 3))
+ reg = (reg & 0x9F) | (pPrefer_Info->eye_dri_pll_rlf << 5);
+ I2CWrite(pDevContext,0x0D, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0C);
+ if((pPrefer_Info->eye_dri_pll_cp >= 0) && (pPrefer_Info->eye_dri_pll_cp <= 3))
+ reg = (reg & 0x3F) | (pPrefer_Info->eye_dri_pll_cp << 6);
+ I2CWrite(pDevContext,0x0C, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0B);
+ if((pPrefer_Info->eye_dri_damp >= 0) && (pPrefer_Info->eye_dri_damp <= 7))
+ reg = (reg & 0x1F) | (pPrefer_Info->eye_dri_damp << 5);
+ I2CWrite(pDevContext,0x0B, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0A);
+ if((reg & 0x01)==0x00)
+ reg = (reg | 0x01);
+ I2CWrite(pDevContext,0x0A, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0A);
+ if((pPrefer_Info->eye_dri_demp >= 0) && (pPrefer_Info->eye_dri_demp <= 15))
+ reg = (reg & 0xE1) | (pPrefer_Info->eye_dri_demp << 1);
+ I2CWrite(pDevContext,0x0A, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x08);
+ if((pPrefer_Info->eye_dacg >= 0) && (pPrefer_Info->eye_dacg <= 3))
+ reg = (reg & 0x3F) | (pPrefer_Info->eye_dacg << 6);
+ I2CWrite(pDevContext,0x08, reg);
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x0F);
+ if((pPrefer_Info->eye_rdac >= 0) && (pPrefer_Info->eye_rdac <= 7))
+ reg = (reg & 0xC7) | (pPrefer_Info->eye_rdac << 3);
+ I2CWrite(pDevContext,0x0F, reg);
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ reg = I2CRead(pDevContext,0x54);
+ if((pPrefer_Info->eye_bgtrim >= 0) && (pPrefer_Info->eye_bgtrim <= 3))
+ reg = (reg & 0xF3) | (pPrefer_Info->eye_bgtrim << 2);
+ I2CWrite(pDevContext,0x54, reg);
+
+
+
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA)
+ {
+
+ if(!post_cal_and_set(pDevContext)){
+ return ch_false;
+ }
+
+
+ I2CWrite(pDevContext,0x03, 0x00);
+ val_t = I2CRead(pDevContext,0x0A);
+ I2CWrite(pDevContext,0x0A, val_t | 0x80);
+ I2CWrite(pDevContext,0x0A, val_t & 0x7F);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ I2CWrite(pDevContext,0x03, 0x00);
+ val_t = I2CRead(pDevContext,0x0A);
+ I2CWrite(pDevContext,0x0A, val_t & 0xEF);
+
+
+
+ }
+
+ return ch_true;
+}
+
+uint32 GetLastErrorMessage()
+{
+ return g_nLastError;
+}
+
+
+
+ch_bool set_input_info(INPUT_INFO* pInput_Info)
+{
+
+ iic_write_ex(HTI, pInput_Info->timing.ht);
+ iic_write_ex(HAI, pInput_Info->timing.ha);
+ iic_write_ex(HOI, pInput_Info->timing.ho);
+ iic_write_ex(HWI, pInput_Info->timing.hw);
+ iic_write_ex(VTI, pInput_Info->timing.vt);
+ iic_write_ex(VAI, pInput_Info->timing.va);
+ iic_write_ex(VOI, pInput_Info->timing.vo);
+ iic_write_ex(VWI, pInput_Info->timing.vw);
+
+ iic_write_ex(RCLK, pInput_Info->rx_clk_khz);
+
+
+ switch(pInput_Info->pixel_fmt)
+ {
+ case 0:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ case 1:
+ iic_write_ex(DITHER_SEL0_SPP, 1);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ case 2:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 1);
+ break;
+ case 3:
+ iic_write_ex(DITHER_SEL0_SPP, 1);
+ iic_write_ex(DITHER_SEL1_SPP, 1);
+ break;
+ default:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ }
+
+
+
+ iic_write_ex(HSYNCP_SPP, pInput_Info->hs_pol);
+ iic_write_ex(VSYNCP_SPP, pInput_Info->vs_pol);
+
+ iic_write_ex(HPO_I, pInput_Info->hs_pol);
+ iic_write_ex(VPO_I, pInput_Info->vs_pol);
+ iic_write_ex(DEPO_I, pInput_Info->de_pol);
+
+ iic_write_ex(NP_INV0_SPP, (pInput_Info->data_ch_pol & (1 << 0)) ? 1 : 0);
+ iic_write_ex(NP_INV1_SPP, (pInput_Info->data_ch_pol & (1 << 1)) ? 1 : 0);
+ iic_write_ex(NP_INV2_SPP, (pInput_Info->data_ch_pol & (1 << 2)) ? 1 : 0);
+ iic_write_ex(NP_INV3_SPP, (pInput_Info->data_ch_pol & (1 << 3)) ? 1 : 0);
+
+ iic_write_ex(LVDS_IN_ORDER, pInput_Info->data_ch_invert);
+
+ iic_write_ex(I2S_SPDIFB, pInput_Info->audio_type);
+ if(pInput_Info->audio_type == AUDIO_I2S) {
+ iic_write_ex(I2SPOL, pInput_Info->i2s_pol);
+ iic_write_ex(I2S_LENGTH, pInput_Info->i2s_len);
+ iic_write_ex(I2SFMT, pInput_Info->i2s_fmt);
+ }
+
+ return ch_true;
+}
+
+ch_bool set_output_info(OUTPUT_INFO* pOutput_Info)
+{
+ uint8 lvds0_seq, lvds1_seq, lvds2_seq, lvds3_seq, lvdsclk_seq;
+ uint8 lvds0_pol, lvds1_pol, lvds2_pol, lvds3_pol, lvdsclk_pol;
+ uint8 hd_dvib, intlc = 0, copy, hd_lv_pol, hd_lv_seq, hdmi_lvds_sel, hsp, vsp, m1m0, c1c0, vic;
+ uint32 hao_down, vao_down;
+
+
+ LVDS_FMT* pLvdsFmt = &pOutput_Info->lvds_fmt;
+ HDMI_FMT* pHdmiFmt = &pOutput_Info->hdmi_fmt;
+
+
+
+
+
+
+
+
+
+
+ if(pOutput_Info->channel & CHANNEL_VGA || pOutput_Info->channel & CHANNEL_HDMI) {
+ iic_write_ex(VP,pOutput_Info->v_position);
+ iic_write_ex(HP,pOutput_Info->h_position);
+ }
+
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA)
+ {
+ iic_write_ex(HTO, pOutput_Info->timing.ht);
+ iic_write_ex(HAO, pOutput_Info->timing.ha);
+ iic_write_ex(HOO_HDMI, pOutput_Info->timing.ho);
+ iic_write_ex(HWO_HDMI, pOutput_Info->timing.hw);
+ iic_write_ex(VTO, pOutput_Info->timing.vt);
+ iic_write_ex(VAO, pOutput_Info->timing.va);
+ iic_write_ex(VOO_HDMI, pOutput_Info->timing.vo);
+ iic_write_ex(VWO_HDMI, pOutput_Info->timing.vw);
+
+ iic_write_ex(UCLK, pOutput_Info->uclk_khz);
+ iic_write_ex(ROTATE, pOutput_Info->rotate);
+ iic_write_ex(HFLIP, pOutput_Info->h_flip);
+ iic_write_ex(VFLIP, pOutput_Info->v_flip);
+
+ hao_down = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+ hao_down = hao_down + (hao_down % 2);
+ vao_down = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+ vao_down = vao_down + (vao_down % 2);
+ if(pOutput_Info->ds_percent_h || pOutput_Info->ds_percent_v)
+ {
+ iic_write_ex(SCAN_EN, 1);
+ iic_write_ex(HAO_SCL, hao_down);
+ iic_write_ex(VAO_SCL, vao_down);
+ }
+
+ iic_write_ex(ROTATE, pOutput_Info->rotate);
+ iic_write_ex(HFLIP, pOutput_Info->h_flip);
+ iic_write_ex(VFLIP, pOutput_Info->v_flip);
+ }
+
+ if(pOutput_Info->channel & CHANNEL_LVDS)
+ {
+
+ lvds0_seq = (pLvdsFmt->channel_swap >> 0) & 0xF;
+ lvds1_seq = (pLvdsFmt->channel_swap >> 4) & 0xF;
+ lvds2_seq = (pLvdsFmt->channel_swap >> 8) & 0xF;
+ lvds3_seq = (pLvdsFmt->channel_swap >> 12) & 0xF;
+ lvdsclk_seq = (pLvdsFmt->channel_swap >> 16) & 0xF;
+ iic_write_ex(LVDS0_SEQ_SPP, lvds0_seq);
+ iic_write_ex(LVDS1_SEQ_SPP, lvds1_seq);
+ iic_write_ex(LVDS2_SEQ_SPP, lvds2_seq);
+ iic_write_ex(LVDS3_SEQ_SPP, lvds3_seq);
+ iic_write_ex(LVDSCLK_SEQ_SPP, lvdsclk_seq);
+
+ lvds0_pol = (pLvdsFmt->channel_pol >> 0) & 0x1;
+ lvds1_pol = (pLvdsFmt->channel_pol >> 1) & 0x1;
+ lvds2_pol = (pLvdsFmt->channel_pol >> 2) & 0x1;
+ lvds3_pol = (pLvdsFmt->channel_pol >> 3) & 0x1;
+ lvdsclk_pol = (pLvdsFmt->channel_pol >> 4) & 0x1;
+ iic_write_ex(LVDS0_POL_SPP, lvds0_pol);
+ iic_write_ex(LVDS1_POL_SPP, lvds1_pol);
+ iic_write_ex(LVDS2_POL_SPP, lvds2_pol);
+ iic_write_ex(LVDS3_POL_SPP, lvds3_pol);
+ iic_write_ex(LVDSCLK_POL_SPP, lvdsclk_pol);
+
+
+ switch(pLvdsFmt->pixel_fmt){
+ case 0:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ case 1:
+ iic_write_ex(DITHER_SEL0_SPP, 1);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ case 2:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 1);
+ break;
+ case 3:
+ iic_write_ex(DITHER_SEL0_SPP, 1);
+ iic_write_ex(DITHER_SEL1_SPP, 1);
+ break;
+ default:
+ iic_write_ex(DITHER_SEL0_SPP, 0);
+ iic_write_ex(DITHER_SEL1_SPP, 0);
+ break;
+ }
+
+ }
+
+ if((pOutput_Info->channel & CHANNEL_VGA)&&((pOutput_Info->channel & CHANNEL_HDMI)==0x00))
+ {
+
+
+ iic_write_ex(HPO_O, 1);
+ iic_write_ex(VPO_O, 1);
+ iic_write_ex(DEPO_O, 0);
+ }
+ else if((pOutput_Info->channel & CHANNEL_VGA)&&(pOutput_Info->channel & CHANNEL_HDMI))
+ {
+
+ iic_write_ex(HPO_O, 1);
+ iic_write_ex(VPO_O, 0);
+ iic_write_ex(DEPO_O, 0);
+ }
+
+ if((pOutput_Info->channel & CHANNEL_HDMI) && ((pOutput_Info->channel & CHANNEL_VGA) == 0x00))
+ {
+ iic_write_ex(HDMIIN_HSP, pHdmiFmt->hs_pol ? 1:0);
+ iic_write_ex(HDMIIN_VSP, pHdmiFmt->vs_pol ? 1:0);
+ iic_write_ex(HDMIIN_DEP, 0);
+ }
+ if((pOutput_Info->channel & CHANNEL_HDMI)&&(pOutput_Info->channel & CHANNEL_VGA))
+ {
+ iic_write_ex(HDMIIN_HSP, 0);
+ iic_write_ex(HDMIIN_VSP, 1);
+ iic_write_ex(HDMIIN_DEP, 1);
+ }
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ {
+
+ hd_dvib = pHdmiFmt->is_dvi_mode ? 0 : 1;
+ iic_write_ex(HD_DVIB, hd_dvib);
+
+ switch(pHdmiFmt->format_index)
+ {
+ case 5:
+ case 6:
+ case 7:
+ case 10:
+ case 11:
+ case 20:
+ case 21:
+ case 22:
+ case 25:
+ case 26:
+ intlc = 1;
+ break;
+ default:
+ intlc = 0;
+ break;
+ }
+ iic_write_ex(INTLC, intlc);
+
+ copy = 1;
+ iic_write_ex(COPY, copy);
+
+ hd_lv_pol = pHdmiFmt->data_pol_invert;
+ iic_write_ex(HD_LV_POL, hd_lv_pol);
+
+ hd_lv_seq = pHdmiFmt->channel_swap;
+ iic_write_ex(HD_LV_SEQ, hd_lv_seq);
+
+ hdmi_lvds_sel = 1;
+ iic_write_ex(HDMI_LVDS_SEL, hdmi_lvds_sel);
+
+
+ if (pOutput_Info->timing.ha > 720) {
+ pOutput_Info->hdmi_fmt.hs_pol = POL_HIGH;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_HIGH;
+ if(pOutput_Info->timing.ha == 1440)
+ {
+ pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+ }
+ }
+ else {
+
+ pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+ }
+
+ hsp = pHdmiFmt->hs_pol;
+ vsp = pHdmiFmt->vs_pol;
+ iic_write_ex(HSP, hsp);
+ iic_write_ex(VSP, vsp);
+
+
+ switch(pHdmiFmt->format_index)
+ {
+ case 1:
+ case 2:
+ case 17:
+ {
+ if(pHdmiFmt->aspect_ratio == AS_RATIO_16_9)
+ {
+ g_nLastError = ERR_ASPECT_RATIO_NOMATCH;
+ return ch_false;
+ }
+ }
+ break;
+ case 4:
+ case 5:
+ case 16:
+ case 19:
+ case 20:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ {
+ if(pHdmiFmt->aspect_ratio == AS_RATIO_4_3)
+ {
+ g_nLastError = ERR_ASPECT_RATIO_NOMATCH;
+ return ch_false;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ m1m0 = pHdmiFmt->aspect_ratio;
+ iic_write_ex(M1M0, m1m0);
+
+ c1c0 = 2;
+ iic_write_ex(C1C0, c1c0);
+
+ vic = pHdmiFmt->format_index;
+ iic_write_ex(VIC, vic);
+ }
+
+ if(pOutput_Info->channel & CHANNEL_VGA){
+ intlc = 0;
+ }
+
+ iic_write_ex(INTLC, intlc);
+
+
+ iic_write( 0x3, 0x1);
+ iic_write( 0x23, 0x63);
+ iic_write( 0x3, 0x0);
+
+ return ch_true;
+}
+
+ch_bool set_prefer_info(PREFER_INFO* pPrefer_Info)
+{
+ uint8 hsync_cnt_th, prbs_set_sel;
+ uint8 dbp ;
+
+ iic_write_ex(MCLK, pPrefer_Info->mclk_khz);
+
+ iic_write_ex(UCLKOD_SEL, pPrefer_Info->uclkod_sel);
+ iic_write_ex(DAT16_32B, pPrefer_Info->dat16_32b);
+ iic_write_ex(TRUE24, pPrefer_Info->true24);
+ iic_write_ex(TRUE_COM, pPrefer_Info->true_com);
+
+ hsync_cnt_th = pPrefer_Info->lvds_out_hs_tolerance;
+ iic_write_ex(HSYNC_CNT_TH_SPP, hsync_cnt_th);
+ prbs_set_sel = pPrefer_Info->lvds_out_reset_bit_sel;
+ iic_write_ex(PRBS_SET_SEL_SPP, prbs_set_sel);
+
+ dbp = pPrefer_Info->dither_filter_enable ? 0 : 1;
+ iic_write_ex(DBP, dbp);
+
+
+
+ iic_write_ex(TXTEN, pPrefer_Info->text_enhancement);
+
+
+
+
+
+
+ return ch_true;
+}
+
+
+ch_bool cal_and_set_clk_pll(DEV_CONTEXT* pDevContext)
+{
+ uint8 pll1n2_reg, pll1n2_div;
+ uint8 pll1n3_reg, pll1n3_div;
+ uint8 pll1n1_reg = 0, pll1n1_div = 0;
+ uint8 pll3n8_reg, pll3n8_div;
+ uint8 pll2n5_reg, pll2n5_div;
+ uint8 pll2n6_reg, pll2n6_div;
+ uint8 pll2n7_reg, pll2n7_div;
+ uint8 dmxtal_reg, dmxtal_div;
+
+ uint32 a2_reg = 0;
+ uint32 a1_reg = 0;
+ uint32 a3_reg = 0;
+ uint32 uclk2d_reg = 0;
+ uint8 uclksec_reg = 0;
+ uint8 dri_pll_n1_reg;
+ uint8 dri_pll_n3_reg;
+
+ uint32 val_t;
+ uint32 val_t1, val_t2;
+
+ uint8 gcksel = 0;
+ uint8 tsten1 = 0;
+ uint8 REV_ID;
+ uint64 temp1;
+
+
+ INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+ OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+ I2CWrite(pDevContext,0x03, 0x04);
+ REV_ID = I2CRead(pDevContext,0x51) & 0x0F;
+
+
+
+ if(pPrefer_Info->reset == 1)
+ {
+ I2CWrite(pDevContext,0x03, 0x01);
+ I2CWrite(pDevContext,0x14, I2CRead(pDevContext,0x14) | 0x40);
+ I2CWrite(pDevContext,0x03, 0x04);
+ I2CWrite(pDevContext,0x54, I2CRead(pDevContext,0x54) | 0x40);
+ tsten1 = 0x40;
+ gcksel = 0x40;
+ iic_write_ex(GCKSEL, 1);
+ iic_write_ex(TSTEN1, 1);
+ }
+
+
+ else if((pPrefer_Info->reset == 0) || (REV_ID >= 0x01))
+ {
+ I2CWrite(pDevContext,0x03, 0x01);
+ I2CWrite(pDevContext,0x14, I2CRead(pDevContext,0x14) & 0xBF);
+ I2CWrite(pDevContext,0x03, 0x04);
+ I2CWrite(pDevContext,0x54, 0x40 | (I2CRead(pDevContext,0x54) & 0xBF));
+ tsten1=0x00;
+ gcksel=0x00;
+ iic_write_ex(GCKSEL, 1);
+ iic_write_ex(TSTEN1, 0);
+ }
+
+
+ pll1n2_div = 4;
+ pll1n3_div = 8;
+ if(!convert_pll1n2_div(ch_false, &pll1n2_reg, &pll1n2_div))
+ {
+ g_nLastError = ERR_PLL1N2_WRONG;
+ return ch_false;
+ }
+ if(!convert_pll1n3_div(ch_false, &pll1n3_reg, &pll1n3_div))
+ {
+ g_nLastError = ERR_PLL1N3_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(PLL1N2, pll1n2_reg);
+ iic_write_ex(PLL1N3, pll1n3_reg);
+
+
+
+ if(((gcksel == 0x40)&&(tsten1 == 0x00)) || ((gcksel == 0x00)&&(tsten1 == 0x00)))
+ {
+
+
+
+
+ pll1n1_div = 8;
+ pll1n1_reg = 3;
+
+
+
+
+
+
+
+ }
+ else if((gcksel == 0x40)&&(tsten1 == 0x40)){
+ for(pll1n1_div=1; pll1n1_div<=64; pll1n1_div<<=1)
+ {
+ val_t = pInput_Info->rx_clk_khz / pll1n1_div;
+ if(val_t >= 2300 && val_t <= 4600)
+ break;
+ }
+ if(pll1n1_div > 64)
+ {
+ g_nLastError = ERR_PLL1N1_WRONG;
+ return ch_false;
+ }
+ if(!convert_pll1n1_div(ch_false, &pll1n1_reg, &pll1n1_div))
+ {
+ g_nLastError = ERR_PLL1N1_WRONG;
+ return ch_false;
+ }
+ }
+
+ iic_write_ex(PLL1N1, pll1n1_reg);
+
+
+ for(pll3n8_div=1; pll3n8_div<=8; pll3n8_div<<=1)
+ {
+ val_t = pPrefer_Info->mclk_khz * pll3n8_div / 64;
+ if(val_t >= 2300 && val_t <= 2600)
+ break;
+ }
+ if(pll3n8_div > 8)
+ {
+ g_nLastError = ERR_PLL3N8_WRONG;
+ return ch_false;
+ }
+ if(!convert_pll3n8_div(ch_false, &pll3n8_reg, &pll3n8_div))
+ {
+ g_nLastError = ERR_PLL3N8_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(PLL3N8, pll3n8_reg);
+
+
+
+ if((gcksel == 0x40)&&(tsten1 == 0x40)){
+ val_t1 = (pInput_Info->rx_clk_khz << 12);
+ val_t2 = (pll1n1_div * pll3n8_div * pPrefer_Info->mclk_khz);
+ a2_reg = (val_t1 % val_t2) ? (val_t1 / val_t2 + 1) : (val_t1 / val_t2);
+
+ }else if(((gcksel == 0x40)&&(tsten1 == 0x00))||((gcksel == 0x00)&&(tsten1 == 0x00))){
+ val_t1 = (27000 << 12);
+ val_t2 = (pll1n1_div * pll3n8_div * pPrefer_Info->mclk_khz);
+
+
+
+
+ a2_reg = (val_t1 % val_t2) ? (val_t1 / val_t2 + 1) : (val_t1 / val_t2);
+ if(pOutput_Info->uclk_khz == 148500){
+ a2_reg = 0x73;
+ }
+ }
+
+ iic_write_ex(A2, a2_reg);
+
+
+ if(pInput_Info->audio_type)
+ {
+ uclksec_reg = pOutput_Info->uclk_khz / 10;
+ }
+ else
+ {
+
+
+
+
+
+ if( (0x40==gcksel)&&(0x40==tsten1) )
+ {
+ uclk2d_reg = (pInput_Info->rx_clk_khz * 2 * pll1n2_div * pll1n3_div) / (pll1n1_div * 10);
+ }
+ if(0x00==tsten1 )
+ {
+ uclk2d_reg = (27000 * 2 * pll1n2_div * pll1n3_div) / (pll1n1_div * 10);
+ }
+
+ }
+ iic_write_ex(PCLK_NUM, uclk2d_reg);
+
+
+
+
+
+ if((pOutput_Info->uclk_khz == 54000 ||
+ pOutput_Info->uclk_khz == 72000 ||
+ pOutput_Info->uclk_khz == 74250 ||
+ pOutput_Info->uclk_khz == 108000 ||
+ pOutput_Info->uclk_khz == 148500 ))
+ {
+ uclksec_reg = 1;
+ }
+ else
+ {
+ uclksec_reg = 0;
+ }
+ iic_write_ex(UCLKSEC, uclksec_reg);
+
+
+ if(uclksec_reg == 0)
+ {
+ pll2n6_div = 8;
+ pll2n7_div = 8;
+ for(pll2n5_div=1; pll2n5_div<=8; ++pll2n5_div)
+ {
+ val_t = pOutput_Info->uclk_khz * pll2n5_div / 64;
+ if(val_t >= 2300 && val_t <= 4600)
+ break;
+ }
+ if(pll2n5_div > 8)
+ {
+ g_nLastError = ERR_PLL2N5_WRONG;
+ return ch_false;
+ }
+ dmxtal_div = 1;
+
+ if(pPrefer_Info->uclkod_sel == 1)
+ {
+ if((gcksel == 0x40)&&(tsten1 == 0x40)){
+ temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+ do_div(temp1 , pInput_Info->rx_clk_khz);
+ a1_reg = (uint32)temp1;
+#else
+ a1_reg = (uint32)((uint64)temp1 / pInput_Info->rx_clk_khz);
+#endif
+ PD_DEBUG ("#1 a1_reg = 0x%.8X\n", a1_reg);
+ } else if((gcksel == 0x40)&&(tsten1 == 0x00)){
+ temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+ do_div(temp1 , (uint32)27000);
+ a1_reg = (uint32)temp1;
+#else
+ a1_reg = (uint32)((uint64)temp1 / (uint32)27000);
+#endif
+ PD_DEBUG ("#2 a1_reg = 0x%.8X\n", a1_reg);
+ }else if((gcksel == 0x00)&&(tsten1 == 0x00)){
+ temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+ do_div(temp1 , (uint32)27000);
+ a1_reg = (uint32)temp1;
+#else
+ a1_reg = (uint32)((uint64)temp1 / (uint32)27000);
+#endif
+ PD_DEBUG ("#3 a1_reg = 0x%.8X\n", a1_reg);
+ }
+ iic_write_ex(A1, a1_reg);
+ }
+ else
+ {
+ if((gcksel == 0x40)&&(tsten1 == 0x40))
+ a3_reg = pInput_Info->rx_clk_khz * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+ else if((gcksel == 0x40)&&(tsten1 == 0x00))
+ a3_reg = 27000 * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+ else if((gcksel == 0x00)&&(tsten1 == 0x00))
+ a3_reg = 27000 * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+
+ iic_write_ex(A3, a3_reg);
+ }
+ }
+ else
+ {
+ switch(pOutput_Info->uclk_khz)
+ {
+ case 54000:
+ dmxtal_div = 6;
+ pll2n7_div = 8;
+ pll2n6_div = 6;
+ pll2n5_div = 4;
+ break;
+ case 72000:
+ dmxtal_div = 6;
+ pll2n7_div = 8;
+ pll2n6_div = 6;
+ pll2n5_div = 3;
+ break;
+ case 74250:
+ dmxtal_div = 6;
+ pll2n7_div = 11;
+ pll2n6_div = 6;
+ pll2n5_div = 4;
+ break;
+ case 108000:
+ dmxtal_div = 6;
+ pll2n7_div = 8;
+ pll2n6_div = 6;
+ pll2n5_div = 2;
+ break;
+ case 148500:
+
+
+
+
+ dmxtal_div = 6;
+ pll2n6_div = 6;
+
+
+
+
+
+ pll2n7_div = 11;
+ pll2n5_div = 2;
+ break;
+ default:
+ return ch_false;
+ }
+ }
+ if(!convert_pll2n5_div(ch_false, &pll2n5_reg, &pll2n5_div))
+ {
+ g_nLastError = ERR_PLL2N5_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(PLL2N5, pll2n5_reg & 0x07);
+ iic_write_ex(PLL2N53, pll2n5_reg >> 3 & 0x01);
+ if(!convert_pll2n6_div(ch_false, &pll2n6_reg, &pll2n6_div))
+ {
+ g_nLastError = ERR_PLL2N6_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(PLL2N6, pll2n6_reg);
+ if(!convert_pll2n7_div(ch_false, &pll2n7_reg, &pll2n7_div))
+ {
+ g_nLastError = ERR_PLL2N7_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(PLL2N7, pll2n7_reg);
+ if(!convert_dmxtal_div(ch_false, &dmxtal_reg, &dmxtal_div))
+ {
+ g_nLastError = ERR_DMXTAL_WRONG;
+ return ch_false;
+ }
+ iic_write_ex(DIVXTAL, dmxtal_reg);
+
+
+ if(pInput_Info->rx_clk_khz > 40000)
+ {
+ iic_write_ex(TXPLL_FFD, 1);
+ }
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ {
+ val_t = pOutput_Info->uclk_khz;
+ if(val_t < 25000 || val_t > 165000)
+ {
+ g_nLastError = ERR_HDMI_CLOCK_NO_SUPPORT;
+ return ch_false;
+ }
+ if(val_t <= 40000)
+ {
+ dri_pll_n1_reg = 0;
+ dri_pll_n3_reg = 0;
+ }
+ else if(val_t < 80000)
+ {
+ dri_pll_n1_reg = 1;
+ dri_pll_n3_reg = 1;
+ }
+ else
+ {
+ dri_pll_n1_reg = 2;
+ dri_pll_n3_reg = 2;
+ }
+ iic_write_ex(DRI_PLL_N1, dri_pll_n1_reg);
+ iic_write_ex(DRI_PLL_N3, dri_pll_n3_reg);
+ }
+
+
+ iic_write_ex(CK_TVINV, 1);
+
+ return ch_true;
+}
+
+ch_bool cal_and_set_scaler(DEV_CONTEXT* pDevContext)
+{
+ uint8 wrlen_reg;
+ uint32 frame_rate_in, frame_rate_out, field_rate_out;
+ uint32 hai_down, hai_sdram;
+ uint8 fltbp2_reg, fltbp1_reg;
+ uint8 dnsmpen_reg;
+ uint32 hadwn_reg = 0;
+ uint8 blk_h_reg;
+ uint32 fba_inc_reg;
+ uint8 sfm_reg;
+ uint8 thren_reg;
+ uint32 thrrl_reg;
+ uint8 lnsel_reg;
+ uint8 wrfast_reg;
+ uint8 chg_hl_reg;
+ uint8 vsmst_reg;
+
+ uint32 val_t;
+ uint32 hao_t;
+ uint32 vao_t;
+ uint32 vai_t;
+
+
+ INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+ OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+
+ wrlen_reg = 0;
+ iic_write_ex(WRLEN, wrlen_reg);
+
+
+ frame_rate_in = ((pInput_Info->rx_clk_khz * 10000) / pInput_Info->timing.ht) * 10 / pInput_Info->timing.vt;
+ frame_rate_out = ((pOutput_Info->uclk_khz * 10000) / pOutput_Info->timing.ht) * 10 / pOutput_Info->timing.vt;
+ field_rate_out = iic_read_ex(INTLC) ? (frame_rate_out * 2) : (frame_rate_out);
+
+
+ hai_down = pInput_Info->timing.ha;
+ if(pOutput_Info->ds_percent_h)
+ {
+ hao_t = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+ }
+ else
+ {
+ hao_t = pOutput_Info->timing.ha;
+ }
+ hao_t = hao_t + (hao_t % 2);
+ if(hai_down > hao_t)
+ {
+ dnsmpen_reg = 1;
+ hadwn_reg = hao_t;
+ hai_down = hadwn_reg;
+ fltbp2_reg = 1;
+ fltbp1_reg = 1;
+ }
+ else
+ {
+ dnsmpen_reg = 0;
+ fltbp2_reg = 1;
+ fltbp1_reg = 1;
+ }
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ val_t = 720;
+ }
+ else
+ {
+ if(pPrefer_Info->dat16_32b)
+ {
+ val_t = 720;
+ }
+ else
+ {
+ val_t = pPrefer_Info->true24 ? 720 : 1440;
+ }
+ }
+ if(hai_down > val_t && (pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip))
+ {
+ dnsmpen_reg = 1;
+ hadwn_reg = val_t;
+ hai_down = hadwn_reg;
+ fltbp2_reg = 1;
+ fltbp1_reg = 1;
+ }
+ iic_write_ex(DNSMPEN, dnsmpen_reg);
+ iic_write_ex(HADWSPP, hadwn_reg);
+
+ if(pInput_Info->timing.ha * 100 / hao_t > pPrefer_Info->hscale_ratio_gate)
+ {
+ fltbp1_reg = 0;
+ }
+ iic_write_ex(FLTBP2, fltbp2_reg);
+ iic_write_ex(FLTBP1, fltbp1_reg);
+
+
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ val_t = 100;
+ }
+ else
+ {
+ if(pPrefer_Info->dat16_32b)
+ {
+ val_t = 100;
+ }
+ else if(pPrefer_Info->true24)
+ {
+ val_t = 100;
+ }
+ else
+ {
+ val_t = pPrefer_Info->true_com ? 75 : 50;
+ }
+ }
+ if(val_t == 75)
+ {
+ hai_sdram = (hai_down / 4) * 3 + (hai_down % 4);
+ }
+ else
+ {
+ hai_sdram = hai_down * val_t / 100;
+ }
+ if(pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip)
+ {
+ blk_h_reg = 45;
+ }
+ else if(hai_sdram <= 720 && pInput_Info->timing.va <= 720)
+ {
+ blk_h_reg = 45;
+ }
+ else
+ {
+ blk_h_reg = hai_sdram / 16;
+ blk_h_reg = (hai_sdram % 16) ? (blk_h_reg + 1) : blk_h_reg;
+ }
+ iic_write_ex(BLK_H, blk_h_reg);
+
+
+ if((pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270) && pPrefer_Info->true24 == 0 && pPrefer_Info->true_com == 0 && pPrefer_Info->dat16_32b == 0)
+ {
+ vai_t = pInput_Info->timing.va / 2;
+ }
+ else
+ {
+ vai_t = pInput_Info->timing.va;
+ }
+ val_t = (vai_t % 16) ? (vai_t / 16 + 1) : (vai_t / 16);
+ fba_inc_reg = blk_h_reg * val_t;
+ if(fba_inc_reg > 2048)
+ {
+ sfm_reg = 1;
+ thren_reg = 1;
+ val_t = (frame_rate_in * 100) / field_rate_out;
+ if(val_t > 100)
+ {
+
+
+ thrrl_reg = pInput_Info->timing.vt * (100 - 10000 / val_t) / 100 + THRRL_ADJUST_DEF;
+ }
+ else
+ {
+ thrrl_reg = pInput_Info->timing.vt * (100 - val_t) / 100 + THRRL_ADJUST_DEF;
+ }
+ }
+ else
+ {
+ sfm_reg = 0;
+ thren_reg = 0;
+ thrrl_reg = 0;
+ }
+ iic_write_ex(FBA_INC, fba_inc_reg);
+ iic_write_ex(SFM, sfm_reg);
+ iic_write_ex(THREN, thren_reg);
+ iic_write_ex(THRRL, thrrl_reg);
+
+
+ if(pOutput_Info->ds_percent_v)
+ {
+ vao_t = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+ }
+ else
+ {
+ vao_t = pOutput_Info->timing.va;
+ }
+ vao_t = vao_t + (vao_t % 2);
+ val_t = iic_read_ex(INTLC) ? (vao_t / 2) : vao_t;
+ if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+ {
+ if(hai_down <= val_t)
+ lnsel_reg = 3;
+ else
+ lnsel_reg = 1;
+ }
+ else
+ {
+ if(pInput_Info->timing.va <= val_t)
+ lnsel_reg = 3;
+ else
+ lnsel_reg = 1;
+ }
+ if(pPrefer_Info->scale_line_adjust)
+ {
+ lnsel_reg++;
+ if((pOutput_Info->ds_percent_v >= 2) && (pOutput_Info->ds_percent_v <= 12) &&
+ (pOutput_Info->ds_percent_h <= 12) &&
+
+ (pOutput_Info->channel & CHANNEL_VGA) &&
+ (pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 960) &&
+ (pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)&&
+ (pInput_Info->timing.ha == 1280) && (pInput_Info->timing.va == 1024)&&
+ (pInput_Info->timing.hz >= 49)){
+
+ lnsel_reg++;
+
+ }
+
+
+
+
+ if((pOutput_Info->ds_percent_v >= 2) && (pOutput_Info->ds_percent_v <= 12) &&
+ (pOutput_Info->ds_percent_h >= 0) && (pOutput_Info->ds_percent_h <= 12) &&
+ (pOutput_Info->channel & CHANNEL_VGA) &&
+ (pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 1024) &&
+ (pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)){
+
+ lnsel_reg++;
+
+ }
+
+ if((pOutput_Info->ds_percent_v >= 2 ) &&
+ (pOutput_Info->ds_percent_h >= 2 ) && (pOutput_Info->channel & CHANNEL_VGA) &&
+ (pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 1024) &&
+ (pOutput_Info->timing.hz == 75) && (pInput_Info->rx_clk_khz >= 75428)){
+
+ lnsel_reg++;
+ }
+
+ if((pOutput_Info->ds_percent_v >= 6 ) &&
+ (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+ (pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+ (pOutput_Info->timing.hz == 50) && (pInput_Info->rx_clk_khz >= 75428)){
+
+ lnsel_reg++;
+ }
+ if((pOutput_Info->ds_percent_v >= 6 ) &&
+ (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+ (pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+ (pOutput_Info->timing.hz == 59) && (pInput_Info->rx_clk_khz >= 75428)){
+
+ lnsel_reg++;
+ }
+ if((pOutput_Info->ds_percent_v >= 6 ) &&
+ (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+ (pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+ (pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)){
+
+ lnsel_reg++;
+ }
+ }
+ iic_write_ex(LNSEL, lnsel_reg);
+
+
+ if(frame_rate_in >= field_rate_out)
+ wrfast_reg = 1;
+ else
+ wrfast_reg = 0;
+ iic_write_ex(WRFAST, wrfast_reg);
+
+
+ chg_hl_reg = ( ( (pPrefer_Info->dat16_32b == 0) &&
+ (pPrefer_Info->true24 == 0) &&
+ (pPrefer_Info->true_com == 0) &&
+ ( (pOutput_Info->rotate == 0) &&
+ (pOutput_Info->h_flip == 1) ) ) ||
+ ( (pOutput_Info->rotate == 1) &&
+ (pOutput_Info->h_flip == 0) ) ||
+ ( (pOutput_Info->rotate == 3) &&
+ (pOutput_Info->h_flip == 1) ) ||
+ ( (pOutput_Info->rotate == 2) &&
+ (pOutput_Info->h_flip == 0) ) ) ? 1 : 0;
+ iic_write_ex(CHG_HL, chg_hl_reg);
+
+
+ vsmst_reg = 2;
+ iic_write_ex(VSMST, vsmst_reg);
+
+ return ch_true;
+}
+
+ch_bool post_cal_and_set(DEV_CONTEXT* pDevContext)
+{
+ uint32 hdinc_reg, hdinca_reg, hdincb_reg;
+ uint32 hinc_reg, hinca_reg, hincb_reg;
+ uint32 vinc_reg, vinca_reg, vincb_reg;
+
+ uint32 val_t;
+ uint64 temp1;
+
+
+
+ I2CWrite(pDevContext,0x03, 0x04);
+
+ val_t = I2CRead(pDevContext,0x2A);
+ hinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x2B) & 0x07);
+
+ val_t = I2CRead(pDevContext,0x2C);
+ hincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x2D) & 0x07);
+
+ val_t = I2CRead(pDevContext,0x2E);
+ vinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x2F) & 0x07);
+
+ val_t = I2CRead(pDevContext,0x30);
+ vincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x31) & 0x07);
+
+ val_t = I2CRead(pDevContext,0x32);
+ hdinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x33) & 0x07);
+
+ val_t = I2CRead(pDevContext,0x34);
+ hdincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x35) & 0x07);
+
+
+ I2CWrite(pDevContext,0x03, 0x04);
+
+
+ if(iic_read_ex(DNSMPEN))
+ {
+ if(hdincb_reg == 0)
+ {
+ g_nLastError = ERR_CAL_INC_DIV_ZERO;
+ return ch_false;
+ }
+ temp1 = ((uint64)hdinca_reg) * (1 << 20);
+#ifdef T_LINUX
+ do_div(temp1 , hdincb_reg);
+ hdinc_reg = (uint32)temp1;
+#else
+ hdinc_reg = (uint32)((uint64)temp1 / hdincb_reg);
+#endif
+
+
+ PD_DEBUG ("#1 hdinc_reg = 0x%.8X\n", hdinc_reg);
+ I2CWrite(pDevContext,0x3C, (hdinc_reg >> 16) & 0xFF);
+ I2CWrite(pDevContext,0x3D, (hdinc_reg >> 8) & 0xFF);
+ I2CWrite(pDevContext,0x3E, (hdinc_reg >> 0) & 0xFF);
+ }
+ if(hincb_reg == 0 || vincb_reg == 0)
+ {
+ g_nLastError = ERR_CAL_INC_DIV_ZERO;
+ return ch_false;
+ }
+
+ if(hinca_reg > hincb_reg)
+ {
+ g_nLastError = ERR_CAL_INC_NO_MATH;
+ return ch_false;
+ }
+
+ temp1 = (uint64)hinca_reg * (1 << 20);
+#ifdef T_LINUX
+ do_div(temp1 , hincb_reg);
+ hinc_reg = (uint32)temp1;
+#else
+ hinc_reg = (uint32)((uint64)temp1 / hincb_reg);
+#endif
+
+PD_DEBUG ("#2 hinc_reg = 0x%.8X\n", hinc_reg);
+
+ temp1 = (uint64)vinca_reg * (1 << 20);
+#ifdef T_LINUX
+ do_div( temp1 , vincb_reg);
+ vinc_reg = (uint32)temp1;
+#else
+ vinc_reg = (uint32)((uint64)temp1 / vincb_reg);
+#endif
+
+ PD_DEBUG ("#1 vinc_reg = 0x%.8X\n", vinc_reg);
+
+ I2CWrite(pDevContext,0x36, (hinc_reg >> 16) & 0xFF);
+ I2CWrite(pDevContext,0x37, (hinc_reg >> 8) & 0xFF);
+ I2CWrite(pDevContext,0x38, (hinc_reg >> 0) & 0xFF);
+
+ I2CWrite(pDevContext,0x39, (vinc_reg >> 16) & 0xFF);
+ I2CWrite(pDevContext,0x3A, (vinc_reg >> 8) & 0xFF);
+ I2CWrite(pDevContext,0x3B, (vinc_reg >> 0) & 0xFF);
+
+ return ch_true;
+}
+
+
+
+
+
+
+ch_bool cal_and_set_power(DEV_CONTEXT* pDevContext)
+{
+
+ uint8 hdmi_pd = 1;
+ uint8 i2s_pd = 1;
+ uint8 spdif_pd = 1;
+ uint8 auddac=1;
+ uint8 dri_pd = 1;
+ uint8 dri_pd_ser = 1;
+ uint8 dri_pd_pll = 1;
+ uint8 dri_pddri = 7;
+ uint8 cec_pd = 1;
+ uint8 pd_ddc = 1;
+
+
+ uint8 lvds_pd = 1;
+ uint8 rx_pd = 63;
+ uint8 rxpll_pd = 1;
+ uint8 txpll_pd = 1;
+ uint8 txdrv_pd = 1;
+ uint8 txser_pd = 1;
+
+
+
+
+
+ uint8 icen0 =1;
+
+
+
+ uint8 vga_pd = 1;
+ uint8 pddac = 7;
+
+ uint8 pdpll1 = 1;
+ uint8 pdpll0 = 1;
+
+
+ uint8 pd_prom = 0;
+ uint8 pdmio = 1;
+ uint8 pdio = 1;
+ uint8 hpd_pd = 0;
+
+
+ uint8 sclpd = 1;
+ uint8 sdpd = 1;
+ uint8 mempd = 1;
+ uint8 dacsence = 1;
+
+ uint8 gckoff = 0;
+
+
+ uint8 dispon = 0;
+
+
+
+
+
+ INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+ OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+
+ iic_write_ex(CRYS_FREQ_SPP, 27000);
+ iic_write_ex(I2SCK_SEC, 1);
+ iic_write_ex(SP_EN, 0);
+ iic_write_ex(HARD_SOFTB, 1);
+ iic_write_ex(MULT_I2CEN, 0);
+
+
+
+ if(pOutput_Info->channel & CHANNEL_LVDS)
+ {
+ lvds_pd = 0;
+ rx_pd = 0;
+ rxpll_pd = 0;
+ txpll_pd = 0;
+ txdrv_pd = 0;
+ txser_pd = 0;
+ pdio = 0;
+
+
+ }
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ {
+ hdmi_pd = 0;
+ if(pInput_Info->audio_type == 1)
+ i2s_pd = 0;
+ else {
+ spdif_pd = 0;
+ auddac=0;
+ }
+ dri_pd = 0;
+ dri_pddri = 0;
+ dri_pd_ser = 0;
+ dri_pd_pll = 0;
+ pd_ddc = 0;
+
+ vga_pd = 0;
+ pdmio = 0;
+ sclpd = 0;
+ sdpd = 0;
+ gckoff = 0;
+ mempd = 0;
+
+ rx_pd = 0;
+ rxpll_pd = 0;
+
+ pdpll0 = 0;
+ pdpll1 = 0;
+ icen0 =0;
+ pdio = 0;
+
+ hpd_pd = 0;
+
+ }
+ if(pOutput_Info->channel & CHANNEL_VGA)
+ {
+ vga_pd = 0;
+ pdmio = 0;
+ sclpd = 0;
+ sdpd = 0;
+ gckoff = 0;
+ mempd = 0;
+
+ rx_pd = 0;
+ rxpll_pd = 0;
+
+ pdpll0 = 0;
+ pdpll1 = 0;
+ icen0 =0;
+ pdio = 0;
+
+ dispon = 1;
+ dri_pd_pll = 0;
+
+ dacsence=1;
+ pddac = 0;
+ }else{
+
+
+
+ if(pPrefer_Info->vga_enable)
+ dispon = 0;
+ }
+
+
+ iic_write_ex(HDMI_PD, hdmi_pd);
+ iic_write_ex(I2S_PD, i2s_pd);
+ iic_write_ex(SPDIF_PD, spdif_pd);
+
+ iic_write_ex(AUDDAC, auddac);
+
+ iic_write_ex(DRI_PD, dri_pd);
+ iic_write_ex(DRI_PD_SER, dri_pd_ser);
+ iic_write_ex(DRI_PD_PLL, dri_pd_pll);
+ iic_write_ex(DRI_PDDRI, dri_pddri);
+ iic_write_ex(CEC_PD, cec_pd);
+ iic_write_ex(PD_DDC, pd_ddc);
+ iic_write_ex(LVDS_PD, lvds_pd);
+ iic_write_ex(RX_PD, rx_pd);
+ iic_write_ex(RXPLL_PD, rxpll_pd);
+ iic_write_ex(TXPLL_PD, txpll_pd);
+ iic_write_ex(TXDRV_PD, txdrv_pd);
+ iic_write_ex(TXSER_PD, txser_pd);
+ iic_write_ex(VGA_PD, vga_pd);
+ iic_write_ex(PDDAC, pddac);
+ iic_write_ex(PDPLL1, pdpll1);
+ iic_write_ex(PDPLL0, pdpll0);
+ iic_write_ex(ICEN0, icen0);
+ iic_write_ex(PD_PROM, pd_prom);
+ iic_write_ex(PDMIO, pdmio);
+ iic_write_ex(PDIO, pdio);
+ iic_write_ex(HPD_PD, hpd_pd);
+ iic_write_ex(SCLPD, sclpd);
+ iic_write_ex(SDPD, sdpd);
+ iic_write_ex(MEMPD, mempd);
+ iic_write_ex(DISPON, dispon);
+
+ iic_write_ex(DACSENCE, dacsence);
+ iic_write_ex(GCKOFF, gckoff);
+ iic_write_ex(ZRCTS, 0);
+
+ return ch_true;
+}
+
+ch_bool convert_pll1n1_div(ch_bool pll1n1_to_div, uint8* pll1n1_addr, uint8* div_addr)
+{
+ uint8 val_t;
+
+ if(pll1n1_to_div)
+ {
+ if((*pll1n1_addr) <= 5)
+ {
+ (*div_addr)= 1<<(*pll1n1_addr);
+ }
+ else if((*pll1n1_addr) == 6 || (*pll1n1_addr) == 7)
+ {
+ (*div_addr) = 64;
+ }
+ else
+ {
+ return ch_false;
+ }
+ }
+ else
+ {
+ for(val_t=1; val_t<=6; ++val_t)
+ {
+ if(*div_addr == (1 << val_t))
+ {
+ *pll1n1_addr = val_t;
+ return ch_true;
+ }
+ }
+ return ch_false;
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll1n2_div(ch_bool pll1n2_to_div, uint8* pll1n2_addr, uint8* div_addr)
+{
+ uint8 val_t;
+
+ if(pll1n2_to_div)
+ {
+ if((*pll1n2_addr) <= 3)
+ {
+ *div_addr = 1 << (*pll1n2_addr);
+ }
+ else if((4 == (*pll1n2_addr)) || (6 == (*pll1n2_addr)))
+ {
+ (*div_addr) = 16;
+ }
+ else if((5 == (*pll1n2_addr)) || (7 == (*pll1n2_addr)))
+ {
+ (*div_addr) = 32;
+ }
+ else
+ {
+ return ch_false;
+ }
+ }
+ else
+ {
+ for(val_t=0; val_t<=5; ++val_t)
+ {
+ if(*div_addr == (1 << val_t))
+ {
+ *pll1n2_addr = val_t;
+ return ch_true;
+ }
+ }
+ return ch_false;
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll1n3_div(ch_bool pll1n3_to_div, uint8* pll1n3_addr, uint8* div_addr)
+{
+ uint8 val_t;
+
+ if(pll1n3_to_div)
+ {
+ if((*pll1n3_addr) <= 3)
+ {
+ *div_addr = 1 << (*pll1n3_addr);
+ }
+ else if((4 == (*pll1n3_addr)) || (6 == (*pll1n3_addr)))
+ {
+ (*div_addr) = 16;
+ }
+ else if((5 == (*pll1n3_addr)) || (7 == (*pll1n3_addr)))
+ {
+ (*div_addr) = 32;
+ }
+ else
+ {
+ return ch_false;
+ }
+ }
+ else
+ {
+ for(val_t=0; val_t<=5; ++val_t)
+ {
+ if(*div_addr == (1 << val_t))
+ {
+ *pll1n3_addr = val_t;
+ return ch_true;
+ }
+ }
+ return ch_false;
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll2n5_div(ch_bool pll2n5_to_div, uint8* pll2n5_addr, uint8* div_addr)
+{
+ if(pll2n5_to_div)
+ {
+ switch(*pll2n5_addr)
+ {
+ case 0:
+ *div_addr = 1;
+ break;
+ case 4:
+ *div_addr = 2;
+ break;
+ case 1:
+ *div_addr = 3;
+ break;
+ case 8:
+ *div_addr = 4;
+ break;
+ case 2:
+ *div_addr = 5;
+ break;
+ case 5:
+ *div_addr = 6;
+ break;
+ case 3:
+ *div_addr = 7;
+ break;
+ case 12:
+ *div_addr = 8;
+ break;
+ default :
+ return ch_false;
+ }
+ }
+ else
+ {
+ switch(*div_addr)
+ {
+ case 1:
+ *pll2n5_addr = 0;
+ break;
+ case 2:
+ *pll2n5_addr = 4;
+ break;
+ case 3:
+ *pll2n5_addr = 1;
+ break;
+ case 4:
+ *pll2n5_addr = 8;
+ break;
+ case 5:
+ *pll2n5_addr = 2;
+ break;
+ case 6:
+ *pll2n5_addr = 5;
+ break;
+ case 7:
+ *pll2n5_addr = 3;
+ break;
+ case 8:
+ *pll2n5_addr = 0x0C;
+ break;
+ default :
+ return ch_false;
+ }
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll2n6_div(ch_bool pll2n6_to_div, uint8* pll2n6_addr, uint8* div_addr)
+{
+ if(pll2n6_to_div)
+ {
+ if(*pll2n6_addr <= 3)
+ {
+ (*div_addr)= (*pll2n6_addr) + 5;
+ return ch_true;
+ }
+ return ch_false;
+ }
+ else
+ {
+ if(*div_addr >= 5 && *div_addr <= 8)
+ {
+ *pll2n6_addr = (*div_addr) - 5;
+ return ch_true;
+ }
+ return ch_false;
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll2n7_div(ch_bool pll2n7_to_div, uint8* pll2n7_addr, uint8* div_addr)
+{
+ if(pll2n7_to_div)
+ {
+ if(*pll2n7_addr <= 3)
+ {
+ (*div_addr)= (*pll2n7_addr) + 8;
+ return ch_true;
+ }
+ return ch_false;
+ }
+ else
+ {
+ if(*div_addr >= 8 && *div_addr <= 11)
+ {
+ *pll2n7_addr = (*div_addr) - 8;
+ return ch_true;
+ }
+ return ch_false;
+ }
+ return ch_true;
+}
+
+ch_bool convert_pll3n8_div(ch_bool pll3n8_to_div, uint8* pll3n8_addr, uint8* div_addr)
+{
+ uint8 val_t;
+
+ if(pll3n8_to_div)
+ {
+ if(*pll3n8_addr <= 3)
+ {
+ *div_addr= 1 << (*pll3n8_addr);
+ return ch_true;
+ }
+ return ch_false;
+ }
+ else
+ {
+ for(val_t=0; val_t<=3; ++val_t)
+ {
+ if(*div_addr == (1 << val_t))
+ {
+ *pll3n8_addr = val_t;
+ return ch_true;
+ }
+ }
+ return ch_false;
+ }
+
+ return ch_true;
+}
+
+ch_bool convert_dmxtal_div(ch_bool dmxtal_to_div, uint8* dmxtal_addr, uint8* div_addr)
+{
+ if(dmxtal_to_div)
+ {
+ switch(*dmxtal_addr)
+ {
+ case 0x00:
+ *div_addr = 1;
+ break;
+ case 0x04:
+ *div_addr = 2;
+ break;
+ case 0x08:
+ *div_addr = 3;
+ break;
+ case 0x0C:
+ *div_addr = 4;
+ break;
+ case 0x10:
+ *div_addr = 5;
+ break;
+ case 0x11:
+ *div_addr = 6;
+ break;
+ case 0x12:
+ *div_addr = 7;
+ break;
+ case 0x13:
+ *div_addr = 8;
+ break;
+ case 0x01:
+ *div_addr = 9;
+ break;
+ case 0x14:
+ *div_addr = 10;
+ break;
+ case 0x02:
+ *div_addr = 11;
+ break;
+ case 0x15:
+ *div_addr = 12;
+ break;
+ case 0x03:
+ *div_addr = 13;
+ break;
+ case 0x16:
+ *div_addr = 14;
+ break;
+ case 0x18:
+ *div_addr = 15;
+ break;
+ case 0x17:
+ *div_addr = 16;
+ break;
+ default:
+ return ch_false;
+ }
+ }
+ else
+ {
+ switch(*div_addr)
+ {
+ case 1:
+ *dmxtal_addr = 0x00;
+ break;
+ case 2:
+ *dmxtal_addr = 0x04;
+ break;
+ case 3:
+ *dmxtal_addr = 0x08;
+ break;
+ case 4:
+ *dmxtal_addr = 0x0C;
+ break;
+ case 5:
+ *dmxtal_addr = 0x10;
+ break;
+ case 6:
+ *dmxtal_addr = 0x11;
+ break;
+ case 7:
+ *dmxtal_addr = 0x12;
+ break;
+ case 8:
+ *dmxtal_addr = 0x13;
+ break;
+ case 9:
+ *dmxtal_addr = 0x01;
+ break;
+ case 10:
+ *dmxtal_addr = 0x14;
+ break;
+ case 11:
+ *dmxtal_addr = 0x02;
+ break;
+ case 12:
+ *dmxtal_addr = 0x15;
+ break;
+ case 13:
+ *dmxtal_addr = 0x03;
+ break;
+ case 14:
+ *dmxtal_addr = 0x16;
+ break;
+ case 15:
+ *dmxtal_addr = 0x18;
+ break;
+ case 16:
+ *dmxtal_addr = 0x17;
+ break;
+ default:
+ return ch_false;
+ }
+ }
+ return ch_true;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
new file mode 100755
index 0000000..9452854
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
@@ -0,0 +1,51 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_H
+#define _CH7036_H
+
+#include "ch7036_typedef.h"
+
+
+
+ch_bool DevicePrepare(DEV_CONTEXT* pDevContext);
+
+
+ch_bool DeviceConfig(DEV_CONTEXT* pDevContext);
+
+
+ch_bool DeviceRunning(DEV_CONTEXT* pDevContext);
+
+
+ch_bool DeviceSetPower(DEV_CONTEXT* pDevContext, unsigned long flags);
+
+
+uint32 GetLastErrorMessage(void);
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
new file mode 100644
index 0000000..fb5cdfe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
@@ -0,0 +1,1061 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_attr.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+
+#ifdef T_LINUX
+ #include "lvds/lvds.h"
+#else
+ #include "lvds.h"
+#endif
+
+
+
+static pd_attr_t g_ch7036_attrs[] =
+{
+
+
+
+ PD_MAKE_ATTR (PD_ATTR_ID_HPOSITION, PD_ATTR_TYPE_RANGE, "H Pos.", 0, DEFAULT_POSITION, DEFAULT_POSITION, DEFAULT_POSITION - 40, DEFAULT_POSITION + 40, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_VPOSITION, PD_ATTR_TYPE_RANGE, "V Pos.", 0, DEFAULT_POSITION, DEFAULT_POSITION, DEFAULT_POSITION - 30, DEFAULT_POSITION + 30, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_HSCALE, PD_ATTR_TYPE_RANGE, "H_Scale", 0, HDMI_DEFAULT_UNDERSCAN, HDMI_DEFAULT_UNDERSCAN, 10, 20, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_VSCALE, PD_ATTR_TYPE_RANGE, "V_Scale", 0, HDMI_DEFAULT_UNDERSCAN, HDMI_DEFAULT_UNDERSCAN, 10, 20, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_HSCALE_CRT, PD_ATTR_TYPE_RANGE, "H_Scale", 0, CRT_DEFAULT_UNDERSCAN, CRT_DEFAULT_UNDERSCAN, 10, 20, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_VSCALE_CRT, PD_ATTR_TYPE_RANGE, "V_Scale", 0, CRT_DEFAULT_UNDERSCAN, CRT_DEFAULT_UNDERSCAN, 10, 20, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_DITHER, PD_ATTR_TYPE_RANGE, "Dither", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 3, 1),
+
+ PD_MAKE_ATTR (PD_ATTR_ID_TEXT_FILTER, PD_ATTR_TYPE_RANGE, "Text Tuning", PD_ATTR_FLAG_USER_INVISIBLE, 4, DEFAULT_TEXT_ENHANCE, 0, 7, 1),
+
+
+ PD_MAKE_ATTR (PD_ATTR_ID_DITHER_BYPASS, PD_ATTR_TYPE_BOOL, "Quality Enhance", 0, 0, 0, 0, 0, 0),
+
+ PD_MAKE_ATTR (PD_ATTR_ID_PLL_REF_DLY, PD_ATTR_TYPE_BOOL, "Pll Reference Delay",PD_ATTR_FLAG_USER_INVISIBLE, 0,0,0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_PLL_REF_FBDLY,PD_ATTR_TYPE_BOOL, "Pll Reference FBDelay",PD_ATTR_FLAG_USER_INVISIBLE, 1, 1, 0, 0, 0),
+
+ PD_MAKE_ATTR (PD_ATTR_ID_LOAD_FIRMWARE,PD_ATTR_TYPE_BOOL, "Load Firmware",PD_ATTR_FLAG_USER_INVISIBLE, 0, 1, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_REFRESH,PD_ATTR_TYPE_BOOL, "Refresh",0, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_DWNSCAL_BYPASS,PD_ATTR_TYPE_BOOL, "Remove_DS",PD_ATTR_FLAG_USER_INVISIBLE, 0, 1, 0, 0, 0),
+
+};
+
+
+static ch7036_attr_list_entry_t g_list_entry_hdmi[] =
+{
+ {OUT_HDMI_640x480P_59, "640x480p_59",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_640x480P_60, "640x480p_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_720x480P_59, "720x480p_59",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_720x480P_60, "720x480p_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_HDMI_720x576P_50, "720x576p_50",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_HDMI_1280x720P_59, "1280x720p_59",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1280x720P_60, "1280x720p_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080I_59, "1920x1080i_59",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080I_60, "1920x1080i_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080P_59, "1920x1080p_59",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080P_60, "1920x1080p_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_HDMI_1280x720P_50, "1280x720p_50",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080I_50, "1920x1080i_50",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_HDMI_1920x1080P_50, "1920x1080p_50",PD_ATTR_FLAG_DYNAMIC},
+ {0, NULL,0}
+};
+
+
+
+static ch7036_attr_list_entry_t g_list_entry_dvi[] =
+{
+
+ {OUT_DVI_640x480_60, "640x480_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_640x480_72, "640x480_72",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_640x480_75, "640x480_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_720x400_70, "720x400_70",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_800x600_56, "800x600_56",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_800x600_60, "800x600_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_800x600_72, "800x600_72",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_800x600_75, "800x600_75",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1024x768_60, "1024x768_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1024x768_70, "1024x768_70",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1024x768_75, "1024x768_75",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1152x864_60, "1152x864_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1280x720_60, "1280x720_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1280x800_60, "1280x800_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1280x960_60, "1280x960_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1280x1024_60, "1280x1024_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1280x1024_75, "1280x1024_75",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1360x768_60, "1360x768_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1366x768_60, "1366x768_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1400x1050_60, "1400x1050_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1400x1050_75, "1400x1050_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1440x900_60, "1440x900_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1440x1050_60, "1440x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1600x900_60, "1600x900_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1600x1200_60, "1600x1200_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_DVI_1680x1050_60, "1680x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_DVI_1920x1080_60, "1920x1080_60",PD_ATTR_FLAG_DYNAMIC},
+ {0, NULL,0}
+};
+
+
+
+static ch7036_attr_list_entry_t g_list_entry_crt[] =
+{
+ {OUT_CRT_640x400_85, "640x400_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_640x480_60, "640x480_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_640x480_72, "640x480_72",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_640x480_75, "640x480_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_640x480_85, "640x480_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_720x400_85, "720x400_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_800x600_56, "800x600_56",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_800x600_60, "800x600_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_800x600_72, "800x600_72",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_800x600_75, "800x600_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_800x600_85, "800x600_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1024x768_60,"1024x768_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1024x768_70,"1024x768_70",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1024x768_75,"1024x768_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1024x768_85,"1024x768_85",PD_ATTR_FLAG_DYNAMIC},
+
+
+ {OUT_CRT_1152x864_75,"1152x864_75",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1280x768_60,"1280x768_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1280x768_75,"1280x768_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1280x768_85,"1280x768_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1280x960_60,"1280x960_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1280x960_85,"1280x960_85",PD_ATTR_FLAG_DYNAMIC},
+
+
+ {OUT_CRT_1280x1024_60,"1280x1024_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1280x1024_75,"1280x1024_75",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1280x1024_85,"1280x1024_85",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1360x768_60,"1360x768_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1400x1050_60,"1400x1050_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1400x1050_75,"1400x1050_75",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1440x900_60,"1440x900_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1440x1050_60,"1440x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1600x900_60,"1600x900_60",PD_ATTR_FLAG_DYNAMIC},
+
+ {OUT_CRT_1600x1200_60,"1600x1200_60",PD_ATTR_FLAG_DYNAMIC},
+ {OUT_CRT_1920x1080_60,"1920x1080_60",PD_ATTR_FLAG_DYNAMIC},
+ {0, NULL,0}
+};
+
+
+static ch7036_attr_list_entry_t g_list_entry_channel[] =
+{
+ {CHANNEL_AUTO_DETECT,"Auto Detect",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_LVDS_HDMI, "LVDS_HDMI",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_LVDS_DVI, "LVDS_DVI",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_LVDS_VGA, "LVDS_VGA",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_HDMI, "HDMI",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_DVI, "DVI",PD_ATTR_FLAG_DYNAMIC},
+ {CHANNEL_VGA, "VGA",PD_ATTR_FLAG_DYNAMIC},
+ {0, NULL,0}
+};
+
+static ch7036_attr_list_header_t g_list_header[] =
+{
+ {7, PD_ATTR_ID_DISPLAY,"Display Channel", 1,1,
+ g_list_entry_channel},
+
+ {14, PD_ATTR_ID_HDMI_OUT_MODE, "HDMI",7,7,
+ g_list_entry_hdmi},
+
+ {27, PD_ATTR_ID_DVI_OUT_MODE,"DVI", 9,9,
+ g_list_entry_dvi},
+
+ {32, PD_ATTR_ID_CRT_OUT_MODE, "VGA", 12,12,
+ g_list_entry_crt},
+
+ { 0 }
+};
+
+
+
+ch7036_status_t ch7036_init_attribute_table(ch7036_device_context_t *p_ctx, ch7036_attr_list_header_t* p_list_header)
+{
+ unsigned long ch7036_num_attrs, num_attrs;
+ unsigned char *p_table;
+
+
+
+ ch7036_num_attrs = ch7036_enumerate_attr_table(p_ctx, NULL, p_list_header);
+ PD_DEBUG("ch7036_init_attribute_table- ch7036 num_attr = [%lu]\n",ch7036_num_attrs);
+
+
+ p_ctx->ch7036_num_attrs = ch7036_num_attrs ;
+
+
+ if(p_ctx->p_ch7036_attr_table) {
+ pd_free(p_ctx->p_ch7036_attr_table);
+ p_ctx->p_ch7036_attr_table = NULL;
+ }
+
+
+ if(p_ctx->p_ch7036_attr_table == NULL) {
+
+ p_ctx->p_ch7036_attr_table = pd_malloc((p_ctx->ch7036_num_attrs + 1) * sizeof(pd_attr_t));
+
+ if (p_ctx->p_ch7036_attr_table == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_init_attribute_table: pd_malloc() failed allocating ch7036_attr_table");
+
+ return SS_MEM_ALLOC_ERR;
+ }
+
+ pd_memset(p_ctx->p_ch7036_attr_table, 0, (p_ctx->ch7036_num_attrs + 1) *
+ sizeof(pd_attr_t));
+
+ }
+
+
+ p_table = (unsigned char *)p_ctx->p_ch7036_attr_table;
+
+
+ if (p_ctx->ch7036_num_attrs > 0) {
+
+ num_attrs = ch7036_enumerate_attr_table(p_ctx, (pd_attr_t *)p_table, p_list_header);
+
+
+ PD_DEBUG("ch7036_init_attribute_table: ch7036_enumerate_attr_table()- returned %lu entries, expected %lu\n",
+ num_attrs, p_ctx->ch7036_num_attrs) ;
+
+ }
+
+
+ return SS_SUCCESS;
+
+}
+
+
+
+unsigned long ch7036_enumerate_attr_table (ch7036_device_context_t *p_ctx,
+ pd_attr_t *p_attr, ch7036_attr_list_header_t* p_list_header)
+{
+
+
+ unsigned long num_attrs, i, j, num_attrs_static;
+ ch7036_attr_list_entry_t *list_item;
+ int ret;
+ pd_attr_t *p_table;
+
+ list_item = NULL;
+ num_attrs = 0;
+ i = j = 0;
+
+
+ PD_DEBUG("ch7036_enumerate_attr_table- enter\n");
+
+
+
+ if ( p_list_header == NULL )
+ p_list_header = g_list_header;
+
+
+ if (p_attr == NULL) {
+
+ if(p_ctx->p_ch7036_attr_table == NULL) {
+ ret = PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(ch7036_lvds_get_attrs,(p_ctx->internal_lvds,&(p_ctx->lvds_num_attrs),&(p_ctx->p_lvds_attr_table)));
+
+ if(ret != PD_SUCCESS)
+ PD_DEBUG("ch7036_enumerate_attr_table: lvds_get_attributes() return ERROR! check this routine\n");
+ else
+ PD_DEBUG("ch7036_enumerate_attr_table: lvds_get_attributes()- lvds num_attr = [%lu]\n",p_ctx->lvds_num_attrs);
+ }
+
+
+
+ while (p_list_header[i].num_entries) {
+
+
+ num_attrs += (p_list_header[i].num_entries + 1);
+ ++i;
+ }
+
+ num_attrs += ((sizeof(g_ch7036_attrs)/sizeof(pd_attr_t)) + p_ctx->lvds_num_attrs) ;
+
+ return num_attrs;
+ }
+
+
+ if(p_ctx->lvds_num_attrs > 0) {
+
+ pd_attr_t *p_lvds_des, *p_lvds_src ;
+
+
+ p_lvds_src= (pd_attr_t *)p_ctx->p_lvds_attr_table;
+ p_lvds_des = (pd_attr_t *)p_attr;
+
+ pd_memcpy(p_lvds_des, p_lvds_src, (p_ctx->lvds_num_attrs)*sizeof(pd_attr_t));
+ num_attrs += p_ctx->lvds_num_attrs;
+
+ for (i=0 ; i < p_ctx->lvds_num_attrs; i++, p_lvds_des++) {
+
+ PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+ "adding lvds attr='%s', id=%lu, default=%lu, current=%lu, \n",
+ p_lvds_des->name, p_lvds_des->id, p_lvds_des->default_value, p_lvds_des->current_value);
+ }
+
+ }
+
+ PD_DEBUG("ch7036 : ch7036_enumerate_attr_table adding lvds num attrs = %lu \n", num_attrs);
+
+
+
+ i=0;
+
+
+ while (p_list_header[i].num_entries) {
+
+ pd_list_attr_t *p_hdr = (pd_list_attr_t *) &p_attr[num_attrs];
+
+
+ p_hdr->type = PD_ATTR_TYPE_LIST;
+ p_hdr->id = p_list_header[i].id;
+ p_hdr->num_entries = p_list_header[i].num_entries;
+ p_hdr->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+ p_hdr->current_index = p_list_header[i].current_index;
+ pd_strcpy(p_hdr->name, p_list_header[i].p_name);
+
+ p_hdr->default_index = p_list_header[i].default_index;
+
+ PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+ "adding attr - list header='%s', id=%lu, default=%lu, current=%lu, \n"
+ "num_entries=%lu\n",
+ p_hdr->name, p_hdr->id, p_hdr->default_index, p_hdr->current_index,
+ p_hdr->num_entries);
+
+ ++num_attrs;
+
+
+
+ list_item = p_list_header[i].attr_list;
+ for (j = 0; j < p_list_header[i].num_entries; ++j, ++num_attrs) {
+
+ pd_list_entry_attr_t *p_entry =
+ (pd_list_entry_attr_t *)&p_attr[num_attrs];
+
+ p_entry->id = p_list_header[i].id;
+ p_entry->type = PD_ATTR_TYPE_LIST_ENTRY;
+ p_entry->value = list_item[j].id;
+
+
+ p_entry->flags = list_item[j].flags;
+
+
+
+
+
+
+
+
+ pd_strcpy(p_entry->name, list_item[j].p_name);
+
+
+
+ PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : list entry[%lu]=%s, id=[%lu], "
+ "value=%lu, flags=0x%x \n",
+ j, p_entry->name, p_entry->id,
+ p_entry->value, (unsigned char)p_entry->flags);
+
+ }
+
+ ++i;
+ }
+
+
+ p_table = (pd_attr_t *)&p_attr[num_attrs];
+ num_attrs_static = sizeof(g_ch7036_attrs)/sizeof(pd_attr_t);
+ pd_memcpy(p_table, g_ch7036_attrs,num_attrs_static*sizeof(pd_attr_t));
+
+ for (i=0 ; i < num_attrs_static; i++, p_table++) {
+
+ PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+ "adding ch7036 static attr='%s', id=%lu, default=%lu, current=%lu, \n",
+ p_table->name, p_table->id, p_table->default_value, p_table->current_value);
+
+ }
+
+ num_attrs += num_attrs_static;
+
+
+ return num_attrs;
+
+}
+
+void ch7036_set_dither(ch7036_device_context_t* p_ctx)
+{
+ uint8 reg=0x00;
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+
+ I2CWrite(p_ch_ctx,0x03, 0x04);
+ reg = I2CRead(p_ch_ctx,0x57);
+ reg = reg & 0x3F;
+
+
+ switch(p_ctx->dither_select)
+ {
+ case DITHER_18_TO_18:
+ reg &= 0x3F;
+ break;
+ case DITHER_18_TO_24:
+ reg = reg | 0x40;
+ break;
+ case DITHER_24_TO_18:
+ reg = reg | 0x80;
+ break;
+ case DITHER_24_TO_24:
+ reg = reg | 0xC0;
+ break;
+ default:
+ break;
+ }
+ I2CWrite(p_ch_ctx,0x57, reg);
+
+ return;
+}
+
+
+
+void ch7036_set_audio_type(INPUT_INFO* pInput_Info, uint8 id)
+{
+
+ pInput_Info->audio_type = id;
+
+ if(pInput_Info->audio_type == AUDIO_I2S) {
+
+
+
+
+ pInput_Info->i2s_pol = 0;
+ pInput_Info->i2s_len = 0;
+ pInput_Info->i2s_fmt = 0;
+
+ }
+}
+
+
+
+ch7036_status_t ch7036_set_output_channel(void* p_context, uint32 channel)
+{
+ ch7036_device_context_t * p_ctx= (ch7036_device_context_t *)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ pd_attr_t *p_attr_hdmi, *p_attr_crt, *p_attr_dvi;
+ pd_attr_t *p_attr_hscale, *p_attr_vscale, *p_attr_hscale_crt, *p_attr_vscale_crt, *p_attr_hp, *p_attr_vp;
+ pd_attr_t* p_attr_dither;
+
+
+
+ PD_DEBUG("ch7036_set_output_channel- channel [%x]\n", channel);
+
+ pOutput_Info->channel = channel;
+
+
+
+ p_attr_dvi = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_DVI_OUT_MODE, PD_GET_ATTR_LIST);
+
+ p_attr_hdmi = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_HDMI_OUT_MODE, PD_GET_ATTR_LIST);
+
+
+ p_attr_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_CRT_OUT_MODE, PD_GET_ATTR_LIST);
+
+
+ p_attr_hscale_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_HSCALE_CRT, 0);
+ p_attr_vscale_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_VSCALE_CRT, 0);
+
+ p_attr_hscale = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_HSCALE, 0);
+ p_attr_vscale = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_VSCALE, 0);
+
+ p_attr_hp = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_HPOSITION, 0);
+ p_attr_vp = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_VPOSITION, 0);
+
+ p_attr_dither = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_DITHER_BYPASS, 0);
+
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI) {
+
+ if(pOutput_Info->hdmi_fmt.is_dvi_mode) {
+
+ if(p_attr_hdmi)
+ p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_dvi->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr_dvi += p_attr_dvi->current_value;
+ p_ctx->dvi_mode_index = ((pd_list_entry_attr_t *)p_attr_dvi)->value;
+
+ PD_DEBUG("ch7036_set_output_channel- dvi mode index [%hu]\n",p_ctx->dvi_mode_index);
+
+
+
+ }
+ else {
+
+ p_attr_hdmi->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+ if(p_attr_dvi)
+ p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr_hdmi += p_attr_hdmi->current_value;
+ p_ctx->hdmi_mode_index = ((pd_list_entry_attr_t *)p_attr_hdmi)->value;
+
+ PD_DEBUG("ch7036_set_output_channel- hdmi mode index [%hu]\n",p_ctx->hdmi_mode_index);
+
+ }
+
+ if(p_attr_crt)
+ p_attr_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ //hdmi/dvi- hide it from user
+ p_attr_hscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ //h/v pos scale- hide it
+ p_attr_hp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ //show it
+ p_attr_hscale->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr_dither->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ PD_DEBUG("ch7036_set_output_channel-current hscale value [%d]\n",(uint8)p_attr_hscale->current_value);
+ PD_DEBUG("ch7036_set_output_channel-current vscale value [%d]\n",(uint8)p_attr_vscale->current_value);
+
+ ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_HSCALE,(uint8)p_attr_hscale->current_value);
+ ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_VSCALE,(uint8)p_attr_vscale->current_value);
+
+
+ } else if (pOutput_Info->channel & CHANNEL_VGA) {
+
+ p_attr_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+ if(p_attr_hdmi)
+ p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ if(p_attr_dvi)
+ p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_crt += p_attr_crt->current_value;
+ p_ctx->crt_mode_index = ((pd_list_entry_attr_t *)p_attr_crt)->value;
+
+ PD_DEBUG("ch7036_set_output_channel- crt mode index [%hu]\n",p_ctx->crt_mode_index);
+
+
+ p_attr_hscale_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_hp->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vp->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_dither->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr_hscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ PD_DEBUG("ch7036_set_output_channel-current hscale_crt value [%d]\n",(uint8)p_attr_hscale_crt->current_value);
+ PD_DEBUG("ch7036_set_output_channel-current vscale_crt value [%d]\n",(uint8)p_attr_vscale_crt->current_value);
+
+
+ ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_HSCALE_CRT,(uint8)p_attr_hscale_crt->current_value);
+ ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_VSCALE_CRT,(uint8)p_attr_vscale_crt->current_value);
+
+
+ } else {
+
+ if(p_attr_crt)
+ p_attr_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ if(p_attr_hdmi)
+ p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ if(p_attr_dvi)
+ p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr_hscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_hscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_hp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_attr_vp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ p_attr_dither->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ }
+
+
+ return SS_SUCCESS;
+}
+unsigned long ch7036_get_output_channel(void* p_context)
+{
+ ch7036_device_context_t * p_ctx= (ch7036_device_context_t *)p_context;
+ pd_list_entry_attr_t *p_attr;
+ uint32 channel = 0;
+
+ PD_DEBUG("ch7036_get_output_channel- enter\n");
+
+ p_attr = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+ PD_ATTR_ID_DISPLAY, PD_GET_ATTR_LIST_ENTRY);
+
+ if(p_attr->value & CHANNEL_DVI)
+ channel = (p_attr->value & 0xF7) | CHANNEL_HDMI;
+
+ return channel;
+}
+
+ch7036_status_t ch7036_set_position(ch7036_device_context_t *p_ctx, uint8 attr_id, uint16 pos)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+
+ uint8 reg;
+
+ PD_DEBUG("ch7036_set_position- enter\n");
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x39);
+
+ if(attr_id == PD_ATTR_ID_HPOSITION) {
+ reg = reg & 0xF0;
+ I2CWrite(p_ch7xxx_context,0x3A, (pos & 0x00FF));
+ reg = ((pos >> 8) & 0x0F) | reg;
+ iic_write_ex(HP,pos);
+ }
+ else {
+ reg = reg & 0x0F;
+ I2CWrite(p_ch7xxx_context,0x3B, (pos & 0x00FF));
+ reg = (((pos >> 8) & 0x0F) << 4) | reg;
+ iic_write_ex(VP,pos);
+ }
+
+ I2CWrite(p_ch7xxx_context,0x39, reg);
+
+ return SS_SUCCESS;
+}
+
+
+void ch7036_set_hdmi_sync_polarity(OUTPUT_INFO* pOutput_Info)
+{
+
+ if((pOutput_Info->channel & CHANNEL_HDMI)&&(pOutput_Info->channel & CHANNEL_VGA))
+ {
+ if (pOutput_Info->timing.ha > 720) {
+ pOutput_Info->hdmi_fmt.hs_pol = POL_HIGH;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_HIGH;
+ if(pOutput_Info->timing.ha == 1440 )
+ {
+ pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+ }
+ }
+ else if(pOutput_Info->timing.ha <= 720){
+
+ pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+ }
+ }
+
+
+ if((pOutput_Info->channel & CHANNEL_HDMI) && ((pOutput_Info->channel & CHANNEL_VGA) == 0x00))
+ {
+ pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+ pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+ }
+
+}
+
+void ch7036_set_quality_enhancement(ch7036_device_context_t *p_ctx, uint8 checked)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+ uint8 reg;
+
+ PD_DEBUG("ch7036_set_quality_enhancement- enter\n");
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x19);
+
+ if(checked)
+ reg = reg & 0xBF;
+ else
+ reg = reg | 0x40;
+
+ I2CWrite(p_ch7xxx_context,0x19, reg);
+
+
+ pPrefer_Info->dither_filter_enable = checked?DITHER_ENABLE:DITHER_BYPASS;
+
+
+ iic_write_ex(DBP, checked?DITHER_ENABLE:DITHER_BYPASS);
+
+}
+
+void ch7036_set_scaling (OUTPUT_INFO* pOutput_Info, unsigned long id, uint8 value)
+{
+ uint8* p_scale;
+
+ PD_DEBUG("ch7036_set_scaling- enter- value [%d]\n", value);
+
+ if(id == PD_ATTR_ID_HSCALE || id == PD_ATTR_ID_HSCALE_CRT)
+ p_scale= &(pOutput_Info->ds_percent_h);
+ else
+ p_scale= &(pOutput_Info->ds_percent_v);
+
+ switch(value) {
+ case 20: *p_scale = 0; break;
+ case 19: *p_scale = 1; break;
+ case 18: *p_scale = 2; break;
+ case 17: *p_scale = 3; break;
+ case 16: *p_scale = 4; break;
+ case 15: *p_scale = 5; break;
+ case 14: *p_scale = 6; break;
+ case 13: *p_scale = 7; break;
+ case 12: *p_scale = 8; break;
+ case 11: *p_scale = 9; break;
+ case 10: *p_scale = 10; break;
+
+ case 9: *p_scale = 11; break;
+ case 8: *p_scale = 12; break;
+ case 7: *p_scale = 13; break;
+ case 6: *p_scale = 14; break;
+ case 5: *p_scale = 15; break;
+ case 4: *p_scale = 16; break;
+ case 3: *p_scale = 17; break;
+ case 2: *p_scale = 18; break;
+ case 1: *p_scale = 19; break;
+ case 0: *p_scale = 20; break;
+ default: break;
+
+ }
+
+ return;
+
+}
+
+void ch7036_set_rotate (OUTPUT_INFO* pOutput_Info)
+{
+
+
+ pOutput_Info->rotate = DEFAULT_ROTATE;
+}
+
+void ch7036_set_hflip (OUTPUT_INFO* pOutput_Info)
+{
+
+
+ pOutput_Info->h_flip = DEFAULT_HFLIP;
+}
+void ch7036_set_vflip (OUTPUT_INFO* pOutput_Info)
+{
+
+
+ pOutput_Info->v_flip = DEFAULT_VFLIP;
+}
+
+void ch7036_set_text_enhancement (ch7036_device_context_t *p_ctx, uint8 val)
+{
+
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+
+
+ PD_DEBUG("ch7036_set_text_enhancement- enter\n");
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ I2CWrite(p_ch7xxx_context,0x2E, (I2CRead(p_ch7xxx_context,0x2E) & 0xF8) | val);
+
+ pPrefer_Info->text_enhancement = val;
+ iic_write_ex(TXTEN, val);
+}
+
+
+void ch7036_set_pll_refdly(PREFER_INFO* pPrefer_Info)
+{
+ pPrefer_Info->pll_ref_dly = DEF_PLL_REF_DLY;
+}
+
+void ch7036_set_pll_fbdly(PREFER_INFO* pPrefer_Info)
+{
+ pPrefer_Info->pll_ref_fbdly = DEF_PLL_REF_FBDLY;
+}
+
+void ch7036_set_lvds_txdrv_ctrl(PREFER_INFO* pPrefer_Info)
+{
+ pPrefer_Info->lvds_txdrv_ctrl = DEF_LVDS_TXDRV_CTRL;
+}
+
+
+
+ch7036_status_t ch7036_alter_display_channel (ch7036_device_context_t *p_ctx)
+{
+
+
+ ch7036_status_t status;
+
+
+ pd_list_entry_attr_t *list_item;
+
+ ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+ ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+ PD_GET_ATTR_LIST_ENTRY);
+
+ PD_DEBUG("ch7036_alter_display_channel=> enter- list_item->value [0x%lu]\n",list_item->value);
+
+ switch (p_ctx->hpd & 0x22) {
+
+ case 0x22:
+ case 0x20:
+ PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi hpd status: attached... \n");
+ if(p_ctx->hpd & 0x41 ) {
+
+ status = ch7036_read_edid(p_ctx, CHANNEL_LVDS_HDMI);
+
+
+ if (status == SS_SUCCESS) {
+
+ if( p_ctx->man_sel_out==1 )
+ p_ctx->hpd &= 0x3F; //need parsing but dont do edid again
+ else
+ p_ctx->hpd &= 0x7F;
+
+
+ PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi, status changed,edid read is a success- proceed to alter attr table...\n");
+
+ }
+ else {
+
+ PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi, status changed,edid read failed- use default attr table- show all modes..\n");
+
+
+ }
+
+
+
+ }
+ else {
+
+ PD_DEBUG("ch7036_alter_display_channel=> hdmi/dvi, status unchanged,check if edid read needed...\n");
+ ch7036_redo_edid_if_needed(p_ctx, (void *)p_hedid, CHANNEL_LVDS_HDMI);
+ }
+
+
+
+
+ if(list_item->value == CHANNEL_AUTO_DETECT) {
+ if(p_ctx->prev_outchannel != CHANNEL_LVDS_HDMI)
+ ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_HDMI);
+ }
+ else {
+
+
+
+
+ if(list_item->value & CHANNEL_DVI)
+ // map DVI to HDMI output channel;
+ ch7036_set_output_channel((void *)p_ctx, (list_item->value & 0x01) | CHANNEL_HDMI);
+
+ else
+
+ ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+
+
+ }
+
+
+ break;
+
+ case 0x02:
+
+ PD_DEBUG("ch7036_alter_display_channel=> crt hpd status: attached... \n");
+
+ if(p_ctx->hpd & 0x05) {
+
+ status = ch7036_read_edid(p_ctx, CHANNEL_LVDS_VGA);
+
+
+ if (status == SS_SUCCESS) {
+
+ PD_DEBUG("ch7036_alter_display_channel=> crt only, status changed, edid is a success, proceed ..\n");
+ if( p_ctx->man_sel_out==1 )
+ p_ctx->hpd &= 0xF3; //need parsing,hpd manually updated to 'unchanged',dont do edid again
+ else
+ p_ctx->hpd &= 0xF7;
+
+
+ }
+ else {
+
+ PD_DEBUG("ch7036_alter_display_channel=> crt only, status changed, edid failed- use default attr table- show all modes..\n");
+
+ }
+
+
+ }
+
+ else {
+ PD_DEBUG("ch7036_alter_display_channel=> crt only, status unchange,check if edid read needed...\n");
+ ch7036_redo_edid_if_needed(p_ctx, (void *)p_cedid, CHANNEL_LVDS_VGA);
+ }
+
+ if(list_item->value == CHANNEL_AUTO_DETECT)
+ ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_VGA);
+ else {
+
+ //set output channel, correct display choice if needed
+ ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+ }
+
+
+ break;
+
+ default:
+
+ if(list_item->value == CHANNEL_AUTO_DETECT) {
+ if (!p_ctx->init_done) {
+ ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_VGA);
+ }
+ else
+ ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS);
+ }
+ else
+ ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+
+
+ break;
+
+
+ }
+
+ PD_DEBUG("ch7036_alter_display_channel=> exit- list_item->value [0x%x]\n",list_item->value);
+ return SS_SUCCESS;
+
+}
+
+
+pd_list_entry_attr_t *ch7036_get_updated_display_ouput_entry(ch7036_device_context_t *p_ctx, uint32 channel)
+{
+
+ pd_list_entry_attr_t *list_item;
+
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+ PD_GET_ATTR_LIST_ENTRY);
+
+ list_item->value = (list_item->value & 0x01) | channel;
+
+ return list_item;
+}
+
+
+void ch7036_redo_edid_if_needed(ch7036_device_context_t *p_ctx, void* p_edidblk, uint32 channel)
+{
+ ch7036_edid_blk_t* p_edid = (ch7036_edid_blk_t *)p_edidblk;
+ ch7036_status_t status = SS_UNSUCCESSFUL;;
+
+
+
+ if (!p_ctx->init_done) {
+
+ PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=> attached, status unchanged at init, read edid NOW...\n");
+ status = ch7036_read_edid(p_ctx, channel);
+
+ }
+ else {
+
+ if(!p_edid->is_edid) {
+ PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=>attached, status unchanged, never read edid or edid failed, read it NOW..\n");
+ status= ch7036_read_edid(p_ctx, channel);
+
+
+ }
+ else
+ PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=> attached, status unchanged, edid read was done, edid read is NOT needed...\n");
+ }
+
+ if(status == SS_SUCCESS) {
+
+ if(channel & CHANNEL_HDMI)
+ if( p_ctx->man_sel_out==1 )
+ p_ctx->hpd &= 0x3F;
+ else
+ p_ctx->hpd &= 0x7F;
+
+ else
+ if( p_ctx->man_sel_out==1 )
+ p_ctx->hpd &= 0xF3;
+ else
+ p_ctx->hpd &= 0xF7;
+
+ }
+
+
+
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
new file mode 100644
index 0000000..4917394
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
@@ -0,0 +1,85 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_attr.h
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+//#include <linux/kernel.h>
+
+#ifndef _CH7036_ATTR_H_
+#define _CH7036_ATTR_H_
+
+typedef struct {
+ unsigned long id;
+ char *p_name;
+ unsigned long flags;
+
+} ch7036_attr_list_entry_t;
+
+typedef struct {
+ unsigned char num_entries;
+ unsigned long id;
+ char *p_name;
+ unsigned long default_index;
+ unsigned long current_index;
+ ch7036_attr_list_entry_t *attr_list;
+
+} ch7036_attr_list_header_t;
+
+
+unsigned long ch7036_enumerate_attr_table(ch7036_device_context_t *p_ctx,pd_attr_t *p_attr,ch7036_attr_list_header_t* p_list_header);
+ch7036_status_t ch7036_init_attribute_table(ch7036_device_context_t *p_ctx,ch7036_attr_list_header_t* p_list_header);
+
+
+void ch7036_set_hdmi_sync_polarity(OUTPUT_INFO* pOutput_Info);
+void ch7036_set_audio_type(INPUT_INFO* pInput_Info, uint8 id);
+void ch7036_set_scaling (OUTPUT_INFO* pOutput_Info, unsigned long id, uint8 value );
+ch7036_status_t ch7036_set_position(ch7036_device_context_t *p_ctx, uint8 attr_id, uint16 pos);
+
+
+void ch7036_set_rotate (OUTPUT_INFO* pOutput_Info);
+void ch7036_set_hflip (OUTPUT_INFO* pOutput_Info);
+void ch7036_set_vflip (OUTPUT_INFO* pOutput_Info);
+
+ch7036_status_t ch7036_set_output_channel(void* p_context, uint32 channel);
+unsigned long ch7036_get_output_channel(void* p_context);
+ch7036_status_t ch7036_alter_display_channel (ch7036_device_context_t *p_ctx);
+
+pd_list_entry_attr_t * ch7036_get_updated_display_ouput_entry(ch7036_device_context_t *p_ctx, uint32 channel);
+
+void ch7036_set_text_enhancement (ch7036_device_context_t *p_ctx, uint8 val);
+void ch7036_set_quality_enhancement(ch7036_device_context_t *p_ctx, uint8 val);
+
+void ch7036_set_pll_refdly(PREFER_INFO* pPrefer_Info);
+void ch7036_set_pll_fbdly(PREFER_INFO* pPrefer_Info);
+void ch7036_set_lvds_txdrv_ctrl(PREFER_INFO* pPrefer_Info);
+
+void ch7036_set_dither(ch7036_device_context_t* p_ctx);
+
+void ch7036_redo_edid_if_needed(ch7036_device_context_t *p_ctx, void* p_edidblk, uint32 channel);
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
new file mode 100755
index 0000000..d2e82fc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
@@ -0,0 +1,700 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_def_regmap.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_DEF_REGMAP_H
+#define _CH7036_DEF_REGMAP_H
+
+#include "ch7036_typedef.h"
+
+
+
+#define REG_PAGE_NUM 5
+#define REG_NUM_PER_PAGE 0x80
+
+static uint8 g_DefRegMap[5][0x80] = {
+
+ {
+ 0x56,
+ 0xF0,
+ 0xF3,
+ 0x00,
+ 0x36,
+ 0x58,
+ 0xAC,
+ 0xDD,
+ 0x0F,
+ 0x1F,
+ 0xB4,
+ 0x1A,
+ 0x80,
+ 0x20,
+ 0x00,
+ 0x10,
+ 0x60,
+ 0x11,
+ 0xE0,
+ 0x0D,
+ 0x00,
+ 0x0A,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0xF8,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x1A,
+ 0x80,
+ 0x20,
+ 0x00,
+ 0x10,
+ 0x60,
+ 0x11,
+ 0xE0,
+ 0x0D,
+ 0x00,
+ 0x0A,
+ 0x02,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x3C,
+ 0x00,
+ 0x01,
+ 0x01,
+ 0xC0,
+ 0x01,
+ 0x01,
+ 0x80,
+ 0x40,
+ 0x40,
+ 0x47,
+ 0x88,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x86,
+ 0x00,
+ 0x11,
+ 0x0E,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x80,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x1F,
+ 0xFF,
+ 0x00,
+ 0x80,
+ 0x10,
+ 0x60,
+ 0x00,
+ 0x0A,
+ 0x02,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x2D,
+ 0x90,
+ 0x20,
+ 0x22,
+ 0x44,
+ 0x24,
+ 0x40,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0xA0,
+ 0x4B,
+ 0x18,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x80,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0x0F,
+ 0x00,
+ },
+
+
+ {
+ 0x56,
+ 0xF0,
+ 0xF3,
+ 0x01,
+ 0x36,
+ 0x58,
+ 0xAC,
+ 0x20,
+ 0x00,
+ 0x4B,
+ 0x00,
+ 0x6D,
+ 0x6A,
+ 0x51,
+ 0x93,
+ 0x1C,
+ 0x00,
+ 0x08,
+ 0xC5,
+ 0xA8,
+ 0x91,
+ 0x68,
+ 0x29,
+ 0x0E,
+ 0xC8,
+ 0x42,
+ 0x6C,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x07,
+ 0xFF,
+ 0xB6,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x15,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x0B,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x60,
+ 0x14,
+ 0x20,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x00,
+ 0x49,
+ 0x10,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x00,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xA0,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7A,
+ 0x5E,
+ 0x6E,
+ 0x1F,
+ 0x1F,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x50,
+ 0x00,
+ 0x00,
+ 0x09,
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x00,
+ 0x50,
+ 0x00,
+ 0x98,
+ 0x00,
+ 0x98,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x00,
+ },
+
+
+ {
+ 0x56,
+ 0xF0,
+ 0xF3,
+ 0xFF,
+ 0x36,
+ 0x58,
+ 0xAC,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ },
+
+
+ {
+ 0x56,
+ 0xF0,
+ 0xF3,
+ 0x03,
+ 0x36,
+ 0x58,
+ 0xAC,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0x00,
+ 0x03,
+ 0x19,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x11,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x09,
+ 0x1D,
+ 0x0F,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0xF8,
+ 0xFF,
+ 0x00,
+ 0x02,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ },
+
+
+ {
+ 0x56,
+ 0xF0,
+ 0xF3,
+ 0x04,
+ 0x36,
+ 0x58,
+ 0xAC,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xC0,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x00,
+ 0x00,
+ 0x4F,
+ 0x07,
+ 0x4F,
+ 0x07,
+ 0x3B,
+ 0x07,
+ 0x3B,
+ 0x07,
+ 0x50,
+ 0x00,
+ 0x50,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x00,
+ 0x03,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x24,
+ 0x00,
+ 0x40,
+ 0xFF,
+ 0xFF,
+ 0x7F,
+ 0x56,
+ 0x80,
+ 0x2F,
+ 0x00,
+ 0x84,
+ 0x60,
+ 0xAF,
+ 0x00,
+ 0x00,
+ 0x80,
+ 0x94,
+ 0x00,
+ 0x80,
+ 0x00,
+ 0x05,
+ 0x38,
+ 0x01,
+ 0x83,
+ 0x11,
+ 0x01,
+ 0x80,
+ 0x90,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0xE4,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x89,
+ 0x10,
+ 0xAC,
+ 0x00,
+ 0xE0,
+ 0x80,
+ 0x80,
+ 0x19,
+ 0x7D,
+ 0x00,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x00,
+ 0x0C,
+ },
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
new file mode 100755
index 0000000..23490d7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
@@ -0,0 +1,468 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_fw.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_intf.h"
+
+#include "edid7036.car"
+
+
+#define EDID_RETRY_MAX_TIMES 5
+#define HPD_LOOP_MAX 10
+
+
+#define SLEEP_TIME 200
+
+
+#define lhfm_size sizeof(lhfm_array)
+
+#define LHFM_TIMEOUT 10
+
+static unsigned char edid_header[8]={0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00};
+
+static unsigned char es_map[16] = {
+ 0x26,0x27,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x6A,0x51,0x52,0x53,0x57,0x58,0x59,0x5A
+};
+
+
+
+
+
+established_timings_t et_I[8] = {
+ {0,"800x600_60", {OUT_DVI_800x600_60,OUT_HDMI_END, OUT_CRT_800x600_60} },
+ {0,"800x600_56", {OUT_DVI_800x600_56,OUT_HDMI_END, OUT_CRT_800x600_56} },
+ {0,"640x480_75", {OUT_DVI_640x480_75, OUT_HDMI_END, OUT_CRT_640x480_75} },
+ {0,"640x480_72", {OUT_DVI_640x480_72, OUT_HDMI_END, OUT_CRT_640x480_72} },
+ {0,"640x480_67", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END } },
+ {0,"640x480_60", {OUT_DVI_640x480_60, OUT_HDMI_640x480P_60, OUT_CRT_640x480_60} },
+ {0,"720x400_88", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END } },
+ {0,"720x400_70", {OUT_DVI_720x400_70, OUT_HDMI_END, OUT_CRT_END} },
+};
+
+established_timings_t et_II[8] ={
+ {0, "1280x1024_75", {OUT_DVI_1280x1024_75, OUT_HDMI_END, OUT_CRT_1280x1024_75} },
+ {0, "1024x768_75", {OUT_DVI_1024x768_75, OUT_HDMI_END, OUT_CRT_1024x768_75} },
+ {0, "1024x768_70", {OUT_DVI_1024x768_70, OUT_HDMI_END, OUT_CRT_1024x768_70} },
+ {0, "1024x768_60", {OUT_DVI_1024x768_60, OUT_HDMI_END, OUT_CRT_1024x768_60} },
+ {0, "1024x768_87", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END} },
+ {0, "832x624_75", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END} },
+ {0, "800x600_75", {OUT_DVI_800x600_75, OUT_HDMI_END, OUT_CRT_800x600_75} },
+ {0, "800x600_72", {OUT_DVI_800x600_72, OUT_HDMI_END, OUT_CRT_800x600_72} }
+};
+
+established_timings_t et_man = {
+ 0, "1152x870_75", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END}
+};
+
+
+int LHFM_get_version(DEV_CONTEXT* p_ch7xxx_context,struct _FW7036_CFG* cfg)
+{
+
+ unsigned char reg;
+ unsigned wj;
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+
+
+ if (0==(LHFM_REQUEST & reg)) {
+ I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_VERSION));
+ wj = 0;
+ while (wj++< LHFM_TIMEOUT) {
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ pd_usleep(SLEEP_TIME );
+ PD_DEBUG("LHFM_get_version [%x]\r\n", wj);
+
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+ if(reg == LHFM_GET_VERSION) {
+ reg = I2CRead(p_ch7xxx_context,0x50);
+ if (!(LHFM_RET_ERROR & reg)) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ cfg->size = I2CRead(p_ch7xxx_context,es_map[0]);
+ cfg->ver_major = I2CRead(p_ch7xxx_context,es_map[1]);
+ cfg->ver_minor = I2CRead(p_ch7xxx_context,es_map[2]);
+ cfg->did = I2CRead(p_ch7xxx_context,es_map[3]);
+ cfg->rid = I2CRead(p_ch7xxx_context,es_map[4]);
+ cfg->capbility = I2CRead(p_ch7xxx_context,es_map[5]);
+ cfg->reserved = I2CRead(p_ch7xxx_context,es_map[6]);
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ return 0;
+ } else return -2;
+
+ }
+
+ }
+
+ }
+
+ return -1;
+}
+
+
+void LHFM_enable_crt_hpd(DEV_CONTEXT* p_ch7xxx_context)
+{
+ uint8 reg;
+
+ PD_DEBUG("ch7036: LHFM_enable_crt_hpd-enter\n");
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x57);
+ I2CWrite(p_ch7xxx_context,0x57, reg | 0x02);
+
+ pd_usleep(SLEEP_TIME);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ I2CWrite(p_ch7xxx_context,0x08, I2CRead(p_ch7xxx_context,0x08) & 0xF1);
+
+ pd_usleep(SLEEP_TIME);
+}
+
+
+ch7036_status_t LHFM_get_crt_hpd(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+ unsigned char reg, count =0;
+ ch7036_status_t status = SS_CRT_HPD_NOTCONNECTED;
+
+ do {
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x74);
+ I2CWrite(p_ch7xxx_context,0x74, reg & 0xFD);
+ pd_usleep(SLEEP_TIME);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x74);
+ I2CWrite(p_ch7xxx_context,0x74, reg | 0x02);
+ pd_usleep(SLEEP_TIME);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x7C);
+
+ if( (reg & 0xF0) == 0x50 || (reg & 0xF4) == 0x14 || (reg & 0xF4) == 0x44)
+ status= SS_SUCCESS;
+
+ } while ( (status == SS_CRT_HPD_NOTCONNECTED) && ( (++count) < HPD_LOOP_MAX ) );
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x74);
+ I2CWrite(p_ch7xxx_context,0x74, reg & 0xFD);
+
+ I2CWrite(p_ch7xxx_context,0x08, I2CRead(p_ch7xxx_context,0x08) | 0x0E);
+
+ return status;
+
+}
+
+
+ch7036_status_t LHFM_get_hdmi_modeinfo(DEV_CONTEXT* p_ch7xxx_context,unsigned char *minfo)
+{
+ unsigned char reg;
+ unsigned wj;
+ unsigned i;
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+
+ if (0==(LHFM_REQUEST & reg)) {
+ I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+ LHFM_GET_MODEINFO));
+ wj = 0;
+ while (wj++< LHFM_TIMEOUT) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ pd_usleep(SLEEP_TIME);
+
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+ if(reg == LHFM_GET_MODEINFO) {
+ reg = I2CRead(p_ch7xxx_context,0x50);
+ if (!(LHFM_RET_ERROR & reg)) {
+ if (minfo) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ for (i=0; i<15; i++) minfo[i] = I2CRead(p_ch7xxx_context,es_map[i]);
+ }
+ return SS_SUCCESS;
+ } else return SS_FIRMWARE_ERR;
+
+ }
+
+ }
+
+ }
+
+ return SS_FIRMWARE_TIMEOUT;
+
+}
+
+
+ch7036_status_t LHFM_get_edid(DEV_CONTEXT* p_ch7xxx_context,unsigned char* edid, unsigned char* ebn, unsigned char flag)
+{
+
+ unsigned i,j, ie;
+ unsigned k1, k2;
+ unsigned char reg;
+ unsigned wj;
+
+ ch7036_status_t status;
+
+
+
+ status = SS_SUCCESS;
+ *ebn = 0;
+
+ pd_memset(edid, 0, EDID_SIZE);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+
+ if( (reg & LHFM_REQUEST) != 0 )
+ return SS_FIRMWARE_ERR; //mcu is busy
+ else { //mcu is ready to serve host request
+
+ for(i=0,j=0; i < 8; i++,j+=16) {
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ I2CWrite(p_ch7xxx_context,0x50, i | flag);
+ I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_EDID));
+ wj = 0;
+
+ status = SS_FIRMWARE_TIMEOUT;
+ PD_DEBUG("ch7036: LHFM_get_edid- block [%d] - getting [%d]- 16 bytes - wj=[0x%x]\n",*ebn,i+1,wj);
+ while (wj++< (2*LHFM_TIMEOUT) ) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ pd_usleep(SLEEP_TIME);
+
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+
+ if(reg == LHFM_GET_EDID) {
+
+ reg = I2CRead(p_ch7xxx_context,0x50);
+
+ if (!(LHFM_RET_ERROR & reg)) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ for (ie=0; ie<16; ie++) edid[j+ie] = I2CRead(p_ch7xxx_context,es_map[ie] );
+ break;
+ }
+ else
+ return SS_FIRMWARE_ERR;
+
+ }
+
+
+ } //while block
+
+ status = SS_SUCCESS;
+
+ } //for
+
+ for(i=0;i<8;i++)
+ if (edid_header[i] != edid[i]) {
+ return SS_FIRMWARE_ERR;
+ }
+
+ (*ebn)++;
+
+ if(flag & 0x80 && (edid[0x7E] > 0) ) {
+ PD_DEBUG("ch7036: LHFM_get_edid- incorrect # of VGA EDID blocks read [%x]\n",edid[0x7E]);
+ return SS_FIRMWARE_ERR;
+ }
+
+ k2 = edid[0x7E];
+
+ k2 = (k2 > 3)? 3 : k2;
+
+ if (k2>0) { //case: there are more than 1 blocks
+ for (k1=1; k1<=k2; k1++) {
+
+ for(i=k1*8; i < 8+k1*8; i++,j+=16){
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ I2CWrite(p_ch7xxx_context,0x50, i + flag);
+ I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_EDID));
+ wj = 0;
+
+ status = SS_FIRMWARE_TIMEOUT;
+ PD_DEBUG("ch7036: LHFM_get_edid- block [%d] - getting [%d]- 16 bytes - wj=[0x%x]\n",k1,i+1,wj);
+ while (wj++< (2*LHFM_TIMEOUT)) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ pd_usleep(SLEEP_TIME);
+
+ reg = I2CRead(p_ch7xxx_context,0x4F);
+
+ if(reg == LHFM_GET_EDID) {
+ reg = I2CRead(p_ch7xxx_context,0x50);
+ if (!(LHFM_RET_ERROR & reg)) {
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ for (ie=0; ie<16; ie++) edid[j+ie] = I2CRead(p_ch7xxx_context,es_map[ie] );
+ break;
+ }
+ else
+ return SS_FIRMWARE_ERR;
+
+
+ }
+
+ } //while
+
+ status = SS_SUCCESS;
+
+ }//nested for
+
+ (*ebn)++;
+
+ } //outermost for
+
+
+ } //if- case: there are more than 1 blocks
+
+ } //else - case: mcu is ready to serve host request
+
+ return status;
+
+}
+
+
+int LHFM_load_firmware(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+
+ unsigned fs1;
+ unsigned char ch;
+
+ PD_DEBUG("ch7036: LHFM_load_firmware- firmware size [0x%.8X]\n",lhfm_size);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ ch = 0x29 | I2CRead(p_ch7xxx_context,0x52);
+ I2CWrite(p_ch7xxx_context,0x52, ch & 0xFB);
+
+
+ I2CWrite(p_ch7xxx_context,0x5B, 0x9E);
+ I2CWrite(p_ch7xxx_context,0x5B, 0xB3);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ I2CWrite(p_ch7xxx_context,0x03, 0x07);
+
+ for (fs1=0; fs1<lhfm_size; fs1++)
+ I2CWrite(p_ch7xxx_context, 0x07, lhfm_array[fs1]);
+
+
+
+ I2CWrite(p_ch7xxx_context, 0x03, 0x03);
+ ch = I2CRead(p_ch7xxx_context,0x74);
+ if (ch & 0x1) {
+
+ return -1;
+ }
+ else {
+
+ I2CWrite( p_ch7xxx_context,0x03, 0x04);
+ ch = I2CRead(p_ch7xxx_context,0x52);
+ I2CWrite(p_ch7xxx_context, 0x52, ch | 0x24);
+ }
+
+ I2CWrite(p_ch7xxx_context, 0x03, 0x00);
+
+ return 0;
+}
+#if 0
+void ch7036_dump( char *s, int size, unsigned char *regdata)
+{
+ char temp[18];
+ int ch;
+
+ int i,j, size1;
+
+ temp[16] = '?';
+ temp[17] = '\n';
+
+ PD_DEBUG("\n");
+ PD_DEBUG("+--------------------------------------------------------------------+\n");
+ PD_DEBUG("|%s |\n",s);
+ PD_DEBUG("+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-----------------+\n");
+ PD_DEBUG("| | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F| |\n");
+ PD_DEBUG("++++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-----------------+\n");
+
+ size1 = size % 16;
+ size = size/16;
+
+ for (i=0; i<size; i++) {
+
+
+ PD_DEBUG("|%02x>", 0xFF & i*16);
+
+
+ for (j=0; j<16; j++) {
+ ch = regdata[i*16+j];
+ PD_DEBUG("%02X|", ch);
+
+#if 0
+
+
+ if( (ch >= 0x30 && ch <= 0x39) || (ch >= 0x61 && ch <= 0x7A) || (ch >= 0x41 && ch <= 0x5C) )
+ temp[j]='.';
+ else
+ temp[j]=(char)ch;
+#endif
+
+ }
+
+ PD_DEBUG("\n");
+ }
+
+ if (size1) {
+
+ PD_DEBUG( "|%02x>", 0xFF & size*16);
+
+ for (j=0; j<size1; j++) {
+ ch = regdata[size*16+j];
+ PD_DEBUG("%02X|", ch);
+#if 0
+
+ if( (ch >= 0x30 && ch <= 0x39) || (ch >= 0x61 && ch <= 0x7A) || (ch >= 0x41 && ch <= 0x5C) )
+ temp[j]='.';
+ else
+ temp[j]=(char)ch;
+#endif
+
+ }
+ for (j=size1; j<16; j++) {
+
+ PD_DEBUG(" ");
+
+ }
+
+ }
+
+ PD_DEBUG("\n");
+
+ return;
+}
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
new file mode 100755
index 0000000..cc4a321
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
@@ -0,0 +1,213 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_fw.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef H_FW_OPER_H
+#define H_FW_OPER_H
+
+#include "ch7036_typedef.h"
+
+
+//#include <linux/kernel.h>
+
+#define CFG_CAP_EDID 0x01
+#define CFG_CAP_HDCP 0x02
+
+typedef unsigned char ch7036_attr_table_index_t;
+
+
+typedef struct _FW7036_CFG {
+ unsigned char size;
+ unsigned char ver_major;
+ unsigned char ver_minor;
+ unsigned char did;
+ unsigned char rid;
+ unsigned char capbility;
+ unsigned char reserved;
+} FW7036_CFG;
+
+
+#define LHFM_GET_VERSION 0x1F
+#define LHFM_GET_HPD 0x06
+#define LHFM_GET_EDID 0x01
+#define LHFM_GET_MODEINFO 0x03
+#define LHFM_GET_VGA_MODEINFO 0x33
+#define LHFM_HDMI_ONOFF 0x04
+#define LHFM_REQUEST 0x40
+#define LHFM_RET_ERROR 0x80
+
+int LHFM_get_version(DEV_CONTEXT* p_ch7xxx_context,struct _FW7036_CFG* cfg);
+
+void LHFM_enable_crt_hpd(DEV_CONTEXT* p_ch7xxx_context);
+ch7036_status_t LHFM_get_crt_hpd(DEV_CONTEXT* p_ch7xxx_context);
+int LHFM_hdmi_onoff(int turnon);
+ch7036_status_t LHFM_get_hdmi_modeinfo(DEV_CONTEXT* p_ch7xxx_context,unsigned char *minfo);
+ch7036_status_t LHFM_get_edid(DEV_CONTEXT* p_ch7xxx_context,unsigned char*edid, unsigned char* ebn, unsigned char flag);
+int LHFM_load_firmware(DEV_CONTEXT* pDevContext);
+void ch7036_dump( char *s, int size, unsigned char *regdata);
+
+#define GET_VER 0x01
+#define GET_HPD 0x02
+#define GET_EDID 0x04
+#define GET_HDMI_DISPLAY_MODES 0x08
+
+#define GET_CRT_HPD 0x10
+#define GET_CRT_EDID 0x20
+
+#define CH7036_HDMI_DDC 0
+#define CH7036_VGA_DDC 0x80
+
+#define MAX_EDID_BLOCKS 2
+
+#define MAX_I2C_BLOCK_SIZE 32
+
+
+
+
+#define NUM_OF_BLOCKS 0x0F
+#define DTD_SIZE 0x12
+#define EDID_SIZE 0x0100
+#define EDID_STRUCTURE_VERSION 0x12
+#define EDID_STRUCTURE_REVISION 0x13
+#define EDID_FEATURE_SUPPORT 0x18
+#define EDID_ESTABLISHED_TIMINGS_1 0x23
+#define EDID_ESTABLISHED_TIMINGS_2 0x24
+#define EDID_MANUFACTURERS_RESERVED_TIMINGS 0x25
+#define EDID_STANDARD_TIMINGS 0x26
+#define EDID_STANDARD_TIMINGS_BIT_DESCRIPTION 0x27
+#define EDID_DETAILED_TIMING_DESCRIPTION_1 0x36
+#define EDID_DETAILED_TIMING_DESCRIPTION_2 0x48
+#define EDID_DETAILED_TIMING_DESCRIPTION_3 0x5A
+
+#define EDID_EXTENSION_FLAG 0x7E
+
+#define EDID_CEA_TAG 0x80
+#define EDID_CEA_REVISION 0x81
+#define EDID_CEA_DETAILED_TIMING_DATA_OFFSET 0x82
+#define EDID_CEA_VIDEO_DATA_BLOCK 0x84
+#define EDID_CEA_DATA_BLOCK 0x84
+
+#define EDID_CEA_VIDEO_DATA_BLOCK_2 0x96
+#define EDID_CEA_VIDEO_DATA_BLOCK_3 0xA8
+#define EDID_CEA_VIDEO_DATA_BLOCK_4 0xBA
+#define EDID_CEA_VIDEO_DATA_BLOCK_5 0xCC
+#define EDID_CEA_VIDEO_DATA_BLOCK_6 0xDE
+
+#define EDID_SPACE_INDEX_START 0x18
+
+
+
+
+
+typedef struct {
+ unsigned char is_supported;
+ char mode_name[13];
+ unsigned long index[3];
+
+}established_timings_t, *p_established_timings;
+
+typedef struct {
+ unsigned int ha;
+ unsigned int va;
+ unsigned char refresh_rate;
+}standard_timings_t, *p_standard_timings;
+
+
+
+typedef struct {
+ unsigned char pclk_lobyte;
+ unsigned char pclk_hibyte;
+ unsigned char hactive_lobyte;
+ unsigned char hblank_lobyte;
+ unsigned char hactive_blank;
+ unsigned char vactive_lobyte;
+ unsigned char vblank_lobyte;
+ unsigned char vactive_blank;
+ unsigned char hsync_off_lobyte;
+ unsigned char hsync_pulse_width;
+ unsigned char vsync_off_pulse_width;
+
+ unsigned char hsopw_vsopw;
+
+
+
+ unsigned char himage_size_lobyte;
+ unsigned char vimage_size_lobyte;
+ unsigned char hvimage_size;
+
+ unsigned char hborder;
+ unsigned char vborder;
+ unsigned char flags;
+}dtd_t, *p_dtd;
+
+
+typedef struct monitor_range {
+
+ unsigned char hrate_min;
+ unsigned char hrate_max;
+ unsigned char vrate_min;
+ unsigned char vrate_max;
+
+ unsigned long pclk_max;
+
+}monitor_range_t;
+
+
+typedef struct detailed_timing_block {
+ unsigned long data_tag;
+ OUT_FMT dtiming;
+} dtblks_t;
+
+
+typedef struct edid_blk {
+
+
+ unsigned char is_edid;
+ unsigned char is_preferred_timing;
+
+ unsigned char ebn;
+ unsigned char edidblk[EDID_SIZE];
+
+ established_timings_t *etiming_I;
+ established_timings_t *etiming_II;
+ established_timings_t *etiming_man;
+
+ standard_timings_t stiming[8];
+
+ standard_timings_t stiming_x[6];
+ monitor_range_t rtiming;
+
+ dtblks_t dtblk[4];
+
+
+ unsigned char supported_modes[15];
+ ch7036_attr_table_index_t modes[MAX_ATTR_LIST_SIZE];
+
+} ch7036_edid_blk_t;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
new file mode 100755
index 0000000..5a842ab
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
@@ -0,0 +1,296 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_iic.c
+* @version 1.2.4
+*-----------------------------------------------------------------------------
+*/
+
+
+
+
+
+#include "ch7036_iic.h"
+#include "ch7036_def_regmap.h"
+
+
+static uint8 g_nCurPage = 0;
+static uint8 g_nCurRegmap[REG_PAGE_NUM][REG_NUM_PER_PAGE];
+
+int g_verbose = 0;
+
+void DeviceReset(DEV_CONTEXT* pDevContext)
+{
+
+ uint8 reg=0x00;
+
+ I2CWrite(pDevContext,0x03, 0x04);
+
+ I2CWrite(pDevContext,0x52, 0x2B);
+ I2CWrite(pDevContext,0x5a, 0x06);
+ I2CWrite(pDevContext,0x5a, 0x04);
+ I2CWrite(pDevContext,0x5a, 0x06);
+
+ I2CWrite(pDevContext,0x52, 0x29);
+ I2CWrite(pDevContext,0x52, 0x2b);
+
+ I2CWrite(pDevContext,0x5a, 0x04);
+
+
+ I2CWrite(pDevContext,0x03, 0x01);
+ reg = I2CRead(pDevContext,0x16);
+
+ reg = reg & 0xF7;
+ I2CWrite(pDevContext,0x16, reg);
+
+
+
+}
+
+
+void DeviceSetup(DEV_CONTEXT* pDevContext)
+{
+ if (g_verbose) {
+ uint8 page, index;
+ uint16 k =0;
+ uint16 rc[5];
+ for(page=0; page<REG_PAGE_NUM; ++page)
+ {
+ rc[page]=0;
+ if(page == 0x02) continue;
+ I2CWrite(pDevContext,0x03, page);
+ for(index=0x07; index<REG_NUM_PER_PAGE; ++index)
+ {
+ if(g_nCurRegmap[page][index] != g_DefRegMap[page][index])
+ {
+
+ k++;
+ rc[page]++;
+ I2CWrite(pDevContext,index, g_nCurRegmap[page][index]);
+
+ }
+ }
+ }
+
+ for(page=0; page<REG_PAGE_NUM; ++page)
+
+ ;
+
+ }
+ else {
+ uint8 page, index;
+ for(page=0; page<REG_PAGE_NUM; ++page)
+ {
+ if(page == 0x02) continue;
+ I2CWrite(pDevContext,0x03, page);
+ for(index=0x07; index<REG_NUM_PER_PAGE; ++index)
+ {
+ if(g_nCurRegmap[page][index] != g_DefRegMap[page][index])
+ {
+ I2CWrite(pDevContext,index, g_nCurRegmap[page][index]);
+ }
+ }
+ }
+ }
+}
+
+
+uint8 iic_read(uint8 index)
+{
+ return g_nCurRegmap[g_nCurPage][index];
+}
+
+void iic_write(uint8 index, uint8 value)
+{
+ if(index == 0x03)
+ {
+ g_nCurPage = value;
+ }
+ else
+ {
+ g_nCurRegmap[g_nCurPage][index] = value;
+ }
+}
+
+void iic_reset()
+{
+ uint8 page, index;
+ for(page=0; page<REG_PAGE_NUM; ++page)
+ {
+ for(index=0; index<REG_NUM_PER_PAGE; ++index)
+ {
+ g_nCurRegmap[page][index] = g_DefRegMap[page][index];
+ }
+ }
+ g_nCurPage = 0x00;
+}
+
+uint32 iic_read_ex(MULTI_REG_ID reg_id)
+{
+ uint8 oldpage;
+ uint32 n0, n1, n2, n3, mask, i, value;
+
+
+ n0 = n1 = n2 = n3 = value = mask = 0;
+
+
+ i = (uint32)reg_id;
+
+
+ oldpage = iic_read(0x03);
+ iic_write(0x03, g_MultiRegTable[i].PageIndex);
+
+ if(NOOP_INDEX != g_MultiRegTable[i].TopRegIndex)
+ n0 = iic_read(g_MultiRegTable[i].TopRegIndex);
+
+ if(NOOP_INDEX != g_MultiRegTable[i].HighRegIndex)
+ n1 = iic_read(g_MultiRegTable[i].HighRegIndex);
+
+ if(NOOP_INDEX != g_MultiRegTable[i].MiddleRegIndex)
+ n2 = iic_read(g_MultiRegTable[i].MiddleRegIndex);
+
+ n3 = iic_read(g_MultiRegTable[i].LowRegIndex);
+
+ iic_write(0x03, oldpage);
+
+ if(0 != n0)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].TopEndBit - g_MultiRegTable[i].TopStartBit + 1;
+ mask -= 1;
+ mask <<= g_MultiRegTable[i].TopStartBit;
+ n0 &= mask;
+ n0 >>= g_MultiRegTable[i].TopStartBit;
+ n0 <<= (g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1)+(g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1) + (g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1);
+ }
+ if(0 != n1)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+ mask -= 1;
+ mask <<= g_MultiRegTable[i].HighStartBit;
+ n1 &= mask;
+ n1 >>= g_MultiRegTable[i].HighStartBit;
+ n1 <<= (g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1) + (g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1);
+ }
+
+ if(0 != n2)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+ mask -= 1;
+ mask <<= g_MultiRegTable[i].MiddleStartBit;
+ n2 &= mask;
+ n2 >>= g_MultiRegTable[i].MiddleStartBit;
+ n2 <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+ }
+
+ if(0 != n3)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+ mask -= 1;
+ mask <<= g_MultiRegTable[i].LowStartBit;
+ n3 &= mask;
+ n3 >>= g_MultiRegTable[i].LowStartBit;
+ }
+
+ value = n0 | n1 | n2 | n3;
+ return value;
+}
+
+void iic_write_ex(MULTI_REG_ID reg_id, uint32 value)
+{
+ uint8 oldpage;
+ uint32 n1, n2, n3, n4, mask, nOrigin, i, value_local;
+
+
+ n1 = n2 = n3 = n4 = mask = nOrigin = i = 0;
+ value_local = value;
+
+
+ i = (uint32)reg_id;
+
+
+ oldpage = iic_read(0x03);
+ iic_write(0x03, g_MultiRegTable[i].PageIndex);
+
+ mask = 1;
+ mask <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+ mask -= 1;
+ n1 = value_local & mask;
+ n1 <<= g_MultiRegTable[i].LowStartBit;
+ nOrigin = iic_read(g_MultiRegTable[i].LowRegIndex);
+ mask <<= g_MultiRegTable[i].LowStartBit;
+ nOrigin &= ~mask;
+ n1 |= nOrigin;
+ iic_write(g_MultiRegTable[i].LowRegIndex, (uint8)n1);
+ value_local >>= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+
+ if(NOOP_INDEX != g_MultiRegTable[i].MiddleRegIndex)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+ mask -= 1;
+ n2 = value_local & mask;
+ n2 <<= g_MultiRegTable[i].MiddleStartBit;
+ nOrigin = iic_read(g_MultiRegTable[i].MiddleRegIndex);
+ mask <<= g_MultiRegTable[i].MiddleStartBit;
+ nOrigin &= ~mask;
+ n2 |= nOrigin;
+ iic_write(g_MultiRegTable[i].MiddleRegIndex, (uint8)n2);
+ value_local >>= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+
+ if(NOOP_INDEX != g_MultiRegTable[i].HighRegIndex)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+ mask -= 1;
+ n3 = value_local & mask;
+ n3 <<= g_MultiRegTable[i].HighStartBit;
+ nOrigin = iic_read(g_MultiRegTable[i].HighRegIndex);
+ mask <<= g_MultiRegTable[i].HighStartBit;
+ nOrigin &= ~mask;
+ n3 |= nOrigin;
+ iic_write(g_MultiRegTable[i].HighRegIndex, (uint8)n3);
+ value_local >>= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+
+ if(NOOP_INDEX != g_MultiRegTable[i].TopRegIndex)
+ {
+ mask = 1;
+ mask <<= g_MultiRegTable[i].TopEndBit - g_MultiRegTable[i].TopStartBit +1;
+ mask -= 1;
+ n4 = value_local & mask;
+ n4 <<= g_MultiRegTable[i].TopStartBit;
+ nOrigin = iic_read(g_MultiRegTable[i].TopRegIndex);
+ mask <<= g_MultiRegTable[i].TopStartBit;
+ nOrigin &= ~mask;
+ n4 |= nOrigin;
+ iic_write(g_MultiRegTable[i].TopRegIndex,(uint8)n4);
+ }
+ }
+ }
+
+ iic_write(0x03, oldpage);
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
new file mode 100755
index 0000000..593aee8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
@@ -0,0 +1,52 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_iic.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_IIC_H
+#define _CH7036_IIC_H
+
+#include "ch7036_typedef.h"
+#include "ch7036_reg_table.h"
+
+
+
+
+uint8 I2CRead(DEV_CONTEXT* pDevContext, uint8 index);
+void I2CWrite(DEV_CONTEXT* pDevContext, uint8 index, uint8 value);
+
+void I2CBlockWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8* value, uint16 len);
+void DeviceReset(DEV_CONTEXT* pDevContext);
+void DeviceSetup(DEV_CONTEXT* pDevContext);
+
+uint8 iic_read(uint8 index);
+void iic_write(uint8 index, uint8 value);
+void iic_reset(void);
+uint32 iic_read_ex(MULTI_REG_ID reg_id);
+void iic_write_ex(MULTI_REG_ID reg_id, uint32 reg_val);
+
+extern int g_verbose;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
new file mode 100644
index 0000000..bc7b8a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
@@ -0,0 +1,1994 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_intf.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+
+#ifdef T_LINUX
+ #include "lvds/lvds.h"
+#else
+ #include "lvds.h"
+#endif
+
+
+ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd);
+
+unsigned long ch7036_invis_6x4_modes_table_size[3] = {2,3,5};
+unsigned long ch7036_invis_8x6_7x4_table_size[3] = {3,5,6};
+
+OUT_FMT hdmi_timing_table[OUT_HDMI_END] = {
+
+
+ {1, 25175, 1, {800, 640, 16, 96, 525, 480, 10, 2, 59, SCANTYPE_PROGRESSIVE} },
+ {1, 25250, 1, {800, 640, 16, 96, 525, 480, 10, 2, 60, SCANTYPE_PROGRESSIVE} },
+ {2, 27000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 59, SCANTYPE_PROGRESSIVE} },
+ {2, 27027, 1, {858, 720, 16, 62, 525, 480, 9, 6, 60, SCANTYPE_PROGRESSIVE} },
+ {17, 27000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
+
+ {4, 74176, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 59, SCANTYPE_PROGRESSIVE} },
+ {4, 74250, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 60, SCANTYPE_PROGRESSIVE} },
+ {5, 74176, 2, {2200, 1920, 88, 44, 1125, 1080, 2, 5, 59, SCANTYPE_INTERLACED} },
+ {5, 74250, 2, {2200, 1920, 88, 44, 1125, 1080, 2, 5, 60, SCANTYPE_INTERLACED} },
+ {16, 148350, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 59, SCANTYPE_PROGRESSIVE} },
+// {16, 148352, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 59, SCANTYPE_PROGRESSIVE} },
+ {16, 148500, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
+
+// {17, 27000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
+ {19, 74250, 2, {1980, 1280, 440, 40, 750, 720, 5, 5, 50, SCANTYPE_PROGRESSIVE} },
+
+ {20, 74250, 2, {2640, 1920, 528, 44, 1125, 1080, 2, 5, 50, SCANTYPE_INTERLACED} },
+
+
+ {31, 148500, 2, {2640, 1920, 528, 44, 1125, 1080, 4, 5, 50, SCANTYPE_PROGRESSIVE} },
+ {32, 74175, 2, {2750, 1920, 638, 44, 1125, 1080, 4, 5, 23, SCANTYPE_PROGRESSIVE} },
+ {32, 74250, 2, {2750, 1920, 638, 44, 1125, 1080, 4, 5, 24, SCANTYPE_PROGRESSIVE} },
+ {33, 74250, 2, {2640, 1920, 528, 44, 1125, 1080, 4, 5, 25, SCANTYPE_PROGRESSIVE} },
+ {34, 74175, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 29, SCANTYPE_PROGRESSIVE} },
+ {34, 74250, 2, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 30, SCANTYPE_PROGRESSIVE} },
+
+ {40, 148500, 2, {2640, 1920, 528, 44, 1124, 1080, 4, 10, 100, SCANTYPE_INTERLACED} },
+ {41, 148500, 2, {1980, 1280, 440, 40, 750, 720, 5, 5, 100, SCANTYPE_PROGRESSIVE} },
+ {42, 54000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 100, SCANTYPE_PROGRESSIVE} },
+
+
+ {46, 148352, 2, {2200, 1920, 88, 44, 1124, 1080, 4, 10, 119, SCANTYPE_INTERLACED} },
+ {46, 148500, 2, {2200, 1920, 88, 44, 1124, 1080, 4, 10, 120, SCANTYPE_INTERLACED} },
+
+ {47, 148352, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 119, SCANTYPE_PROGRESSIVE} },
+ {47, 148500, 2, {1650, 1280, 110, 40, 750, 720, 5, 5, 120, SCANTYPE_PROGRESSIVE} },
+
+ {48, 54000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 119, SCANTYPE_PROGRESSIVE} },
+ {48, 54054, 1, {858, 720, 16, 62, 525, 480, 9, 6, 120, SCANTYPE_PROGRESSIVE} },
+
+ {52, 108000, 1, {864, 720, 12, 64, 625, 576, 5, 5, 200, SCANTYPE_PROGRESSIVE} },
+
+ {56, 108000, 1, {858, 720, 16, 62, 525, 480, 9, 6, 239, SCANTYPE_PROGRESSIVE} },
+ {56, 108108, 1, {858, 720, 16, 62, 525, 480, 9, 6, 240, SCANTYPE_PROGRESSIVE} },
+
+};
+
+OUT_FMT dvi_timing_table[OUT_DVI_END] = {
+
+
+
+ {0, 25170, 0, { 800, 640, 16, 96, 525, 480, 10, 2, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 31500, 0, { 832, 640, 24, 40, 520, 480, 9, 3, 72, SCANTYPE_PROGRESSIVE} },
+ {0, 31500, 0, { 800, 640, 16, 96, 525, 480, 11, 2, 75, SCANTYPE_PROGRESSIVE} },
+
+ {0, 28322, 0, { 900, 720, 15, 108, 449, 400, 11, 2, 70, SCANTYPE_PROGRESSIVE} },
+
+ {0, 38100, 0, {1088, 800, 32, 128, 619, 600, 1, 4, 56, SCANTYPE_PROGRESSIVE} },
+
+
+ {0, 40000, 0, {1056, 800, 40, 128, 628, 600, 1, 4, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 50000, 0, {1040, 800, 56, 120, 666, 600, 37, 6, 72, SCANTYPE_PROGRESSIVE} },
+ {0, 49500, 0, {1056, 800, 16, 80, 624, 600, 1, 2, 75, SCANTYPE_PROGRESSIVE} },
+
+ {0, 65000, 0, {1344, 1024, 24, 136, 806, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 75000, 0, {1328, 1024, 24, 136, 806, 768, 3, 6, 70, SCANTYPE_PROGRESSIVE} },
+ {0, 78750, 0, {1312, 1024, 16, 96, 800, 768, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
+
+ {0, 81517, 0, {1688, 1152, 48,112,1066, 864, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 83460, 0, {1680, 1280, 64, 136, 828, 720, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 83865, 0, {1680, 1280, 64, 136, 828, 800, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 100638, 0, {1688, 1280, 48, 112, 1066, 960, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 108000, 0, {1688, 1280, 48, 112, 1066, 1024, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 135000, 0, {1688, 1280, 16, 144, 1066, 1024, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
+
+ {0, 85543, 0, {2256, 1360,104, 184, 1087, 768, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 85920, 0, {2256, 1366,104, 184, 1087, 768, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 121750, 0, {1864, 1400, 88,144,1089, 1050, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 156000, 0, {1896, 1400,104,144,1099, 1050, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
+
+
+ {0, 88750, 0, {1600, 1440, 48, 32, 926, 900, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 119000, 0, {1840, 1440, 48, 32, 1080, 1050, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 117936, 0, {2256, 1600,104, 184, 1250, 900, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 162000, 0, {2160, 1600, 64, 192, 1250, 1200, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+ {0, 147130, 0, {2256, 1680,104, 184, 1087, 1050, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 148500, 0, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
+ {0, 154000, 0, {2080, 1920, 48, 32, 1235, 1200, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+
+};
+
+
+
+
+OUT_FMT ch7036_crt_timing_table[OUT_CRT_END] = {
+
+
+ {100, 31500, 1, {832, 640, 32, 64, 445, 400, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+ {100, 25175, 1, {800, 640, 8, 96, 525, 480, 2, 2, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 31500, 1, {832, 640, 16, 40, 520, 480, 1, 3, 72, SCANTYPE_PROGRESSIVE} },
+ {100, 31500, 1, {840, 640, 16, 64, 500, 480, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
+ {100, 36000, 1, {832, 640, 56, 56, 509, 480, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+ {100, 35500, 1, {936, 720, 36, 72, 446, 400, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+
+
+ {100, 36000, 1, {1024, 800, 24, 72, 625, 600, 1, 2, 56, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 38250, 1, {1024, 800, 32, 80, 624, 600, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 50000, 1, {1040, 800, 56, 120, 666, 600, 37, 6, 72, SCANTYPE_PROGRESSIVE} },
+ {100, 49000, 1, {1040, 800, 40, 80, 629, 600, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
+ {100, 56750, 1, {1056, 800, 48, 80, 633, 600, 3, 4, 85, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 65000, 1, {1344, 1024, 24, 136, 806, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 75000, 1, {1328, 1024, 24, 136, 806, 768, 3, 6, 70, SCANTYPE_PROGRESSIVE} },
+ {100, 78750, 1, {1312, 1024, 16, 96, 800, 768, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
+
+ {100, 94500, 1, {1376, 1024, 48, 96, 808, 768, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 108000, 1, {1600, 1152, 64, 128, 900, 864, 1, 2, 75, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 79500, 1, {1664, 1280, 64, 128, 798, 768, 3, 7, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 102250, 1, {1696, 1280, 80, 128, 805, 768, 3, 7, 75, SCANTYPE_PROGRESSIVE} },
+ {100, 117500, 1, {1712, 1280, 80, 136, 809, 768, 3, 7, 85, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 108000, 1, {1800, 1280, 96, 112, 1000, 960, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 148500, 1, {1728, 1280, 64, 160, 1011, 960, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 108000, 1, {1688, 1280, 48, 112, 1066, 1024, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 135000, 1, {1688, 1280, 16, 144, 1066, 1024, 1, 3, 75, SCANTYPE_PROGRESSIVE} },
+ {100, 157500, 1, {1728, 1280, 64, 160, 1072, 1024, 1, 3, 85, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 85500, 1, {1792, 1360, 64, 112, 795, 768, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 121750, 1, {1864, 1400, 88,144,1089, 1050, 3, 4, 60, SCANTYPE_PROGRESSIVE} },
+ {100, 156000, 1, {1896, 1400,104,144,1099, 1050, 3, 4, 75, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 88750, 1, {1600, 1440, 48, 32, 926, 900, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 119000, 1, {1840, 1440, 48, 32, 1080, 1050, 3, 6, 60, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 117936, 1, {2256, 1600,104, 184, 1250, 900, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+
+ {100, 162000, 1, {2160, 1600, 64, 192, 1250, 1200, 1, 3, 60, SCANTYPE_PROGRESSIVE} },
+
+
+
+ {100, 148500, 1, {2200, 1920, 88, 44, 1125, 1080, 4, 5, 60, SCANTYPE_PROGRESSIVE} },
+
+
+
+};
+
+
+
+
+
+uint8 I2CRead(DEV_CONTEXT* pDevContext,uint8 index)
+{
+
+ ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+ pd_reg_t reg_list[2];
+
+ reg_list[0].reg = (i2c_reg_t)index;
+ reg_list[1].reg = PD_REG_LIST_END;
+
+ p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+ return (uint8)(reg_list[0].value);
+}
+
+void I2CWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8 value)
+{
+ ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+ pd_reg_t reg_list[2];
+
+
+
+ reg_list[0].reg = (i2c_reg_t)index;
+ reg_list[0].value = (i2c_reg_t)value;
+
+ reg_list[1].reg = PD_REG_LIST_END;
+
+ p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+ return;
+}
+
+
+void I2CBlockWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8* value, uint16 len)
+{
+ ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+ pd_reg_t reg_list[MAX_I2C_BLOCK_SIZE +1];
+ uint16 i=0;
+
+
+ for(i=0;i<len;i++) {
+ reg_list[i].reg = (i2c_reg_t)index;
+ reg_list[i].value = (i2c_reg_t)value[i];
+ }
+
+ reg_list[len].reg = PD_REG_LIST_END;
+
+ p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+ return;
+}
+
+ch7036_status_t ch7036_device_prepare(ch7036_device_context_t* p_ctx)
+{
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status = SS_SUCCESS;
+
+ PD_DEBUG("ch7036_intf: ch7036_device_prepare()\n");
+
+
+ if(!DevicePrepare(p_ch_ctx))
+ {
+ p_ctx->last_emsg = GetLastErrorMessage();
+ status = SS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+ch7036_status_t ch7036_device_config(ch7036_device_context_t* p_ctx)
+{
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status = SS_SUCCESS;
+
+ PD_DEBUG("ch7036_intf: ch7036_device_config()\n");
+
+
+ if(!DeviceConfig(p_ch_ctx))
+ {
+ p_ctx->last_emsg = GetLastErrorMessage();
+ status = SS_UNSUCCESSFUL;
+ }
+
+ return status;
+
+}
+
+ch7036_status_t ch7036_device_start(ch7036_device_context_t* p_ctx)
+{
+
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status = SS_SUCCESS;
+
+ PD_DEBUG("ch7036_intf: ch7036_device_start()\n");
+
+ if(!DeviceRunning(p_ch_ctx))
+ {
+ p_ctx->last_emsg = GetLastErrorMessage();
+ status = SS_UNSUCCESSFUL;
+ }
+
+ return status;
+
+}
+
+ch7036_status_t ch7036_device_set_power(ch7036_device_context_t* p_ctx, unsigned long channel)
+{
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status = SS_SUCCESS;
+
+ PD_DEBUG("ch7036_intf: ch7036_device_set_power()- channel [%x]\n", channel);
+
+ if(!DeviceSetPower(p_ch_ctx,channel))
+ {
+ p_ctx->last_emsg = GetLastErrorMessage();
+ status = SS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+
+
+ch7036_status_t ch7036_load_firmware(ch7036_device_context_t* p_ctx)
+{
+
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+
+ ch7036_status_t status = SS_UNSUCCESSFUL;
+
+ PD_DEBUG("ch7036: ch7036_load_firmware()\n");
+
+
+ if(LHFM_load_firmware(p_ch_ctx) == -1) {
+ PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading FAILED...\n");
+
+ }
+ else {
+ PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading is a SUCCESS\n");
+ status = SS_SUCCESS;
+ }
+
+
+ return status;
+
+}
+
+
+
+
+
+
+ch7036_status_t ch7036_get_hdvi_display_modes_supported(ch7036_device_context_t* p_ctx)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status;
+ ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+
+ PD_DEBUG("ch7036_get_hdvi_display_modes_supported()- enter\n");
+
+ status = LHFM_get_hdmi_modeinfo(p_ch7xxx_context,p_hedid->supported_modes);
+
+ if (status == SS_SUCCESS) {
+
+ PD_DEBUG("HDMI_Modes=%02X. Vesa_Modes=%02x\r\n", p_hedid->supported_modes[13], p_hedid->supported_modes[14]);
+
+
+ }
+ else {
+ PD_DEBUG("ch7036_get_hdvi_display_modes_supported()-- failed!\r\n");
+ PD_DEBUG("status: [%s]\n",status == SS_FIRMWARE_TIMEOUT?"timeout!":"firmware_error!");
+
+
+ }
+
+ return status;
+}
+
+
+
+ch7036_status_t ch7036_read_edid(ch7036_device_context_t* p_ctx, uint32 channel)
+{
+
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ ch7036_status_t status = SS_UNSUCCESSFUL;
+
+
#ifdef T_CH7036_EDID_DUMP
+ uint8 ebn;
+ int i;
+#endif
+
+ ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+ ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+
+ unsigned char* hedidblk = p_hedid->edidblk;
+ unsigned char* cedidblk = p_cedid->edidblk;
+
+
+
+ switch (channel) {
+
+ case CHANNEL_LVDS_HDMI:
+ case CHANNEL_HDMI:
+
+
+ status = LHFM_get_edid(p_ch7xxx_context,hedidblk, &(p_hedid->ebn), CH7036_HDMI_DDC);
+
+ if(status == SS_SUCCESS) {
+
+ PD_DEBUG("ch7036_read_edid()-hdmi-dvi hpd status- attached, hdmi-dvi edid read is a SUCCESS\n");
+ PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_hedid->ebn);
+
+ p_hedid->is_edid = 1;
+ if(p_hedid->ebn == 1)
+ pOutput_Info->hdmi_fmt.is_dvi_mode =1;
+
+ else
+ pOutput_Info->hdmi_fmt.is_dvi_mode =0;
+
+
+
+#ifdef T_CH7036_EDID_DUMP
+
+ if (p_hedid->ebn <= MAX_EDID_BLOCKS) {
+ for (i=0; i<p_hedid->ebn; i++)
+ ch7036_dump("HDMI-DVI EDID Data", 128, &hedidblk[i*128]);
+
+ }
+
+#endif
+
+ }
+
+ else {
+ p_hedid->is_edid = 0;
+
+ status = SS_UNSUCCESSFUL;
+
+ }
+
+ break;
+
+ case CHANNEL_LVDS_VGA:
+ case CHANNEL_VGA:
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ I2CWrite(p_ch7xxx_context,0x0F, I2CRead(p_ch7xxx_context,0x0F) & 0x7F);
+ pd_usleep(200);
+
+ status = LHFM_get_edid(p_ch7xxx_context,cedidblk, &(p_cedid->ebn), CH7036_VGA_DDC);
+ if (status== SS_SUCCESS) {
+ p_cedid->is_edid =1;
+ PD_DEBUG("ch7036_read_edid()- crt hpd status- attached, crt edid read is a SUCCESS\n");
+ PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_cedid->ebn);
+
+#ifdef T_CH7036_EDID_DUMP
+ if (p_cedid->ebn <= MAX_EDID_BLOCKS)
+ for (i=0; i<p_cedid->ebn; i++)
+ ch7036_dump("VGA EDID Data", 128, &cedidblk[i*128]);
+
+
+#endif
+
+ }
+ else {
+ p_cedid->is_edid =0;
+
+ status = SS_UNSUCCESSFUL;
+ }
+
+
+ break;
+
+ default:
+ break;
+
+
+ }
+
+
+ return status;
+}
+
+ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ ch7036_status_t status= SS_SUCCESS;
+ unsigned char reg, reg_hpdpw;
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x03);
+ reg = I2CRead(p_ch7xxx_context,0x25);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg_hpdpw = I2CRead(p_ch7xxx_context,0x51);
+
+#ifdef T_CONFIG_PLB
+ if(!(reg & 0x10) && (reg_hpdpw & 0x80) ){
+ reg= 0x10;
+ }
+#endif
+
+ switch (reg & 0x10) {
+ case 0x10:
+ if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
+ *hpd = 0x01;
+ else
+ *hpd = 0x81;
+ break;
+ case 0x00:
+ if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
+ *hpd = 0x80;
+ else
+ *hpd = 0x00;
+ break;
+ }
+
+
+ PD_DEBUG("ch7036: ch7036_get_hdmi_hpd- exit...*hpd [0x%x]\n",*hpd);
+
+ return status;
+
+}
+ch7036_status_t ch7036_get_attached_device(ch7036_device_context_t* p_ctx)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ uint8 reg;
+ ch7036_status_t status = SS_SUCCESS;
+ ch7036_status_t status_hdmi, status_crt;
+
+ ch7036_edid_blk_t * p_hedid = (ch7036_edid_blk_t *)(p_ctx->hedid);
+
+ uint8 hpd = 0;
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x52);
+
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x52, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x0);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+
+ reg = reg & 0x70;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x0F);
+
+ reg = reg & 0x7F;
+ I2CWrite(p_ch7xxx_context,0x0F, reg);
+
+ I2CWrite(p_ch7xxx_context,0x0E, I2CRead(p_ch7xxx_context,0x0E) & 0x7F);
+
+ PD_DEBUG("ch7036_get_attached_device()- enter- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
+
+ status_hdmi = ch7036_get_hdmi_hpd(p_ctx,&hpd);
+ LHFM_enable_crt_hpd(p_ch7xxx_context);
+ status_crt = LHFM_get_crt_hpd(p_ch7xxx_context);
+
+ PD_DEBUG("ch7036_get_attached_device()- enter- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
+
+ if(p_ctx->man_sel_out==1) { //manual selection
+
+
+ if( (status_crt == SS_SUCCESS) || ( (hpd & 0x01)== 1 ) ) {
+
+ switch (pOutput_Info->channel) {
+ case CHANNEL_LVDS_DVI:
+ case CHANNEL_DVI:
+ case CHANNEL_LVDS_HDMI:
+ case CHANNEL_HDMI:
+
+
+ if( (status_crt == SS_SUCCESS) && ( (hpd & 0x01)== 0 ) ) {
+
+ p_ctx->hpd = 0x16; //bit 4=1 to indicate SS_DISPLAY_CHOICE_NOT_ALLOWED, check edid and parse it
+ status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+
+ }
+ else {
+
+ if (!p_ctx->init_done || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) != 0x02 )
+ p_ctx->hpd = 0x60;
+ else
+ p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) == 0x02)?0xA0:0x60;
+
+ status = SS_SUCCESS;
+ }
+
+ break;
+
+ case CHANNEL_LVDS_VGA:
+ case CHANNEL_VGA:
+
+
+ if((status_crt != SS_SUCCESS) && ((hpd & 0x01)==1 ) ) {
+
+ if(!p_ctx->init_done) {
+ p_ctx->hpd = 0x06;
+ status = SS_SUCCESS;
+
+ }else {
+ p_ctx->hpd = (hpd & 0x80)?0x70:0x30;
+ status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+ }
+
+ }
+ else {
+
+ if ( (!p_ctx->init_done) || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) != 0x04 )//at init, need to read edid, and parse it
+ p_ctx->hpd = 0x06;
+ else {
+ p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) == 0x04)?0x0A:0x06;
+
+ }
+
+ status = SS_SUCCESS;
+ }
+
+ break;
+ } //switch
+
+ if(status == SS_DISPLAY_CHOICE_NOT_ALLOWED)
+ PD_DEBUG("ch7036_get_attached_device()- manual selection- display choice is not allowed...\n");
+
+ }
+ else {
+
+ if (!p_ctx->init_done) {
+ p_ctx->hpd = 0x06;
+ status = SS_SUCCESS;
+
+ }else {
+
+ PD_DEBUG("ch7036_get_attached_device()- manual selection- none is connected- not allowed...\n");
+
+ status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+ p_ctx->hpd = 0x50;
+
+ }
+
+
+ }
+
+ PD_DEBUG("ch7036_get_attached_device()- manual selection- exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
+ PD_DEBUG("ch7036_get_attached_device()- exit- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x03);
+ reg = I2CRead(p_ch7xxx_context,0x25);
+
+ PD_DEBUG("ch7036_get_attached_device()- manual selection- exit...HPD_MCU [0x%x]\n",reg);
+
+ return status;
+ }
+
+ //auto detection
+
+ if(status_hdmi == SS_SUCCESS) {
+
+ if( hpd == 0x81 ) {
+ if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) {
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED);
+
+ ch7036_get_hdvi_display_modes_supported(p_ctx);
+
+ if (
+ ((pOutput_Info->hdmi_fmt.is_dvi_mode== 0) && (p_hedid->supported_modes[13] == 0) )||
+ ((pOutput_Info->hdmi_fmt.is_dvi_mode== 1) && (p_hedid->supported_modes[13] > 0))
+ ) {
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed [HDMI<->DVI] since last query and it's HIGH\n");
+
+ }
+ else
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n");
+ }
+ else {
+
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's HIGH\n");
+ }
+ }
+ else if (hpd ==0x80) {
+ if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 ) {
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~ CH7036HPD_HDVI_STATUS_CHANGED) & (~CH7036HPD_HDVI_ATTACHED)) ;
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status not changed since last query and it's LOW\n");
+ }
+ else {
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED & (~CH7036HPD_HDVI_ATTACHED)) ;
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's LOW\n");
+ }
+
+ }
+ else if (hpd == 0x01) {
+
+ p_ctx->hpd = (p_ctx->hpd & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED);
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n");
+ }
+ else {
+
+ p_ctx->hpd &= 0x9F;
+ PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's LOW\n");
+ }
+
+
+
+ PD_DEBUG("ch7036: ch7036_get_attached_device()- SUCCESS- hdmi hpd [0x%x]\n", hpd);
+
+ }
+ else {
+
+
+ if ( (!p_ctx->init_done) && (hpd == 0x86) ) {
+
+ p_ctx->hpd |= CH7036HPD_HDVI_ATTACHED;
+
+ }
+
+ else {
+ p_ctx->hpd &= ~CH7036HPD_HDVI_ATTACHED;
+
+ }
+
+ }
+
+ if(status_crt == SS_SUCCESS) {
+
+ if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED )== CH7036HPD_CRT_ATTACHED)
+ p_ctx->hpd = (p_ctx->hpd & 0xF9) & ((~CH7036HPD_CRT_STATUS_CHANGED) | CH7036HPD_CRT_ATTACHED);
+
+ else
+ p_ctx->hpd = ((p_ctx->hpd & 0xF9) | ( CH7036HPD_CRT_STATUS_CHANGED | CH7036HPD_CRT_ATTACHED));
+
+ }
+ else {
+
+ if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED ) == 0 ) {
+ p_ctx->hpd &= 0xF9;
+
+ if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)== 0 )
+ p_ctx->hpd |= 0x06;
+
+ }
+ else {
+
+ if ( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 )
+ p_ctx->hpd &= 0xFB;
+ else
+ p_ctx->hpd = (p_ctx->hpd & 0xF9) | CH7036HPD_CRT_STATUS_CHANGED;
+ }
+
+ }
+
+ PD_DEBUG("ch7036_get_attached_device()- auto detection - exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
+ return SS_SUCCESS;
+}
+
+
+void ch7036_reset(ch7036_device_context_t* p_ctx)
+{
+ DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+
+ ch7036_reset_mcu(p_ch_ctx);
+ ch7036_reset_datapath(p_ch_ctx);
+
+ return;
+}
+
+void ch7036_reset_datapath(DEV_CONTEXT* p_ch_ctx)
+{
+
+ PD_DEBUG("ch7036: ch7036_reset_datapath()-enter\n");
+ I2CWrite(p_ch_ctx,0x03, 0x04);
+ I2CWrite(p_ch_ctx,0x52, 0x2E);
+
+ pd_usleep(50);
+ I2CWrite(p_ch_ctx,0x52, 0x2F);
+
+ return;
+}
+
+void ch7036_reset_mcu(DEV_CONTEXT* p_ch_ctx)
+{
+
+ PD_DEBUG("ch7036: ch7036_reset_mcu()-enter\n");
+
+ I2CWrite(p_ch_ctx,0x03, 0x04);
+ I2CWrite(p_ch_ctx,0x52, 0x2B);
+
+ pd_usleep(50);
+ I2CWrite(p_ch_ctx,0x52, 0x2F);
+
+
+ PD_DEBUG("ch7036: ch7036_reset_mcu()-exit-\n");
+ return;
+}
+
+
+
+
+
+void ch7036_set_input_timing_info(ch7036_device_context_t *p_ctx, INPUT_INFO* pInput_Info)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+
+ pd_timing_t * p_current_mode = &(p_ctx->native_dtd);
+ uint8 audio_id = AUDIO_SPDIF;
+ PD_DEBUG("ch7036_intf: ch7036_set_input_timing_info()-\n");
+
+
+ if (p_ctx->init_done) {
+
+
+ pInput_Info->timing.ht = p_current_mode->htotal+1;
+
+ pInput_Info->timing.ha = p_current_mode->width;
+ pInput_Info->timing.ho = p_current_mode->hsync_start - p_current_mode->hblank_start;
+ pInput_Info->timing.hw = p_current_mode->hsync_end - p_current_mode->hsync_start;
+ pInput_Info->timing.vt = p_current_mode->vtotal+1;
+
+ pInput_Info->timing.va = p_current_mode->height;
+ pInput_Info->timing.vo = p_current_mode->vsync_start - p_current_mode->vblank_start;
+ pInput_Info->timing.vw = p_current_mode->vsync_end - p_current_mode->vsync_start;
+
+
+ pInput_Info->rx_clk_khz = p_current_mode->dclk;
+
+
+ pInput_Info->hs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_HSYNC_HIGH) >> 24 ))?1:0;
+ pInput_Info->vs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_VSYNC_HIGH) >> 24))?1:0;
+
+ }
+
+
+
+
+
+ pInput_Info->pixel_fmt = ((lvds_context_t *)p_ctx->internal_lvds)->panel_depth == 18?PIXEL_FMT_18BIT:3;
+
+
+ pInput_Info->data_ch_pol = POL_NO_INV;
+
+
+ pInput_Info->data_ch_invert = POL_NO_INV;
+
+
+
+
+
+ pInput_Info->de_pol = POL_HIGH;
+
+
+
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ ch7036_set_audio_type(pInput_Info, audio_id);
+
+}
+
+void ch7036_set_output_timing_info(ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info)
+{
+
+
+ PD_DEBUG("ch7036: ch7036_set_output_timing_info()\n");
+
+
+ PD_DEBUG("ch7036_set_output_timing_info()- output channel from pd context[%u]\n",pOutput_Info->channel);
+
+
+ pOutput_Info->lvds_fmt.channel_swap = LVDS_CHANNEL_SWAP_DEF;
+ pOutput_Info->lvds_fmt.channel_pol = (POL_LOW << 4) | (POL_LOW << 3) | (POL_LOW << 2) | (POL_LOW << 1) | (POL_LOW << 0);
+ pOutput_Info->lvds_fmt.pixel_fmt = p_ctx->dither_select;
+
+
+
+ pOutput_Info->hdmi_fmt.channel_swap = 0;
+ pOutput_Info->hdmi_fmt.data_pol_invert = POL_NO_INV;
+ pOutput_Info->hdmi_fmt.protect_enable = 0;
+
+
+
+
+ if (pOutput_Info->channel & CHANNEL_HDMI)
+ {
+
+ if(!(pOutput_Info->hdmi_fmt.is_dvi_mode))
+ {
+ PD_DEBUG("ch7036_set_output_timing_info- hdmi mode index is [0x%x]\n",p_ctx->hdmi_mode_index);
+ pOutput_Info->hdmi_fmt.format_index = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].fmt_index;
+ pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].aspect;
+
+ pOutput_Info->timing.ht = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ht;
+ pOutput_Info->timing.ha = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ha;
+ pOutput_Info->timing.ho = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ho;
+ pOutput_Info->timing.hw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.hw;
+ pOutput_Info->timing.vt = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vt;
+ pOutput_Info->timing.va = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.va;
+ pOutput_Info->timing.vo = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vo;
+ pOutput_Info->timing.vw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vw;
+ pOutput_Info->uclk_khz = hdmi_timing_table[p_ctx->hdmi_mode_index].clk_freq;
+ }
+ else
+ {
+ pOutput_Info->hdmi_fmt.format_index = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].fmt_index;
+ pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].aspect;
+
+ pOutput_Info->timing.ht = dvi_timing_table[p_ctx->dvi_mode_index].timing.ht;
+ pOutput_Info->timing.ha = dvi_timing_table[p_ctx->dvi_mode_index].timing.ha;
+ pOutput_Info->timing.ho = dvi_timing_table[p_ctx->dvi_mode_index].timing.ho;
+ pOutput_Info->timing.hw = dvi_timing_table[p_ctx->dvi_mode_index].timing.hw;
+ pOutput_Info->timing.vt = dvi_timing_table[p_ctx->dvi_mode_index].timing.vt;
+ pOutput_Info->timing.va = dvi_timing_table[p_ctx->dvi_mode_index].timing.va;
+ pOutput_Info->timing.vo = dvi_timing_table[p_ctx->dvi_mode_index].timing.vo;
+ pOutput_Info->timing.vw = dvi_timing_table[p_ctx->dvi_mode_index].timing.vw;
+ pOutput_Info->uclk_khz = dvi_timing_table[p_ctx->dvi_mode_index].clk_freq;
+
+ }
+
+
+
+ } else if((pOutput_Info->channel & CHANNEL_VGA) && ((pOutput_Info->channel & CHANNEL_HDMI)==0x00) )
+ {
+
+
+
+ PD_DEBUG("ch7036_set_output_timing_info- crt mode index is [0x%x]\n",p_ctx->crt_mode_index);
+ pOutput_Info->timing.ht = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ht;
+ pOutput_Info->timing.ha = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ha;
+ pOutput_Info->timing.ho = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ho;
+ pOutput_Info->timing.hw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.hw;
+ pOutput_Info->timing.vt = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vt;
+ pOutput_Info->timing.va = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.va;
+ pOutput_Info->timing.vo = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vo;
+ pOutput_Info->timing.vw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vw;
+ pOutput_Info->uclk_khz = ch7036_crt_timing_table[p_ctx->crt_mode_index].clk_freq;
+
+
+ } else
+ ;
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ ch7036_set_hdmi_sync_polarity(pOutput_Info);
+
+ if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA) {
+
+ ch7036_set_rotate (pOutput_Info);
+ ch7036_set_hflip (pOutput_Info);
+ ch7036_set_vflip (pOutput_Info);
+ }
+}
+
+void ch7036_set_prefer_timing_info(ch7036_device_context_t *p_ctx, PREFER_INFO* pPrefer_Info)
+{
+
+
+
+
+ PD_DEBUG("ch7036_intf: ch7036_set_prefer_timing_info()\n");
+
+
+ if (!p_ctx->init_done) {
+
+ pPrefer_Info->mclk_khz = 166000;
+ pPrefer_Info->uclkod_sel = 1;
+ pPrefer_Info->dat16_32b = 0;
+ pPrefer_Info->true24 = 0;
+ pPrefer_Info->true_com = 0;
+ pPrefer_Info->lvds_out_hs_tolerance = HS_TOLERANCE_LEVEL0;
+ pPrefer_Info->lvds_out_reset_bit_sel = RST_BIT_VSYNC;
+ pPrefer_Info->dither_filter_enable = DITHER_ENABLE;
+
+ pPrefer_Info->hscale_ratio_gate = 130;
+ pPrefer_Info->reset=0;
+ pPrefer_Info->vga_enable=0;
+
+ pPrefer_Info->text_enhancement = DEFAULT_TEXT_ENHANCE;
+ pPrefer_Info->pll_ref_dly = DEF_PLL_REF_DLY;
+ pPrefer_Info->pll_ref_fbdly = DEF_PLL_REF_FBDLY;
+ pPrefer_Info->lvds_txdrv_ctrl = DEF_LVDS_TXDRV_CTRL;
+
+ pPrefer_Info->eye_bgtrim=0;
+ pPrefer_Info->eye_dacg=0;
+ pPrefer_Info->eye_dri_demp=0;
+ pPrefer_Info->eye_dri_pll_cp=0;
+ pPrefer_Info->eye_dri_damp=0;
+ pPrefer_Info->eye_dri_pll_rlf=0;
+ pPrefer_Info->eye_rdac=0;
+
+ }
+
+ pPrefer_Info->scale_line_adjust = 0;
+
+
+
+}
+
+
+ch7036_status_t ch7036_parse_standard_edid(ch7036_device_context_t* p_ctx, uint32 channel)
+{
+ uint8 i, index = 0;
+
+ ch7036_edid_blk_t* p_edid = (ch7036_edid_blk_t *)p_ctx->cedid;
+ unsigned char* p_edidblk = p_edid->edidblk;
+
+
+ OUT_FMT* p_table = ch7036_crt_timing_table;
+ TIMING* p_timing;
+
+ unsigned char j=0;
+
+
+
+
+
+ established_timings_t *p_etiming_I = p_edid->etiming_I;
+ established_timings_t *p_etiming_II = p_edid->etiming_II;
+
+
+
+ standard_timings_t *stiming = p_edid->stiming;
+ ch7036_attr_table_index_t* p_modes = p_edid->modes;
+
+ unsigned long idx = 2;
+
+
+ PD_DEBUG("ch7036_parse_stardard_edid() channel [0x%x] - enter...\n", channel);
+
+
+ if(channel == CHANNEL_LVDS_HDMI) {
+
+ p_edid = (ch7036_edid_blk_t *)p_ctx->hedid;
+ p_edidblk = p_edid->edidblk;
+ p_etiming_I = p_edid->etiming_I;
+ p_etiming_II = p_edid->etiming_II;
+
+ stiming = p_edid->stiming;
+ p_modes = p_edid->modes;
+
+
+ if (p_edid->ebn > 1) {
+ idx = 1;
+ p_table = hdmi_timing_table;
+ }
+ else {
+ idx = 0;
+ p_table = dvi_timing_table;
+ channel = 7;
+ }
+
+
+ }
+
+
+ while (index < MAX_ATTR_LIST_SIZE)
+ p_modes[index++] = FALSE;
+
+
+ if (p_edidblk[EDID_EXTENSION_FLAG] == 0x00 ) {
+
+
+ ch7036_parse_standard_timing(p_edid,0);
+
+
+ ch7036_parse_established_timing(p_ctx, p_edid);
+
+
+
+ ch7036_parse_detailed_descriptor_blocks(p_ctx, p_edid);
+
+
+
+ for(i=0; i<8;i++) {
+
+
+ index=0;
+ while (index < MAX_ATTR_LIST_SIZE ) {
+ if(p_modes[index]== TRUE) {
+ index++;
+ continue;
+ }
+ p_timing = &(p_table[index].timing);
+
+ if ( (p_edid->dtblk[j]).data_tag & 0x00FFFFFF ) {
+ OUT_FMT* p_dtd = &((p_edid->dtblk[j]).dtiming);
+
+ if( (p_dtd->timing.ha == p_timing->ha) && (p_dtd->timing.va == p_timing->va) && (p_dtd->timing.hz >= p_timing->hz) ) {
+ p_modes[index] = TRUE;
+ j= j> 3?3:j+1;
+
+ PD_DEBUG("ch7036_parse_standard_edid()- detailed timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
+
+ }
+
+ }
+
+
+ if( (stiming[i].ha == p_timing->ha) && (stiming[i].va == p_timing->va) && (stiming[i].refresh_rate >= p_timing->hz) ) {
+ p_modes[index] = TRUE;
+ PD_DEBUG("ch7036_parse_standard_edid()- std_timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
+ }
+
+ index++;
+
+ }
+
+ }
+
+
+ for(i=0;i<4;i++) {
+ if ( (p_edid->dtblk[i]).data_tag == 0xFA000000) {
+ ;
+ continue;
+ }
+ }
+
+
+
+ for(i=0; i<8;i++) {
+
+
+
+ if( (p_etiming_I[i].is_supported == TRUE) && (p_etiming_I[i].index[idx] != OUT_CRT_END) ) {
+ p_modes[p_etiming_I[i].index[idx]] = TRUE;
+ PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
+ continue;
+
+ }
+
+
+ if( (i==7) && (channel ==7) && (p_etiming_I[i].is_supported == TRUE) ) {
+ p_modes[p_etiming_I[i].index[idx]] = TRUE;
+ PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
+ }
+
+
+ }
+
+ for(i=0; i<8;i++) {
+
+ if( (p_etiming_II[i].is_supported == TRUE) && (p_etiming_II[i].index[idx] != OUT_CRT_END) ) {
+ p_modes[p_etiming_II[i].index[idx]] = TRUE;
+ PD_DEBUG("ch7036_parse_standard_edid()- et2 mode supported- index [%d] name [%s]...\n",p_etiming_II[i].index[idx],p_etiming_II[i].mode_name);
+ continue;
+
+ }
+
+ }
+
+
+
+ }
+ else {
+ PD_DEBUG("ch7036_parse_standard_edid()- vga/dvi has more than one 128 byte block\n");
+ }
+
+
+ PD_DEBUG("ch7036_parse_stardard_edid()-channel [0x%x] - exit...\n", channel);
+
+ return SS_SUCCESS;
+
+}
+
+void ch7036_parse_detailed_descriptor_blocks(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid)
+{
+ unsigned long *monitor_descriptor;
+ unsigned char* p_ebuf, *p_st;
+ unsigned char* p_edidblk = p_edid->edidblk;
+ unsigned char i;
+ OUT_FMT* p_dt;
+
+
+ p_ebuf = &(p_edidblk[EDID_DETAILED_TIMING_DESCRIPTION_1]);
+
+ PD_DEBUG("parse_detailed_descriptor_blocks()- enter...\n");
+
+ for(i=0;i<4;i++) {
+
+ monitor_descriptor = (unsigned long *) p_ebuf;
+
+ if((*monitor_descriptor) & 0x00FFFFFF ) {
+
+
+ p_dt = &(p_edid->dtblk[i].dtiming);
+ ch7036_parse_detailed_timing(p_dt, p_ebuf);
+
+ }
+
+ else {
+
+ p_st = p_ebuf;
+ p_st +=5;
+
+ switch (*monitor_descriptor) {
+ case 0xFA000000:
+ ch7036_parse_standard_timing(p_edid,p_st);
+ break;
+
+ case 0xFD000000:
+ (p_edid->rtiming).vrate_min = *p_st;
+ (p_edid->rtiming).vrate_max = *(p_st+1);
+ (p_edid->rtiming).hrate_min = *(p_st+2);
+ (p_edid->rtiming).hrate_max = *(p_st+3);
+ (p_edid->rtiming).pclk_max = (unsigned long)(*(p_st+4))*10000L;
+
+
+ break;
+
+ case 0xFC000000:
+ case 0xFF000000:
+ default:
+ break;
+ }
+ }
+
+ (p_edid->dtblk[i]).data_tag = *monitor_descriptor;
+
+ p_ebuf += 18;
+ }
+
+ return;
+}
+
+void ch7036_parse_detailed_timing(OUT_FMT *p_dt, unsigned char* p_ebuf)
+{
+
+ unsigned short blanking;
+
+ PD_DEBUG("ch7036_parse_detailed_descriptor_timing()- enter...\n");
+
+
+ p_dt->clk_freq = ((uint32)(p_ebuf[1]<<8) | p_ebuf[0]) * 10;
+
+ p_dt->timing.ha = ((uint16)(p_ebuf[4] & 0xF0) << 4) | p_ebuf[2];
+
+ PD_DEBUG("ch7036_parse_detailed_timing() byte 3 [%x] byte 5 [%x]\n",p_ebuf[2],p_ebuf[4]);
+
+ blanking = ((uint16)(p_ebuf[4] & 0x0F) << 8) | p_ebuf[3];
+ p_dt->timing.ht = p_dt->timing.ha + blanking;
+
+ p_dt->timing.va = ((uint16)(p_ebuf[7] & 0xF0) << 4) | p_ebuf[5];
+
+ PD_DEBUG("ch7036_parse_detailed_timing() byte 6 [%x] byte 8 [%x]\n",p_ebuf[5],p_ebuf[7]);
+
+ blanking = ((uint16)(p_ebuf[7] & 0x0F) << 8) | p_ebuf[6];
+ p_dt->timing.vt = p_dt->timing.va + blanking;
+
+ PD_DEBUG("ch7036_parse_detailed_timing()- pclk [%d] Khz ha [%d] va [%d] ht [%d] vt [%d]\n",p_dt->clk_freq,p_dt->timing.ha,p_dt->timing.va,p_dt->timing.ht,p_dt->timing.vt);
+
+ p_dt->timing.hz = (((p_dt->clk_freq / p_dt->timing.ht) + 1 ) * 1000) / p_dt->timing.vt;
+
+ p_dt->timing.stype = (p_ebuf[17] & 0x80)?0:1;
+
+ PD_DEBUG("ch7036_parse_detailed_timing()- refresh [%d] scantype [%d]\n",
+ p_dt->timing.hz,p_dt->timing.stype);
+
+ return;
+}
+
+
+
+void ch7036_parse_standard_timing(ch7036_edid_blk_t* p_edid, unsigned char* p_addtional_st)
+{
+ standard_timings_t *stiming = p_edid->stiming;
+ unsigned char i, max=8;
+
+ unsigned char* p_edidblk = &(p_edid->edidblk[EDID_STANDARD_TIMINGS]);
+
+
+ PD_DEBUG("ch7036_parse_standard_timing()- enter\n");
+
+ if(p_addtional_st) {
+ p_edidblk = p_addtional_st;
+ stiming = p_edid->stiming_x;
+ max = 6;
+ }
+
+ for(i = 0; i < max; stiming++,i++) {
+
+
+ if( (*p_edidblk) == 0x01 && *(p_edidblk+1) == 0x01)
+ continue;
+
+ stiming->ha = ((*p_edidblk) + 31) << 3 ;
+
+ stiming->refresh_rate = (*(p_edidblk + 1) & 0x3F) + 60;
+
+ switch(*(p_edidblk +1) >> 6) {
+
+ case 0:
+ stiming->va = (stiming->ha *10) >> 4;
+ break;
+ case 1:
+ stiming->va = (stiming->ha *3) >> 2;
+ break;
+ case 2:
+ stiming->va = (stiming->ha << 2) / 5;
+ break;
+ case 3:
+ stiming->va = (stiming->ha* 9) >>4;
+ break;
+ default:
+ break;
+ }
+
+ p_edidblk +=2;
+
+ PD_DEBUG("ch7036_parse_standard_timing()- ha [%d] va [%d] refresh [%d]\n",stiming->ha,stiming->va,stiming->refresh_rate);
+
+ }
+
+ return;
+}
+
+
+
+
+void ch7036_parse_established_timing(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid)
+{
+
+ unsigned char* p_edidblk = p_edid->edidblk;
+
+
+
+ established_timings_t *p_etiming_I = p_edid->etiming_I;
+ established_timings_t *p_etiming_II = p_edid->etiming_II;
+ established_timings_t *p_etiming_man = p_edid->etiming_man;
+
+ unsigned char i=0;
+ unsigned char et1, et2;
+
+ PD_DEBUG("ch7036_parse_established_timing()- enter...\n");
+
+ et1 = p_edidblk[EDID_ESTABLISHED_TIMINGS_1];
+ et2 = p_edidblk[EDID_ESTABLISHED_TIMINGS_2];
+
+
+
+ for(i=0; i<8;i++) {
+ p_etiming_I[i].is_supported = FALSE;
+ p_etiming_II[i].is_supported = FALSE;
+ }
+
+
+
+ p_etiming_man->is_supported = FALSE;
+
+
+ for(i=0;i<8;i++) {
+
+
+
+ if(et1 & 0x01) {
+ p_etiming_I[i].is_supported = TRUE;
+
+ }
+
+
+ if(et2 & 0x01) {
+ p_etiming_II[i].is_supported = TRUE;
+
+ }
+
+ et1 >>= 1;
+ et2 >>= 1;
+
+ }
+
+
+
+ if (p_edidblk[EDID_MANUFACTURERS_RESERVED_TIMINGS] & 0x80) {
+
+ p_etiming_man->is_supported = TRUE;
+
+ }
+
+
+ return;
+
+}
+
+
+ch7036_status_t ch7036_parse_cea_edid(ch7036_device_context_t* p_ctx)
+{
+ uint8 tag, blk_size =0;
+ uint8 index = 0;
+
+ uint16 count;
+
+ uint8* p_buff;
+
+
+ ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+ unsigned char* p_edidblk = p_hedid->edidblk;
+ ch7036_attr_table_index_t* p_modes = p_hedid->modes;
+
+
+ PD_DEBUG("ch7036_parse_cea_edid()- enter...\n");
+
+ while (index < MAX_ATTR_LIST_SIZE )
+ p_modes[index++] = FALSE;
+
+
+ if(p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] == 0 || p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] > 124) {
+ PD_DEBUG("ch7036_parse_cea_edid()- invalid data block size [%d]\n", p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]);
+ return SS_UNSUCCESSFUL;
+ }
+
+
+
+ PD_DEBUG("ch7036_parse_cea_edid()- CEA revision [0x%x]...\n",p_edidblk[EDID_CEA_REVISION]);
+
+ if(p_edidblk[EDID_CEA_TAG] == 0x02 && p_edidblk[EDID_CEA_REVISION] == 0x03)
+ {
+
+ p_buff = &(p_edidblk[EDID_CEA_DATA_BLOCK]);
+
+
+
+ count=4 ;
+ for(; count < p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]; p_buff += blk_size) {
+
+ blk_size = (*p_buff) & 0x1F;
+ tag = (*p_buff) & 0xE0;
+
+ PD_DEBUG("ch7036_parse_cea_edid()- data type [0x%x] block_size [%d]\n", tag, blk_size);
+
+ p_buff++;
+ switch (tag) {
+
+ case 0x20:
+
+ break;
+
+ case 0x40:
+ ch7036_parse_cea_video_data_block(blk_size, p_buff, p_hedid);
+ break;
+
+ case 0x60:
+ break;
+
+ case 0x80:
+ break;
+
+ default:
+ break;
+
+ }
+
+ count += (blk_size + 1);
+
+
+ }
+
+ }
+
+
+ PD_DEBUG("ch7036_parse_cea_edid()- exit...\n");
+
+ return SS_SUCCESS;
+
+
+}
+
+
+void ch7036_parse_cea_video_data_block(uint8 blk_size, uint8* p_buff, ch7036_edid_blk_t* p_edid)
+{
+ uint8 i, index;
+
+ ch7036_attr_table_index_t* p_modes = p_edid->modes;
+
+ for(i=1; i <= blk_size; i++, p_buff++ ) {
+
+ index=0;
+
+ PD_DEBUG("ch7036_parse_cea_video_data_block()- HDMI display video code [0x%x]\n",(*p_buff) & 0x7F);
+
+ while (index < OUT_HDMI_END) {
+
+
+ if( p_modes[index] == TRUE ) {
+ index++;
+ continue;
+ }
+
+
+ if( ((*p_buff) & 0x7F) == hdmi_timing_table[index].fmt_index ) {
+
+ p_modes[index] = TRUE;
+ PD_DEBUG("ch7036_parse_cea_video_data_block()- mode supported: global table index [%d] name [%s]...\n",index, ch7036_get_mode_name(CHANNEL_LVDS_HDMI,index) );
+
+ if( hdmi_timing_table[index-1].fmt_index == hdmi_timing_table[index].fmt_index) {
+
+ break;
+ }
+
+ }
+
+ index++;
+
+ }
+ }
+
+ return;
+}
+
+
+ch7036_status_t ch7036_parse_edid(ch7036_device_context_t* p_ctx)
+{
+
+
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+
+ ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+ ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+ unsigned char* p_edidblk=0;
+ ch7036_attr_table_index_t* p_modes = 0;
+ pd_attr_t *p_attr = NULL ;
+ int RESET =1;
+
+ PD_DEBUG("ch7036_parse_edid()- enter...\n");
+
+
+ //hpd checking schemes
+ if(p_ctx->hpd == 0)
+ return SS_SUCCESS;
+
+
+ if (
+ ( (pOutput_Info->channel & 0x02) && (p_ctx->hpd & 0x80) )||
+ ( (pOutput_Info->channel & 0x04) && (p_ctx->hpd & 0x08) )
+ )
+ //parsing is already done
+ return SS_SUCCESS;
+
+
+ switch (pOutput_Info->channel) {
+ case CHANNEL_LVDS_HDMI:
+ case CHANNEL_HDMI:
+ if(p_hedid->is_edid) {
+ p_edidblk = p_hedid->edidblk;
+
+ p_hedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
+
+
+ if(pOutput_Info->hdmi_fmt.is_dvi_mode == 0) {
+ p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+ ch7036_parse_cea_edid(p_ctx);
+ }
+ else {
+ p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_DVI_OUT_MODE, 0);
+ ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_HDMI);
+ }
+
+
+
+ p_ctx->hpd |= 0x80; //don't parse again next time
+
+ }
+ else {
+
+ PD_DEBUG("ch7036_parse_edid()- hdmi edid read failed or never done...use default...\n");
+ ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_hedid->modes,RESET);
+ p_ctx->hpd &= 0x7F; //allow to enter parsing block again
+
+ }
+
+ p_modes = p_hedid->modes;
+
+ break;
+
+ case CHANNEL_LVDS_VGA:
+ case CHANNEL_VGA:
+ if(p_cedid->is_edid) {
+ p_edidblk = p_cedid->edidblk;
+
+ p_cedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
+ p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_CRT_OUT_MODE, 0);
+
+ ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_VGA);
+ p_ctx->hpd |= 0x08;
+ }
+ else {
+ PD_DEBUG("ch7036_parse_edid()- vga edid read failed or never done...use default...\n");
+ ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_cedid->modes,RESET);
+ p_ctx->hpd &= 0x7F; //allow to enter parsing block again
+ }
+ p_modes = p_cedid->modes;
+
+ break;
+ default:
+ //there is no separate DVI display channel, or LVDS edid reading at this time
+ //DVI display option should already be mapped to HDMI channel
+ p_edidblk = 0;
+
+ }
+
+ if(p_edidblk) {
+
+ ch7036_set_edid_display_supported_attr( (void *)p_attr,0,p_ctx->downscaled,p_modes,0);
+
+ }
+
+ PD_DEBUG("ch7036_parse_edid()- exit...\n");
+
+ return SS_SUCCESS;
+}
+
+
+void ch7036_alter_display_table(int all, void *p_table,unsigned char* p_modes, void* val,unsigned long* p_invis,unsigned char is_invis,unsigned char is_6x4)
+{
+ pd_attr_t *p_attr;
+ unsigned long i,j;
+
+
+ PD_DEBUG("ch7036_alter_display_table()-enter...\n");
+
+ if(all) {
+ unsigned long* num_attrs = (unsigned long *)val;
+ for(i=0;i<3;i++) { //all 3 tables: hdmi, dvi, vga
+
+ p_attr = pd_get_attr((pd_attr_t *)p_table, *num_attrs, PD_ATTR_ID_HDMI_OUT_MODE+i, 0);
+ if(is_6x4)
+ p_attr++;
+ else
+ p_attr= p_attr + ch7036_invis_6x4_modes_table_size[i] + 1; //1 is to skip header
+
+
+ for(j=0; j < *p_invis;j++) {
+ if(is_invis)
+ p_attr->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ else
+ p_attr->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+ p_attr++;
+ }
+ p_invis++; //now, grab dvi, then vga table size
+
+
+ }
+
+ }
+ else {
+ unsigned long id= 0,k;
+ p_attr = (pd_attr_t *)p_table;
+ id = p_attr->id;
+
+ if(is_6x4) {
+ p_attr++;
+ j=0;
+ }
+ else {
+ p_attr= p_attr + ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE] + 1; //point to the first 7x4 entry
+ j= ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE];
+ }
+ p_invis = p_invis + (id - PD_ATTR_ID_HDMI_OUT_MODE);
+ k= *p_invis + j;
+
+ for(; j < k;j++) {
+ if(is_invis) {
+ p_attr->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_modes[j]=FALSE;
+ }
+
+ p_attr++;
+ }
+
+ }
+}
+
+
+ch7036_status_t ch7036_set_edid_display_supported_attr(void *p_table, unsigned long num_attrs, unsigned char* p_downscaled, unsigned char* p_modes, int is_reset)
+{
+
+ pd_list_attr_t *p_hdr = (pd_list_attr_t *)p_table;
+ pd_attr_t *p_entry = (pd_attr_t *)p_table;
+
+ uint8 i=0;
+
+#ifdef T_SHOW_EDID_DISPLAY_ATTR
+ pd_list_entry_attr_t *list_entry;
+#endif
+
+ PD_DEBUG("ch7036_set_edid_display_supported_attr()-enter... is_reset status = [%d]\n", is_reset);
+
+ if(is_reset) {
+ while (i < MAX_ATTR_LIST_SIZE ) {
+ p_modes[i++] = TRUE;
+ }
+
+
+
+ //special handling for 1080i/p @ 59Hz
+ p_entry = pd_get_attr((pd_attr_t *)p_table, num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+ p_entry++;
+ p_entry = p_entry + OUT_HDMI_1920x1080I_59;
+ p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ p_entry += 2;
+ p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+ }
+ else {
+
+ PD_DEBUG("ch7036_set_edid_display_supported_attr()-start to build edid display mode list...\n");
+
+ p_entry++;
+
+ for (i = 0; i < p_hdr->num_entries ; ++i,++p_entry) {
+ if(
+ (p_modes[i] == FALSE) ||
+ //1080 i/p @ 59 Hz
+ ((p_hdr->id == PD_ATTR_ID_HDMI_OUT_MODE) && (i == OUT_HDMI_1920x1080I_59 || i== OUT_HDMI_1920x1080P_59) ) ){
+
+ p_entry->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+ continue;
+ }
+
+
+ p_entry->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+ }
+
+
+ }
+
+ //special handling for 8x6,7x4,6x4-
+ ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_6x4_modes_table_size,*p_downscaled,1);
+ p_downscaled++;
+ ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_8x6_7x4_table_size,*p_downscaled,0);
+
+#ifdef T_SHOW_EDID_DISPLAY_ATTR
+
+ list_entry = (pd_list_entry_attr_t *)(p_table);
+
+ for (i = 0,++list_entry; i < p_hdr->num_entries; ++i, ++list_entry)
+ PD_DEBUG("ch7036 : ch7036_set_edid_display_supported_attr : \n"
+ "list entry[%hhu]=%s, id=%lu, "
+ "value=%lu, flags=0x%x \n",
+ i, list_entry->name, list_entry->id,
+ list_entry->value, (unsigned char)list_entry->flags);
+#endif
+
+
+ return SS_SUCCESS;
+}
+
+
+uint8 * ch7036_get_mode_name(uint32 channel, uint8 index)
+{
+ uint8* str = "Name String Is Not Yet Converted";
+
+ switch (channel) {
+
+ case CHANNEL_LVDS_HDMI:
+ switch (index) {
+ case OUT_HDMI_640x480P_59:
+ return ("OUT_HDMI_640x480P_59");
+ case OUT_HDMI_640x480P_60:
+ return ("OUT_HDMI_640x480P_60");
+ case OUT_HDMI_720x480P_59:
+ return ("OUT_HDMI_720x480P_59");
+ case OUT_HDMI_720x480P_60:
+ return ("OUT_HDMI_720x480P_60");
+ case OUT_HDMI_1280x720P_59:
+ return ("OUT_HDMI_1280x720P_59");
+ case OUT_HDMI_1280x720P_60:
+ return ("OUT_HDMI_1280x720P_60");
+ case OUT_HDMI_1920x1080I_59:
+ return ("OUT_HDMI_1920x1080I_59");
+ case OUT_HDMI_1920x1080I_60:
+ return ("OUT_HDMI_1920x1080I_60");
+ case OUT_HDMI_1920x1080P_59:
+ return ("OUT_HDMI_1920x1080P_59");
+ case OUT_HDMI_1920x1080P_60:
+ return ("OUT_HDMI_1920x1080P_60");
+
+
+ }
+ break;
+
+ case CHANNEL_LVDS_VGA:
+
+ switch (index) {
+
+ case OUT_CRT_640x400_85:
+ return ("OUT_CRT_640x400_85");
+
+ case OUT_CRT_640x480_60:
+ return ("OUT_CRT_640x480_60");
+ case OUT_CRT_640x480_72:
+ return ("OUT_CRT_640x480_72");
+ case OUT_CRT_640x480_75:
+ return ("OUT_CRT_640x480_75");
+ case OUT_CRT_640x480_85:
+ return ("OUT_CRT_640x480_85");
+
+ case OUT_CRT_720x400_85:
+ return ("OUT_CRT_720x400_85");
+
+ case OUT_CRT_800x600_56:
+ return ("OUT_CRT_800x600_56");
+ case OUT_CRT_800x600_60:
+ return ("OUT_CRT_800x600_60");
+ case OUT_CRT_800x600_72:
+ return ("OUT_CRT_800x600_72");
+ case OUT_CRT_800x600_75:
+ return ("OUT_CRT_800x600_75");
+
+ case OUT_CRT_800x600_85:
+ return ("OUT_CRT_800x600_85");
+
+ case OUT_CRT_1024x768_60:
+ return ("OUT_CRT_1024x768_60");
+ case OUT_CRT_1024x768_70:
+ return ("OUT_CRT_1024x768_70");
+ case OUT_CRT_1024x768_75:
+ return ("OUT_CRT_1024x768_75");
+ case OUT_CRT_1024x768_85:
+ return ("OUT_CRT_1024x768_85");
+
+ case OUT_CRT_1152x864_75:
+ return ("OUT_CRT_1152x864_75");
+
+ case OUT_CRT_1280x768_60:
+ return ("OUT_CRT_1280x768_60");
+ case OUT_CRT_1280x768_75:
+ return ("OUT_CRT_1280x768_75");
+ case OUT_CRT_1280x768_85:
+ return ("OUT_CRT_1280x768_85");
+
+ case OUT_CRT_1280x960_60:
+ return ("OUT_CRT_1280x960_60");
+ case OUT_CRT_1280x960_85:
+ return ("OUT_CRT_1280x960_85");
+
+ case OUT_CRT_1280x1024_60:
+ return ("OUT_CRT_1280x1024_60");
+ case OUT_CRT_1280x1024_75:
+ return ("OUT_CRT_1280x1024_75");
+ case OUT_CRT_1280x1024_85:
+ return ("OUT_CRT_1280x1024_85");
+
+ case OUT_CRT_1360x768_60:
+ return ("OUT_CRT_1360x768_60");
+
+ case OUT_CRT_1400x1050_60:
+ return ("OUT_CRT_1400x1050_60");
+ case OUT_CRT_1400x1050_75:
+ return ("OUT_CRT_1400x1050_75");
+
+ case OUT_CRT_1440x900_60:
+ return ("OUT_CRT_1440x900_60");
+
+ case OUT_CRT_1440x1050_60:
+ return ("OUT_CRT_1440x1050_60");
+
+ case OUT_CRT_1600x900_60:
+ return ("OUT_CRT_1600x900_60");
+
+ case OUT_CRT_1600x1200_60:
+ return ("OUT_CRT_1600x1200_60");
+
+ case OUT_CRT_1920x1080_60:
+ return ("OUT_CRT_1920x1080_60");
+
+ }
+ break;
+
+ default:
+ switch (index) {
+ case OUT_DVI_640x480_60:
+ return ("OUT_DVI_640x480_60");
+ case OUT_DVI_640x480_72:
+ return ("OUT_DVI_640x480_72");
+
+ case OUT_DVI_720x400_70:
+ return ("OUT_DVI_720x400_70");
+
+ case OUT_DVI_800x600_56:
+ return ("OUT_DVI_800x600_56");
+ case OUT_DVI_800x600_60:
+ return ("OUT_DVI_800x600_60");
+ case OUT_DVI_800x600_72:
+ return ("OUT_DVI_800x600_72");
+ case OUT_DVI_800x600_75:
+ return ("OUT_DVI_800x600_75");
+
+ case OUT_DVI_1024x768_60:
+ return ("OUT_DVI_1024x768_60");
+ case OUT_DVI_1024x768_70:
+ return ("OUT_DVI_1024x768_70");
+ case OUT_DVI_1024x768_75:
+ return ("OUT_DVI_1024x768_75");
+
+ case OUT_DVI_1152x864_60:
+ return ("OUT_CRT_1152x864_60");
+
+ case OUT_DVI_1280x720_60:
+ return ("OUT_DVI_1280x720_60");
+
+ case OUT_DVI_1280x800_60:
+ return ("OUT_DVI_1280x800_60");
+
+ case OUT_DVI_1280x960_60:
+ return ("OUT_DVI_1280x960_60");
+
+ case OUT_DVI_1280x1024_60:
+ return ("OUT_DVI_1280x1024_60");
+ case OUT_DVI_1280x1024_75:
+ return ("OUT_DVI_1280x1024_75");
+
+ case OUT_DVI_1360x768_60:
+ return ("OUT_DVI_1360x768_60");
+
+ case OUT_DVI_1366x768_60:
+ return ("OUT_DVI_1366x768_60");
+
+ case OUT_DVI_1400x1050_60:
+ return ("OUT_DVI_1400x1050_60");
+ case OUT_DVI_1400x1050_75:
+ return ("OUT_DVI_1400x1050_75");
+
+ case OUT_DVI_1440x900_60:
+ return ("OUT_DVI_1440x900_60");
+
+ case OUT_DVI_1440x1050_60:
+ return ("OUT_DVI_1440x1050_60");
+
+ case OUT_DVI_1600x900_60:
+ return ("OUT_DVI_1600x900_60");
+
+ case OUT_DVI_1600x1200_60:
+ return ("OUT_DVI_1600x1200_60");
+
+ case OUT_DVI_1680x1050_60:
+ return ("OUT_DVI_1680x1050_60");
+
+ case OUT_DVI_1920x1080_60:
+ return ("OUT_DVI_1920x1080_60");
+ }
+ break;
+
+
+ }
+
+
+ return str;
+
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
new file mode 100644
index 0000000..d031396
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
@@ -0,0 +1,243 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_intf.h
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#ifndef _CH7036_INTF_H_
+#define _CH7036_INTF_H_
+
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+
+#include "ch7036_typedef.h"
+#include "ch7036_iic.h"
+#include "ch7036.h"
+
+#include "ch7036_fw.h"
+
+
+#include "config_.h"
+
+#ifdef T_LINUX
+#include "asm/div64.h"
+#endif
+
+
+#define internal_lvds_context_t lvds_context_t
+
+typedef unsigned char i2c_reg_t;
+
+
+
+#define DITHER_18_TO_18 0
+#define DITHER_18_TO_24 1
+#define DITHER_24_TO_18 2
+#define DITHER_24_TO_24 3
+
+
+#define DEFAULT_POSITION 2048
+#define DEFAULT_H_1080P_POSITION 2137
+#define HDMI_DEFAULT_UNDERSCAN 15
+#define CRT_DEFAULT_UNDERSCAN 18
+#define DEFAULT_ROTATE 0
+#define DEFAULT_HFLIP 0
+#define DEFAULT_VFLIP 0
+#define DEFAULT_TEXT_ENHANCE 7
+#define DEF_PLL_REF_DLY 0
+#define DEF_PLL_REF_FBDLY 1
+#define DEF_LVDS_TXDRV_CTRL 0
+#define DITHER_ENABLE 0
+#define DITHER_BYPASS 1
+#define MODE_6x4_BYPASS 0
+#define MODE_8x6_7x4_BYPASS 1
+
+
+typedef struct {
+ i2c_reg_t dev_D0 :1;
+ i2c_reg_t dev_D1 :1;
+ i2c_reg_t dev_D2 :1;
+ i2c_reg_t dev_D3 :1;
+ i2c_reg_t disp_D0:1;
+ i2c_reg_t disp_D1:1;
+ i2c_reg_t disp_D2:1;
+ i2c_reg_t disp_D3:1;
+} ch7036_power_states_t;
+
+
+
+typedef unsigned char ch7036_hpd_t;
+
+#define CH7036HPD_RESERVED1 0x01 //force port status inquiry bit
+#define CH7036HPD_CRT_ATTACHED 0x02
+#define CH7036HPD_CRT_STATUS_CHANGED 0x04
+#define CH7036HPD_CRT_EDID_PARSING_STATUS 0x08
+
+#define CH7036HPD_RESERVED2 0x10 //incorrect display choice bit
+#define CH7036HPD_HDVI_ATTACHED 0x20
+#define CH7036HPD_HDVI_STATUS_CHANGED 0x40
+#define CH7036HPD_HDVI_EDID_PARSING_STATUS 0x80
+
+
+typedef struct _ch7036_device_context {
+
+
+ void *internal_lvds;
+ DEV_CONTEXT *p_ch7xxx_context;
+ pd_callback_t *p_callback;
+
+
+ pd_attr_t *p_ch7036_attr_table;
+ pd_attr_t *p_lvds_attr_table;
+
+ unsigned long ch7036_num_attrs;
+ unsigned long lvds_num_attrs;
+
+
+ HDMI_OUT_MODE hdmi_mode_index;
+ DVI_OUT_MODE dvi_mode_index;
+ CRT_OUT_MODE crt_mode_index;
+
+
+ pd_timing_t *p_lvds_table;
+
+
+
+
+ pd_timing_t native_dtd;
+
+
+ unsigned short fp_width;
+ unsigned short fp_height;
+
+ unsigned char dither_select;
+
+
+ unsigned long pwr_state;
+
+ unsigned char init_done;
+
+
+
+
+ uint8 use_firmware;
+
+ ch7036_hpd_t hpd;
+ uint8 man_sel_out; //auto or manually select display output channel
+
+ uint32 prev_outchannel;
+
+ void* fw;
+ void* cedid;
+ void* hedid;
+ uint8 downscaled[2];
+ uint8 dwnscal_bypass; //1: remove 8x6,&7x4 when downscaling, 0: keep them
+
+ uint32 last_emsg;
+
+} ch7036_device_context_t;
+
+
+
+
+#if 0
+#define PD_INTERNAL_LVDS_MODULE_OPEN(name, params) lvds_open params
+#define PD_INTERNAL_LVDS_MODULE_POST_SET_MODE(name, params) lvds_post_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_MODE(name, params) lvds_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_POWER(name, params) lvds_set_power params
+#define PD_INTERNAL_LVDS_MODULE_INIT_DEVICE(name, params) lvds_init_device params
+#define PD_INTERNAL_LVDS_MODULE_CLOSE(name, params) lvds_close params
+#define PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(name, params) lvds_get_attrs params
+#define PD_INTERNAL_LVDS_MODULE_SET_ATTRIBUTES(name, params) lvds_set_attrs params
+#define PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(name, params) lvds_get_timing_list params
+
+#endif
+
+
+
+#define PD_INTERNAL_LVDS_MODULE_OPEN(name, params) internal_lvds_open params
+#define PD_INTERNAL_LVDS_MODULE_POST_SET_MODE(name, params) internal_lvds_post_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_MODE(name, params) internal_lvds_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_POWER(name, params) internal_lvds_set_power params
+#define PD_INTERNAL_LVDS_MODULE_GET_POWER(name, params) internal_lvds_get_power params
+#define PD_INTERNAL_LVDS_MODULE_INIT_DEVICE(name, params) internal_lvds_init_device params
+#define PD_INTERNAL_LVDS_MODULE_CLOSE(name, params) internal_lvds_close params
+#define PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(name, params) internal_lvds_get_attrs params
+#define PD_INTERNAL_LVDS_MODULE_SET_ATTRIBUTES(name, params) internal_lvds_set_attrs params
+#define PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(name, params) internal_lvds_get_timing_list params
+#define PD_INTERNAL_LVDS_MODULE_SAVE(name, params) internal_lvds_save params
+#define PD_INTERNAL_LVDS_MODULE_RESTORE(name, params) internal_lvds_restore params
+#define PD_INTERNAL_LVDS_MODULE_GET_PORT_STATUS(name, params) internal_lvds_get_port_status params
+
+
+
+
+ch7036_status_t ch7036_device_prepare(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_config(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_start(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_set_power(ch7036_device_context_t* p_ctx,unsigned long channel);
+
+
+void ch7036_set_input_timing_info(ch7036_device_context_t *p_ctx,INPUT_INFO* pInput_Info);
+void ch7036_set_output_timing_info (ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info);
+void ch7036_set_prefer_timing_info(ch7036_device_context_t *p_ctx,PREFER_INFO* pPrefer_Info);
+
+
+
+ch7036_status_t ch7036_load_firmware(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_get_attached_device(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_read_edid(ch7036_device_context_t* p_ctx, uint32 channel);
+ch7036_status_t ch7036_get_hdvi_display_modes_supported(ch7036_device_context_t* p_ctx);
+
+
+uint8 * ch7036_get_mode_name(uint32 channel, uint8 index);
+//void ch7036_reset_edid_supported_modes(unsigned char *p_modes);
+ch7036_status_t ch7036_parse_edid(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_parse_cea_edid(ch7036_device_context_t* p_ctx);
+void ch7036_parse_cea_video_data_block(uint8 blk_size, uint8* p_buff, ch7036_edid_blk_t* p_edid);
+ch7036_status_t ch7036_set_edid_display_supported_attr(void *p_table, unsigned long num_attrs, unsigned char* p_downscaled, unsigned char* p_modes,int is_reset);
+void ch7036_alter_display_table(int all, void *p_table,unsigned char* p_modes, void* val,unsigned long* p_invis,unsigned char is_invis,unsigned char is_6x4);
+
+ch7036_status_t ch7036_parse_standard_edid(ch7036_device_context_t* p_ctx, uint32 channel);
+
+void ch7036_parse_standard_timing(ch7036_edid_blk_t* p_edid, unsigned char* p_addtional_st);
+
+void ch7036_parse_established_timing(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid);
+void ch7036_parse_detailed_descriptor_blocks(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid);
+void ch7036_parse_detailed_timing(OUT_FMT *p_dt, unsigned char* p_ebuf);
+
+
+void ch7036_reset_mcu(DEV_CONTEXT* p_ch_ctx);
+void ch7036_reset_datapath(DEV_CONTEXT* p_ch_ctx);
+void ch7036_reset(ch7036_device_context_t* p_ctx);
+
+extern uint32 GetLastErrorMessage(void);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
new file mode 100755
index 0000000..1922bda
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
@@ -0,0 +1,494 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_pm.c
+* @version 1.2.4
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_intf.h"
+
+
+
+void ch7036_set_power_lvds(DEV_CONTEXT* pDevContext);
+void ch7036_set_power_hdmi(DEV_CONTEXT* pDevContext);
+void ch7036_set_power_crt(DEV_CONTEXT* pDevContext);
+
+void ch7036_set_power_lvds(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ uint8 reg=0x00;
+
+ PD_DEBUG("ch7036: ch7036_set_power_lvds()-enter...channel [%lu]\n", pOutput_Info->channel);
+ if(pOutput_Info->channel & CHANNEL_LVDS)
+ {
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x1A);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x1A, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg & 0xEF;
+ if(((pOutput_Info->channel & CHANNEL_HDMI)==0x00)&&
+ ((pOutput_Info->channel & CHANNEL_VGA) == 0x00))
+ {
+
+ reg = reg | 0x80;
+ }
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x66);
+ reg = reg & 0xFD;
+ I2CWrite(p_ch7xxx_context,0x66, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x64);
+ reg = reg & 0xFE;
+ I2CWrite(p_ch7xxx_context,0x64, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x63);
+ reg = reg & 0x03;
+ I2CWrite(p_ch7xxx_context,0x63, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg & 0xF7;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ /*Fix backlight blinking during mode switching in and out of lvds*/
+ I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) | 0x80 );
+ I2CWrite(p_ch7xxx_context,0x4D,0x80);/*need to use PWM to control backlight-6/4/12*/
+
+ if((pOutput_Info->channel & CHANNEL_HDMI) == 0x00 && (pOutput_Info->channel & CHANNEL_VGA) == 0x00){
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x02;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x54);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x54, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x02);
+ reg = I2CRead(p_ch7xxx_context,0x16);
+ reg = reg | 0x08;
+
+
+ I2CWrite(p_ch7xxx_context,0x16, reg);
+
+ }
+
+
+
+ }
+
+ if((pOutput_Info->channel & CHANNEL_LVDS) == 0x00)
+ {
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+
+ /*Fix backlight blinking during mode switching in and out of lvds*/
+ I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) & 0x7F );
+ I2CWrite(p_ch7xxx_context,0x4D,0x0);/*need to use PWM to control backlight-6/4/12*/
+
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg | 0x08;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ if((pOutput_Info->channel & CHANNEL_HDMI) == 0x00 && (pOutput_Info->channel & CHANNEL_VGA)==0x00)
+ {
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x63);
+ reg = reg | 0xFC;
+ I2CWrite(p_ch7xxx_context,0x63, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x64);
+ reg = reg | 0x01;
+ I2CWrite(p_ch7xxx_context,0x64, reg);
+ }
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x66);
+ reg = reg | 0x02;
+ I2CWrite(p_ch7xxx_context,0x66, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x1A);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x1A, reg);
+
+ }
+
+
+}
+
+void ch7036_set_power_hdmi(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ INPUT_INFO* pInput_Info = p_ch7xxx_context->pInput_Info;
+ uint8 reg=0x00;
+
+ PD_DEBUG("ch7036: ch7036_set_power_hdmi()-enter...channel [%lu]\n", pOutput_Info->channel);
+ if(pOutput_Info->channel & CHANNEL_HDMI)
+ {
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x52);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x52, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg & 0xDF;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xBF;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xF7;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg & 0x7F;
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg & 0xFD;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x54);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x54, reg);
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg & 0xFB;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xFB;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x0E);
+ reg = reg & 0x7F;
+ I2CWrite(p_ch7xxx_context,0x0E, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+
+ if(pInput_Info->audio_type == AUDIO_I2S){
+
+ reg = reg & 0xBF;
+ reg = reg | 0x01;
+ }else{
+
+ reg = reg | 0x40;
+ reg = reg & 0xFE;
+ }
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x16);
+ reg = reg & 0xF7;
+ I2CWrite(p_ch7xxx_context,0x16, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x16);
+ reg = reg & 0xFE;
+ I2CWrite(p_ch7xxx_context,0x16, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x08);
+ reg = reg & 0x0F;
+ I2CWrite(p_ch7xxx_context,0x08, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg & 0xF7;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xFE;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+
+
+ }else {
+
+
+ if((pOutput_Info->channel & CHANNEL_VGA) == 0x00){
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg | 0x20;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x40;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x08;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x04;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg | 0x80;
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x02;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x54);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x54, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x04;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ }
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x40;
+ reg = reg | 0x01;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+
+
+ if((pOutput_Info->channel & CHANNEL_LVDS) == 0x00)
+ {
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x16);
+ reg = reg | 0x08;
+ I2CWrite(p_ch7xxx_context,0x16, reg);
+ }
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x16);
+ reg = reg | 0x01;
+ I2CWrite(p_ch7xxx_context,0x16, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x08);
+ reg = reg | 0xF0;
+ I2CWrite(p_ch7xxx_context,0x08, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x08;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x01;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+
+ }
+
+}
+
+void ch7036_set_power_crt(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ uint8 reg=0x00;
+
+ PD_DEBUG("ch7036: ch7036_set_power_crt()-enter...channel [%lu]\n", pOutput_Info->channel);
+ if(pOutput_Info->channel & CHANNEL_VGA)
+ {
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg & 0x7F;
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg & 0xDF;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xBF;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xF7;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg & 0xF9;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x54);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x54, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x08);
+ reg = reg & 0xF1;
+ I2CWrite(p_ch7xxx_context,0x08, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg & 0xFB;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ }else if((pOutput_Info->channel & CHANNEL_VGA) == 0x00){
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+
+ reg = I2CRead(p_ch7xxx_context,0x08);
+ reg = reg | 0x0E;
+ I2CWrite(p_ch7xxx_context,0x08, reg);
+
+
+
+ if((pOutput_Info->channel & CHANNEL_HDMI)==0x00){
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x11);
+ reg = reg | 0x80;
+ I2CWrite(p_ch7xxx_context,0x11, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x02;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x54);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x54, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x00);
+ reg = I2CRead(p_ch7xxx_context,0x0A);
+ reg = reg | 0x20;
+ I2CWrite(p_ch7xxx_context,0x0A, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x40;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x08;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x10;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg | 0x04;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+
+ reg = I2CRead(p_ch7xxx_context,0x09);
+ reg = reg | 0x04;
+ I2CWrite(p_ch7xxx_context,0x09, reg);
+ }
+ }
+
+ return;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
new file mode 100644
index 0000000..d909c64
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
@@ -0,0 +1,1565 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_port.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+#include <linux/kernel.h>
+
+#include "ch7036_port.h"
+
+
+#ifdef T_LINUX
+ #include "lvds/lvds.h"
+#else
+ #include "lvds.h"
+#endif
+
+
+
+static pd_version_t g_ch7036_version = {1, 2, 5, 0};
+static unsigned long g_ch7036_dab_list[] = {0xEC,PD_DAB_LIST_END};
+
+
+void ch7036_update_position(ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info);
+int ch7036_initialize_device(ch7036_device_context_t *p_ctx);
+
+
+static pd_driver_t g_ch7036_drv = {
+ PD_SDK_VERSION,
+ "Chrontel CH7036 Port Driver",
+ 0,
+ &g_ch7036_version,
+ PD_DISPLAY_LVDS_INT,
+ PD_FLAG_UP_SCALING,
+ g_ch7036_dab_list,
+ 100,
+ ch7036_validate,
+ ch7036_open,
+ ch7036_init_device,
+ ch7036_close,
+ ch7036_set_mode,
+ ch7036_post_set_mode,
+ ch7036_set_attributes,
+ ch7036_get_attributes,
+ ch7036_get_timing_list,
+ ch7036_set_power,
+ ch7036_get_power,
+ ch7036_save,
+ ch7036_restore,
+ ch7036_get_port_status
+};
+
+
+extern established_timings_t et_I[8];
+extern established_timings_t et_II[8];
+extern established_timings_t et_man;
+
+
+int PD_MODULE_INIT(ch7036_init, (void *handle))
+{
+ int status;
+
+ PD_DEBUG("ch7036: ch7036_init()\n");
+
+ status = pd_register(handle, &g_ch7036_drv);
+ if (status != PD_SUCCESS) {
+ PD_DEBUG("ch7036: Error ! ch7036_init: pd_register() failed with "
+ "status=%#x\n", status);
+ }
+ return status;
+}
+
+
+
+int PD_MODULE_EXIT(ch7036_exit, (void))
+{
+ PD_DEBUG("ch7036: ch7036_exit()\n");
+
+ return (PD_SUCCESS);
+}
+
+
+unsigned long ch7036_validate(unsigned long cookie)
+{
+ PD_DEBUG("ch7036: ch7036_validate()\n");
+
+ return cookie;
+}
+
+
+int ch7036_open(pd_callback_t *p_callback, void **pp_context)
+{
+ uint8 device_ID;
+ ch7036_device_context_t* p_ctx;
+ DEV_CONTEXT* p_ch7xxx_context;
+
+ ch7036_edid_blk_t *p_edid1, *p_edid2;
+
+
+ int ret;
+
+
+
+ PD_DEBUG("ch7036: ch7036_open()- enter- ch7036 pd release- major [%x] minor [%x] patch [%x]\n",
+ g_ch7036_version.major,g_ch7036_version.minor,g_ch7036_version.patch);
+
+ ret = PD_INTERNAL_LVDS_MODULE_OPEN(ch7036_lvds_open,(p_callback, pp_context));
+ if ( ret != PD_SUCCESS)
+ {
+
+
+ PD_ERROR("ch7036: ch7036_open: EXIT#1\n");
+ return ret;
+ }
+
+ p_ctx = pd_malloc(sizeof(ch7036_device_context_t));
+ if (p_ctx == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed\n");
+ goto exit6;
+ }
+
+ pd_memset(p_ctx, 0, sizeof(ch7036_device_context_t));
+
+ /* per EMGD request */
+ p_edid1 = (ch7036_edid_blk_t *)p_ctx->cedid;
+ p_edid2 = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+
+ p_ctx->fw = (FW7036_CFG *)(pd_malloc(sizeof(FW7036_CFG)));
+
+ if (p_ctx->fw == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating FW7036_CFG struct\n");
+ goto exit5;
+ }
+
+#if 0
+ ret = PD_INTERNAL_LVDS_MODULE_OPEN(ch7036_lvds_open,(p_callback, pp_context));
+ if ( ret != PD_SUCCESS)
+ {
+ pd_free(p_ctx->fw);
+ pd_free(p_ctx);
+ return ret;
+ }
+#endif
+
+ p_ctx->internal_lvds = *pp_context;
+
+ p_ctx->p_callback = p_callback;
+
+#ifdef LVDS_ONLY
+ *pp_context = (void *)p_ctx;
+ return (PD_SUCCESS);
+#endif
+
+
+
+ p_ctx->p_ch7xxx_context = pd_malloc(sizeof(DEV_CONTEXT));
+ if (p_ctx->p_ch7xxx_context == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating DEV_CONTEXT struct");
+ goto exit4;
+ }
+
+ p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+
+ p_ch7xxx_context->pd_context = (void *)p_ctx;
+
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+
+ device_ID = I2CRead(p_ch7xxx_context,0x50);
+
+ PD_DEBUG("ch7036: ch7036_open()- read device ID= 0x%.2X\n", device_ID);
+
+
+ if(device_ID != 0x56)
+ {
+ PD_DEBUG("ch7036: ch7036_open()- device is NOT found...\n");
+
+ if(p_ch7xxx_context->pd_context)
+ p_ch7xxx_context->pd_context=NULL;
+ pd_free(p_ch7xxx_context);
+ if(p_ctx->internal_lvds) {
+ p_ctx->internal_lvds=NULL;
+
+ }
+ pd_free(p_ctx->fw);
+ pd_free(p_ctx);
+ return PD_ERR_NODEV;
+
+ }
+ else
+ {
+ PD_DEBUG("ch7036: ch7036_open()- ch7036 device is found...\n");
+
+
+ }
+
+ p_ch7xxx_context->DeviceID = device_ID;
+
+ ch7036_reset(p_ctx);
+ pd_usleep(50);
+
+ if (ch7036_load_firmware(p_ctx) != SS_SUCCESS) {
+ p_ctx->use_firmware =0;
+ p_ctx->cedid = NULL;
+ p_ctx->hedid = NULL;
+
+ }
+ else {
+ p_ctx->use_firmware =1;
+
+
+ p_ctx->cedid = (ch7036_edid_blk_t *)pd_malloc(sizeof(ch7036_edid_blk_t));
+
+ if (p_ctx->cedid == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating ch7036_edid_blk_t struct for crt");
+ goto exit3;
+ }
+
+ p_edid1 = (ch7036_edid_blk_t *)p_ctx->cedid ;
+
+ p_edid1->etiming_I = (established_timings_t *)pd_malloc(8 * sizeof(established_timings_t));
+ if (p_edid1->etiming_I == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating established_timings_t struct I for crt");
+ pd_free(p_ctx->cedid);
+ goto exit3;
+ }
+ p_edid1->etiming_II = (established_timings_t *)pd_malloc(8 * sizeof(established_timings_t));
+ if (p_edid1->etiming_II == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating established_timings_t struct II for crt");
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_ctx->cedid);
+ goto exit3;
+ }
+
+ p_ctx->hedid = (ch7036_edid_blk_t *)pd_malloc(sizeof(ch7036_edid_blk_t));
+
+ if (p_ctx->hedid == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating ch7036_edid_blk_t struct for hdvi");
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_edid1->etiming_II);
+ pd_free(p_ctx->cedid);
+
+ goto exit3;
+ }
+
+ p_edid2 = (ch7036_edid_blk_t *)p_ctx->hedid ;
+
+ p_edid2->etiming_I = (established_timings_t *)pd_malloc(8 * sizeof(established_timings_t));
+ if (p_edid2->etiming_I == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating established_timings_t struct I for crt");
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_edid1->etiming_II);
+ pd_free(p_ctx->cedid);
+ pd_free(p_ctx->hedid);
+
+ goto exit3;
+ }
+
+ p_edid2->etiming_II = (established_timings_t *)pd_malloc(8 * sizeof(established_timings_t));
+
+ if (p_edid2->etiming_II == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating established_timings_t struct for hdvi");
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_edid1->etiming_II);
+ pd_free(p_ctx->cedid);
+ pd_free(p_edid2->etiming_I);
+
+ pd_free(p_ctx->hedid);
+
+ goto exit3;
+ }
+
+
+ }
+
+
+ pd_memset(p_edid1->etiming_I, 0, 8 *
+ sizeof(established_timings_t));
+ pd_memset(p_edid1->etiming_II, 0, 8 *
+ sizeof(established_timings_t));
+
+ pd_memset(p_edid2->etiming_I, 0, 8 *
+ sizeof(established_timings_t));
+ pd_memset(p_edid2->etiming_II, 0, 8 *
+ sizeof(established_timings_t));
+
+
+
+
+
+
+
+ p_ch7xxx_context->pInput_Info = pd_malloc(sizeof(INPUT_INFO));
+ if (p_ch7xxx_context->pInput_Info == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating INPUT_INFO struct");
+
+ goto exit23;
+ }
+
+ p_ch7xxx_context->pOutput_Info = pd_malloc(sizeof(OUTPUT_INFO));
+ if (p_ch7xxx_context->pOutput_Info == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating OUTPUT_INFO struct");
+
+ goto exit2;
+ }
+
+ p_ch7xxx_context->pPrefer_Info = pd_malloc(sizeof(PREFER_INFO));
+ if (p_ch7xxx_context->pPrefer_Info == NULL) {
+ PD_ERROR("ch7036: Error ! ch7036_open: pd_malloc() failed allocating PREFER_INFO struct");
+
+ goto exit1;
+ }
+
+
+
+
+ p_ctx->p_ch7036_attr_table = NULL;
+
+ if( ch7036_init_attribute_table(p_ctx, NULL) == SS_MEM_ALLOC_ERR)
+ {
+ pd_free(p_ch7xxx_context->pPrefer_Info);
+ goto exit1;
+ }
+
+
+ ch7036_initialize_device(p_ctx);
+
+ g_ch7036_drv.type = PD_DISPLAY_LVDS_INT;
+
+
+ *pp_context = (void *)p_ctx;
+
+ PD_DEBUG("ch7036: ch7036_open: EXIT w/ SUCCESS...ch7036 pd release- major [%x] minor [%x] patch [%x]\n",
+ g_ch7036_version.major,g_ch7036_version.minor,g_ch7036_version.patch);
+ return (PD_SUCCESS);
+
+exit1:
+ pd_free(p_ch7xxx_context->pOutput_Info);
+exit2:
+ pd_free(p_ch7xxx_context->pInput_Info);
+
+exit23:
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_edid1->etiming_II);
+ pd_free(p_ctx->cedid);
+ pd_free(p_edid2->etiming_I);
+ pd_free(p_edid2->etiming_II);
+ pd_free(p_ctx->hedid);
+
+exit3:
+ p_ch7xxx_context->pd_context=NULL;
+ pd_free(p_ch7xxx_context);
+exit4:
+
+ p_ctx->internal_lvds = NULL;
+ pd_free(p_ctx->fw);
+exit5:
+ pd_free(p_ctx);
+exit6:
+ PD_ERROR("ch7036: ch7036_open: EXIT- PD_ERR_NOMEM\n");
+ return PD_ERR_NOMEM;
+}
+
+
+int ch7036_init_device(void *p_context)
+{
+ ch7036_device_context_t* p_ctx = (ch7036_device_context_t*)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ int ret;
+
+ PD_DEBUG("ch7036: ch7036_init_device()-enter\n");
+
+ p_ctx->init_done = 1;
+ ret= PD_INTERNAL_LVDS_MODULE_INIT_DEVICE(ch7036_lvds_init_device, (p_ctx->internal_lvds));
+
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+ PD_DEBUG("ch7036: ch7036_init_device()-p_ctx->prev_outchannel = pOutput_Info->channel = [0x%x]\n",pOutput_Info->channel);
+
+ PD_DEBUG("ch7036: ch7036_init_device()-exit\n");
+ return ret;
+
+}
+
+
+
+int ch7036_set_mode(void *p_context, pd_timing_t *p_mode, unsigned long flags)
+{
+
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t*)p_context;
+
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ INPUT_INFO* pInput_Info = p_ch7xxx_context->pInput_Info;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+ int ret, channel_on=0;
+
+
+ PD_DEBUG("ch7036: ch7036_set_mode()-enter\n");
+
+
+ if (!p_ctx || !p_mode) {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ if (p_ch7xxx_context->DeviceID != 0x56)
+ {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ PD_DEBUG("ch7036_set_mode: requested width = %u height = %u\n",
+ p_mode->width, p_mode->height);
+
+#ifndef LVDS_ONLY
+ if (
+ (p_ctx->fp_width && (p_mode->width > p_ctx->fp_width)) ||
+ (p_ctx->fp_height && (p_mode->height > p_ctx->fp_height))
+ ) {
+ return PD_ERR_MODE_NOTSUPP;
+ }
+
+ if( (p_ctx->fp_width == 640) && (p_ctx->fp_height == 480) ) {
+ p_ctx->downscaled[MODE_6x4_BYPASS] = 0;
+ }
+ else {
+ p_ctx->downscaled[MODE_6x4_BYPASS] = 1;
+ if( (!p_ctx->dwnscal_bypass) || ((p_ctx->fp_width <= 800) && (p_ctx->fp_height <= 600) ) )
+ p_ctx->downscaled[MODE_8x6_7x4_BYPASS] = 0;
+ else
+ p_ctx->downscaled[MODE_8x6_7x4_BYPASS] = 1;
+
+ }
+
+ if(pOutput_Info->channel == CHANNEL_LVDS_HDMI_VGA_OFF) {
+
+ pOutput_Info->channel = p_ctx->prev_outchannel; //restore output channel before temp. power down
+ channel_on =1;
+ }
+
+
+ if (pOutput_Info->channel == CHANNEL_LVDS) {
+
+ pOutput_Info->channel = CHANNEL_LVDS_HDMI; //force both channel on before setting in/out timing
+
+ }
+
+
+ ch7036_set_input_timing_info(p_ctx,pInput_Info);
+ ch7036_set_output_timing_info(p_ctx, pOutput_Info);
+ ch7036_set_prefer_timing_info(p_ctx,pPrefer_Info);
+
+
+ if(ch7036_device_prepare(p_ctx)== SS_UNSUCCESSFUL)
+ {
+ PD_DEBUG("ch7036_set_mode: ch7036_device_prepare()- NOT SUCCESS... ERROR CODE [%lu]\n", p_ctx->last_emsg);
+ return PD_ERR_UNSUCCESSFUL;
+ }
+
+
+ ch7036_update_position(p_ctx, pOutput_Info);
+
+ if(ch7036_device_config(p_ctx) == SS_UNSUCCESSFUL)
+ {
+ PD_DEBUG("ch7036_set_mode: ch7036_device_config()- NOT SUCCESS...ERROR CODE [%lu]\n", p_ctx->last_emsg);
+ return PD_ERR_UNSUCCESSFUL;
+ }
+
+ if(channel_on) {
+
+ pOutput_Info->channel = CHANNEL_LVDS_HDMI_VGA_OFF; //now, power down if it's tmp. powered up
+
+ }
+
+#endif
+
+ ret = PD_INTERNAL_LVDS_MODULE_SET_MODE(ch7036_lvds_set_mode,(p_ctx->internal_lvds,p_mode,flags));
+ if(ret != PD_SUCCESS)
+ return ret;
+
+
+ return PD_SUCCESS;
+}
+//thua- 10/24/11- when user switches back and forth from VGA to HDMI or vice versa
+//need to set h/v pos. accordingly
+void ch7036_update_position(ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info)
+{
+
+ PD_DEBUG("ch7036: ch7036_update_position()- enter\n");
+
+
+ if(pOutput_Info->channel & CHANNEL_HDMI) {
+ pOutput_Info->h_position = DEFAULT_POSITION;
+ pOutput_Info->v_position = DEFAULT_POSITION;
+
+ }
+
+ else { //pOutput_Info->channel & CHANNEL_VGA; note that CHANNEL_LVDS would never come here
+
+ pOutput_Info->h_position = (uint16)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_HPOSITION,
+ PD_GET_ATTR_LIST)->current_value;
+
+ pOutput_Info->v_position = (uint16)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_VPOSITION,
+ PD_GET_ATTR_LIST)->current_value;
+
+ }
+
+ PD_DEBUG("ch7036: ch7036_update_position()- h pos [%d]\n",pOutput_Info->h_position);
+ PD_DEBUG("ch7036: ch7036_update_position()- v pos [%d]\n",pOutput_Info->v_position);
+
+ return;
+}
+
+
+int ch7036_post_set_mode(void *p_context, pd_timing_t *p_mode,
+ unsigned long flags)
+{
+
+
+ ch7036_device_context_t* p_ctx = (ch7036_device_context_t*)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ int ret;
+
+
+
+
+
+ if (!p_ctx || !p_mode ) {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ if (p_ch7xxx_context->DeviceID != 0x56)
+ {
+ return (PD_ERR_NULL_PTR);
+ }
+
+#ifndef LVDS_ONLY
+
+
+
+ ch7036_set_output_channel(p_ctx, p_ctx->prev_outchannel);
+ PD_DEBUG("ch7036_post_set_mode- now, current pOutput_Info->channel is [%x]\n",pOutput_Info->channel);
+
+ if(ch7036_device_start(p_ctx) == SS_UNSUCCESSFUL)
+ {
+ PD_DEBUG("ch7036_post_set_mode: ch7036_device_start()- NOT SUCCESS\n");
+ return PD_ERR_UNSUCCESSFUL;
+ }
+
+
+
+
+
+#endif
+
+ /* Fix backlight blinking during mode switching
+ * in and out of lvds.
+ */
+ I2CWrite(p_ch7xxx_context,0x03,0x00);
+ I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) & 0x7F);
+
+ I2CWrite(p_ch7xxx_context,0x4D,0x0);/*need to use PWM to control backlight-6/4/12*/
+
+ ret = PD_INTERNAL_LVDS_MODULE_POST_SET_MODE(ch7036_lvds_post_set_mode,(p_ctx->internal_lvds,p_mode,flags));
+
+#ifndef LVDS_ONLY
+ if(ret != PD_SUCCESS)
+ return ret;
+ else
+ {
+
+ ch7036_reset_datapath(p_ch7xxx_context);
+ pd_usleep(50);
+
+
+ ch7036_device_set_power(p_ctx, pOutput_Info->channel);
+
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+ }
+
+#endif
+
+ /* for CH7036: Code fix Meego hang after killall X */
+ return p_ctx->pwr_state = PD_POWER_MODE_D0;
+}
+
+
+
+
+
+int ch7036_close(void *p_context)
+{
+
+ ch7036_device_context_t* p_ctx = (ch7036_device_context_t*)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ ch7036_edid_blk_t *p_edid1, *p_edid2;
+
+ p_edid1 = (ch7036_edid_blk_t *)p_ctx->cedid;
+ p_edid2 = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+
+ PD_DEBUG("ch7036: ch7036_close()\n");
+
+#ifndef LVDS_ONLY
+
+ ch7036_set_power(p_context, PD_POWER_MODE_D3);
+#endif
+
+ PD_INTERNAL_LVDS_MODULE_CLOSE(ch7036_lvds_close, (p_ctx->internal_lvds));
+
+ if (p_ctx!= NULL)
+ {
+
+ if(p_ctx->p_ch7xxx_context) {
+
+ pd_free(p_ch7xxx_context->pInput_Info);
+ p_ch7xxx_context->pInput_Info = NULL;
+
+ pd_free(p_ch7xxx_context->pOutput_Info);
+ p_ch7xxx_context->pOutput_Info = NULL;
+
+ pd_free(p_ch7xxx_context->pPrefer_Info);
+ p_ch7xxx_context->pPrefer_Info = NULL;
+
+ pd_free(p_ctx->p_ch7xxx_context);
+ p_ch7xxx_context = NULL;
+ }
+
+
+ if(p_edid1) {
+ pd_free(p_edid1->etiming_I);
+ pd_free(p_edid1->etiming_II);
+ pd_free(p_ctx->cedid);
+
+ p_edid1->etiming_I=NULL;
+ p_edid1->etiming_II=NULL;
+ p_ctx->cedid = NULL;
+
+ }
+ if(p_edid2) {
+ pd_free(p_edid2->etiming_I);
+ pd_free(p_edid2->etiming_II);
+ pd_free(p_ctx->hedid);
+
+ p_edid2->etiming_I=NULL;
+ p_edid2->etiming_II=NULL;
+ p_ctx->hedid = NULL;
+
+ }
+
+ if ( p_ctx->p_ch7036_attr_table) {
+ pd_free(p_ctx->p_ch7036_attr_table);
+ p_ctx->p_ch7036_attr_table = NULL;
+ p_ctx->ch7036_num_attrs = 0;
+ }
+
+ if(p_ctx->fw) {
+ pd_free(p_ctx->fw);
+ p_ctx->fw = NULL;
+ }
+
+
+ pd_free(p_ctx);
+ p_ctx = NULL;
+ }
+
+ return PD_SUCCESS;
+}
+
+
+int ch7036_get_timing_list(void *p_context, pd_timing_t *p_in_list,
+ pd_timing_t **pp_out_list)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+
+ int ret = 0;
+
+
+#ifndef T_PANEL_NATIVE_DTD
+ int i;
+ pd_timing_t * p_table;
+ lvds_context_t * p_lvds = (lvds_context_t *)(p_ctx->internal_lvds);
+
+#endif
+
+ pd_port_status_t port_status;
+
+
+
+ PD_DEBUG("ch7036: ch7036_get_timing_list()-enter\n");
+
+ if (p_ch7xxx_context->DeviceID != 0x56)
+ {
+ return (PD_ERR_NODEV);
+ }
+
+#ifdef LVDS_ONLY
+ PD_DEBUG("NUHAIRI: p_ctx->internal_lvds = %lu\n", p_ctx->internal_lvds);
+ if (p_ctx->internal_lvds != NULL){
+ PD_DEBUG("NUHAIRI: p_ctx->internal_lvds = %lu\n", p_ctx->internal_lvds);
+ return PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(ch7036_get_timing_list, (p_ctx->internal_lvds,p_in_list,pp_out_list));
+ }
+ return PD_SUCCESS;
+#endif
+
+
+
+ if ( (g_ch7036_drv.type & PD_DISPLAY_LVDS_INT) || (g_ch7036_drv.type & PD_DISPLAY_LVDS_LHDV) )
+ {
+ ret = PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(ch7036_lvds_get_timing_list, (p_ctx->internal_lvds,p_in_list,pp_out_list));
+
+ if(((lvds_context_t *)(p_ctx->internal_lvds))->native_dtd == 0 )
+ return PD_ERR_NO_TIMINGS;
+
+ p_ctx->p_lvds_table = *pp_out_list;
+
+#ifdef T_PANEL_NATIVE_DTD
+
+
+ pd_memcpy(&(p_ctx->native_dtd),((lvds_context_t *)(p_ctx->internal_lvds))->native_dtd,sizeof(pd_timing_t));
+
+ p_ctx->fp_width = ((lvds_context_t *)(p_ctx->internal_lvds))->fp_width;
+ p_ctx->fp_height = ((lvds_context_t *)(p_ctx->internal_lvds))->fp_height;
+
+ if( (p_ctx->fp_width == 0) || (p_ctx->fp_height == 0) )
+ return PD_ERR_NO_TIMINGS ;
+
+#else
+
+ for(i=0,p_table = *pp_out_list;i< 30;i++)
+ {
+
+ if((p_table->width == 1024) && (p_table->height == 768 )&&
+ (p_table->refresh == 60) )
+ {
+
+
+
+ pd_memcpy(&(p_ctx->native_dtd),p_table,sizeof(pd_timing_t));
+ p_ctx->fp_width = p_table->width;
+ p_ctx->fp_height = p_table->height;
+
+ break;
+ }
+
+ p_table= (pd_timing_t*)((uint8*)p_table + (sizeof(pd_timing_t)+4));
+
+ }
+
+
+ pd_memcpy(p_lvds->native_dtd,&(p_ctx->native_dtd),sizeof(pd_timing_t));
+ p_lvds->fp_width = p_ctx->fp_width;
+ p_lvds->fp_height = p_ctx->fp_height;
+
+#endif
+
+ }
+
+
+
+ if ( !p_ctx->init_done) {
+ PD_DEBUG("ch7036: ch7036_get_timing_list()-init is not done- inquire port status...\n");
+ ch7036_get_port_status((void *)p_ctx, &port_status);
+
+ }
+
+
+ ch7036_parse_edid(p_ctx);
+
+ return ret;
+
+}
+
+
+
+int ch7036_get_attributes(void *p_context, unsigned long *p_num_attr,
+ pd_attr_t **pp_list)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+
+
+
+ PD_DEBUG("ch7036: ch7036_get_attributes()-enter\n");
+
+
+
+ if (!p_ctx || !p_num_attr || !pp_list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ *pp_list = p_ctx->p_ch7036_attr_table;
+
+
+ *p_num_attr = p_ctx->ch7036_num_attrs;
+
+ PD_DEBUG("ch7036: ch7036_get_attributes()- total num_attrs = [%u]\n",*p_num_attr);
+
+ return PD_SUCCESS;
+}
+
+
+int ch7036_set_attributes(void *p_context, unsigned long num_attrs,
+ pd_attr_t *p_list)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+ pd_list_entry_attr_t* list_item;
+
+ pd_port_status_t port_status;
+
+ pd_attr_t *p_curr, *p_attr;
+ int ret;
+ unsigned long i,temp=0;
+ uint32 temp_chan;
+ ch7036_status_t status;
+
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()-enter: num_attrs=%u\n", num_attrs);
+
+
+ ret = PD_INTERNAL_LVDS_MODULE_SET_ATTRIBUTES(ch7036_lvds_set_attrs, (p_ctx->internal_lvds,num_attrs,p_list));
+
+
+
+ if(ret != PD_SUCCESS)
+ return ret;
+
+#ifdef LVDS_ONLY
+ return PD_SUCCESS;
+#endif
+
+
+ if (!p_ctx->init_done) {
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()- at bootup...\n");
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()- p_ctx->hpd [%x]\n", p_ctx->hpd);
+
+ p_attr = pd_get_attr(p_list, num_attrs, PD_ATTR_ID_DISPLAY, 0);
+ if (p_attr && (p_attr->flags & PD_ATTR_FLAG_VALUE_CHANGED) ) {
+
+
+ pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+ PD_GET_ATTR_LIST)->current_value
+ = p_attr->current_value;
+
+
+ }
+
+
+ p_attr = pd_get_attr(p_list, num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+ p_curr = pd_get_attr(p_ctx->p_ch7036_attr_table, num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+
+ if (p_attr && (p_attr->flags & PD_ATTR_FLAG_VALUE_CHANGED) ) {
+
+ if(p_curr) {
+ pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_HDMI_OUT_MODE,
+ PD_GET_ATTR_LIST)->current_value
+ = p_attr->current_value;
+ p_curr->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ }
+
+
+ }
+
+
+ p_attr = pd_get_attr(p_list, num_attrs, PD_ATTR_ID_DVI_OUT_MODE, 0);
+ p_curr = pd_get_attr(p_ctx->p_ch7036_attr_table, num_attrs, PD_ATTR_ID_DVI_OUT_MODE, 0);
+
+ if (p_attr && (p_attr->flags & PD_ATTR_FLAG_VALUE_CHANGED) ) {
+
+
+
+ if(p_curr) {
+ pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DVI_OUT_MODE,
+ PD_GET_ATTR_LIST)->current_value
+ = p_attr->current_value;
+ p_curr->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ }
+
+
+ }
+
+
+
+
+ p_attr = pd_get_attr(p_list, num_attrs, PD_ATTR_ID_CRT_OUT_MODE, 0);
+ p_curr = pd_get_attr(p_ctx->p_ch7036_attr_table, num_attrs, PD_ATTR_ID_CRT_OUT_MODE, 0);
+
+ if (p_attr && (p_attr->flags & PD_ATTR_FLAG_VALUE_CHANGED) ) {
+
+ if(p_curr) {
+ pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_CRT_OUT_MODE,
+ PD_GET_ATTR_LIST)->current_value
+ = p_attr->current_value;
+
+ p_curr->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+ }
+
+
+ }
+
+
+
+ }
+
+
+ for (i = 0, p_attr = p_list; i < num_attrs; i++,p_attr++)
+ {
+
+
+ if (!(p_attr->flags & PD_ATTR_FLAG_VALUE_CHANGED)) {
+
+ continue;
+ }
+
+
+ p_attr->flags &= ~PD_ATTR_FLAG_VALUE_CHANGED;
+
+ if (p_attr->flags & PD_ATTR_FLAG_USER_INVISIBLE)
+ continue;
+
+
+ if( (p_attr->id == 0x1A) || (p_attr->id == 0x1B) ||
+ (p_attr->id == 0x3C) || (p_attr->id == 0x46) ||
+ (p_attr->id == 0x47) )
+ continue;
+
+#if 0
+
+ p_curr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_attr->id,
+ PD_GET_ATTR_LIST);
+#endif
+
+
+ p_curr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_attr->id,
+ 0);
+ PD_DEBUG("ch7036_set_attributes(): attribute changed is of type [%ld] name [%s] id [%ld]\n",p_attr->type, p_attr->name, p_attr->id);
+
+ PD_DEBUG("ch7036_set_attributes():current value [%ld] requested value [%ld]\n",p_curr->current_value, p_attr->current_value);
+
+
+ temp = p_curr->current_value;
+ p_curr->current_value = p_attr->current_value;
+ switch (p_attr->id) {
+ case PD_ATTR_ID_DISPLAY:
+
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+ PD_GET_ATTR_LIST_ENTRY);
+
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+
+ if(list_item->value == CHANNEL_AUTO_DETECT) {
+ p_ctx->man_sel_out = 0;
+
+ if(p_ctx->init_done) {
+ p_ctx->hpd |= CH7036HPD_RESERVED1; //force port status inquiry
+ ch7036_get_port_status((void *)p_ctx, &port_status);
+
+ }
+ break;
+ }
+ //end of CHANNEL_AUTO_DETECT, manual selection of display output begins
+
+
+ p_ctx->man_sel_out = 1;
+
+ //1- save a copy
+ temp_chan = p_ctx->prev_outchannel;
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+
+ PD_DEBUG("ch7036_set_attributes():current list item value [0x%x]\n",list_item->value);
+
+ //2- get requested output channel- assume it's allowed
+
+ if(list_item->value & CHANNEL_DVI) {
+ pOutput_Info->channel = (list_item->value & 0x01) | CHANNEL_HDMI;
+ }
+ else
+ pOutput_Info->channel = list_item->value;
+
+ PD_DEBUG("ch7036_set_attributes():current output channel value [0x%x]\n",pOutput_Info->channel);
+
+ //3- check requested selection vs what is available
+ status = ch7036_get_attached_device(p_ctx); //manual mode- verify its selection and correct if needed
+
+ //4- NOT allowed display choice- also include when none is connected
+ if( status == SS_DISPLAY_CHOICE_NOT_ALLOWED) { //restore previous states
+ PD_DEBUG("ch7036_set_attributes(): display choice is not allowed- restore prev. states...\n");
+
+ p_ctx->hpd &= 0xEF; //reset
+
+ if(p_ctx->init_done){
+ pOutput_Info->channel = p_ctx->prev_outchannel;
+ p_ctx->prev_outchannel = temp_chan;
+ p_curr->current_value = temp;
+ //when system is restarted right after this point, need to provide main driver w/ a valid
+ //restored choice
+ p_attr->current_value = p_curr->current_value;
+ if(p_curr->current_value==1)
+ p_ctx->man_sel_out = 0;
+
+ }
+ else { //at installation, when init is not done, if manual choice is not valid, revert to auto
+
+ p_curr->current_value = 1;
+ p_ctx->man_sel_out = 0;
+
+ if (pOutput_Info->channel & CHANNEL_HDMI) //DVI mapped to CHANNEL_HDMI
+ {
+ pOutput_Info->channel = (pOutput_Info->channel & 0x01) | CHANNEL_VGA;
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+
+ }
+ else { //VGA
+ pOutput_Info->channel = (pOutput_Info->channel & 0x01) | CHANNEL_HDMI;
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+ }
+
+
+ }
+
+ PD_DEBUG("ch7036_set_attributes(): p_curr->current_value is: [%x]\n",p_curr->current_value);
+ if(p_ctx->hpd == 0x50) {//none is attached
+ pOutput_Info->channel &= CHANNEL_LVDS;
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+ }
+
+
+ }
+ PD_DEBUG("ch7036_set_attributes(): now- output display channel is: value [%ld]\n",pOutput_Info->channel);
+
+
+ //special case channel CHANNEL_xxx_HDMI:
+ //incoming dvi format => convert to hdmi format- or- incoming hdmi format => convert to dvi format
+ if( ( (pOutput_Info->hdmi_fmt.is_dvi_mode==1) && ((list_item->value & 0x02) == CHANNEL_HDMI) ) ||
+ ( (pOutput_Info->hdmi_fmt.is_dvi_mode==0) && ((list_item->value & 0x08) == CHANNEL_DVI) )
+ )
+ p_ctx->hpd |= 0x40; //request edid read again to update hdmi/dvi format accordingly
+
+
+ //base on 'new' attached info, read edid and set proper display output channel, including DVI
+ //case: manual selection w/ hpd change
+ if(p_ctx->hpd & 0x44) {
+ ch7036_alter_display_channel(p_ctx);
+ }
+
+ if( (pOutput_Info->channel & 0x04) == CHANNEL_VGA || p_curr->current_value==1 /* Coerced Auto Detect */ )
+ break;
+
+ //case:
+ //channel CHANNEL_xxx_HDMI- update list item xxx_DVI or xxx_HDMI accordingly
+ if((pOutput_Info->channel & CHANNEL_HDMI) && (pOutput_Info->hdmi_fmt.is_dvi_mode==1) )
+ p_curr->current_value = (pOutput_Info->channel & 0x01) == CHANNEL_LVDS?3:6;//lvds-dvi:dvi
+
+ else
+ if((pOutput_Info->channel & CHANNEL_HDMI) && (pOutput_Info->hdmi_fmt.is_dvi_mode==0) )
+ p_curr->current_value = (pOutput_Info->channel & 0x01) == CHANNEL_LVDS?2:5;//lvds-hdmi:hdmi
+
+ PD_DEBUG("ch7036_set_attributes(): after alter channel- output display channel is: value [%ld]\n",pOutput_Info->channel);
+
+ break;
+
+ case PD_ATTR_ID_HDMI_OUT_MODE:
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_HDMI_OUT_MODE,
+ PD_GET_ATTR_LIST_ENTRY);
+ p_ctx->hdmi_mode_index = list_item->value;
+ PD_DEBUG("ch7036_set_attributes(): updated hdmi_mode_index is: value [%ld]\n",p_ctx->hdmi_mode_index);
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ break;
+
+ case PD_ATTR_ID_DVI_OUT_MODE:
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DVI_OUT_MODE,
+ PD_GET_ATTR_LIST_ENTRY);
+ p_ctx->dvi_mode_index = list_item->value;
+ PD_DEBUG("ch7036_set_attributes(): updated dvi_mode_index is: value [%ld]\n",p_ctx->dvi_mode_index);
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ break;
+
+ case PD_ATTR_ID_CRT_OUT_MODE:
+ list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_CRT_OUT_MODE,
+ PD_GET_ATTR_LIST_ENTRY);
+ p_ctx->crt_mode_index = list_item->value;
+ PD_DEBUG("ch7036_set_attributes(): updated crt_mode_index is: value [%ld]\n",p_ctx->crt_mode_index);
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ break;
+
+ case PD_ATTR_ID_HPOSITION: //these attributes are for vga only
+ case PD_ATTR_ID_VPOSITION:
+
+ PD_DEBUG("ch7036_set_attributes(): set vga h/v position...\n");
+
+ //save vga h/v attribute context
+ if(p_curr->current_value > ((pd_range_attr_t *)p_curr)->max)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->max;
+ else if (p_curr->current_value < ((pd_range_attr_t *)p_curr)->min)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->min;
+
+
+ if( pOutput_Info->channel & CHANNEL_HDMI)
+ break;
+
+ if (p_attr->id == PD_ATTR_ID_HPOSITION)
+ pOutput_Info->h_position = (uint16)(p_curr->current_value);
+ else
+ pOutput_Info->v_position = (uint16)(p_curr->current_value);
+
+ ch7036_set_position(p_ctx, (uint8)p_attr->id, (uint16)(p_curr->current_value));
+
+ PD_DEBUG("ch7036_set_attributes(): updated and set vga position: value [%d]\n",p_curr->current_value);
+
+ break;
+ case PD_ATTR_ID_HSCALE:
+ case PD_ATTR_ID_VSCALE:
+ case PD_ATTR_ID_HSCALE_CRT:
+ case PD_ATTR_ID_VSCALE_CRT:
+
+ if(p_curr->current_value > ((pd_range_attr_t *)p_curr)->max)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->max;
+ else if (p_curr->current_value < ((pd_range_attr_t *)p_curr)->min)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->min;
+
+
+ if(p_attr->id== PD_ATTR_ID_HSCALE || p_attr->id== PD_ATTR_ID_HSCALE_CRT)
+ ch7036_set_scaling (pOutput_Info,PD_ATTR_ID_HSCALE, (uint8)p_curr->current_value);
+ else
+ ch7036_set_scaling (pOutput_Info,PD_ATTR_ID_VSCALE, (uint8)p_curr->current_value);
+ PD_DEBUG("ch7036_set_attributes(): updated scale value is: value [%lu]\n",p_curr->current_value);
+
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+
+ break;
+ case PD_ATTR_ID_DITHER_BYPASS:
+
+
+ PD_DEBUG("ch7036_set_attributes(): updated quality enhance value is: value [%lu]\n",p_curr->current_value);
+ ch7036_set_quality_enhancement(p_ctx,(uint8)p_curr->current_value);
+ break;
+
+ case PD_ATTR_ID_DITHER:
+ p_ctx->dither_select = (uint8)p_curr->current_value;
+ PD_DEBUG("ch7036_set_attributes(): updated dither select value is: value [%lu]\n",p_curr->current_value);
+ ch7036_set_dither(p_ctx);
+
+ break;
+
+ case PD_ATTR_ID_TEXT_FILTER:
+
+ if(p_curr->current_value > ((pd_range_attr_t *)p_curr)->max)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->max;
+ else if (p_curr->current_value < ((pd_range_attr_t *)p_curr)->min)
+ p_curr->current_value = ((pd_range_attr_t *)p_curr)->min;
+
+ PD_DEBUG("ch7036_set_attributes(): update text tuning value...\n");
+ ch7036_set_text_enhancement (p_ctx, (uint8) p_curr->current_value);
+
+ break;
+
+ case PD_ATTR_ID_LOAD_FIRMWARE:
+ PD_DEBUG("ch7036_set_attributes(): updated [reload-firmware] value is: value [%lu]\n",p_curr->current_value);
+
+ break;
+
+ case PD_ATTR_ID_DWNSCAL_BYPASS:
+ PD_DEBUG("ch7036_set_attributes(): updated [dwnscal_bypass] value is: value [%lu]\n",p_curr->current_value);
+ if(p_curr->current_value ) {
+ p_ctx->dwnscal_bypass = 1;
+ p_ctx->downscaled[MODE_8x6_7x4_BYPASS]=1;
+ }
+ else {
+ p_ctx->dwnscal_bypass = 0;
+ p_ctx->downscaled[MODE_8x6_7x4_BYPASS]=0;
+ }
+
+ break;
+
+ case PD_ATTR_ID_REFRESH:
+ PD_DEBUG("ch7036_set_attributes(): refresh value is: value [%lu]\n",p_curr->current_value);
+
+ if(p_curr->current_value )
+ p_curr->current_value= 0;
+
+ if(p_ctx->init_done && !p_ctx->man_sel_out ) {
+
+ p_ctx->hpd |= CH7036HPD_RESERVED1; //force port status inquiry- edid read bit
+
+ ch7036_get_port_status((void *)p_ctx, &port_status);
+
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+
+ }
+ break;
+
+ default:
+
+ PD_DEBUG("ch7036_set_attr(): unhandled attr name[%s]id[%ld]curr_index[%lu]\n",p_attr->name, p_attr->id,p_attr->current_value);
+ break;
+
+ }
+
+ }
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()-p_ctx->man_sel_out at exit [0x%x]\n",p_ctx->man_sel_out);
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()-p_ctx->hpd at exit [0x%x]\n",p_ctx->hpd);
+
+ PD_DEBUG("ch7036: ch7036_set_attributes()-exit\n");
+
+ return ret;
+}
+
+int ch7036_set_power(void *p_context, unsigned long state)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+ OUTPUT_INFO* pOutput_Info = (p_ctx->p_ch7xxx_context)->pOutput_Info;
+
+
+ int ret;
+
+
+ PD_DEBUG("ch7036: ch7036_set_power()-enter: requested state=%x\n", state);
+
+#ifdef LVDS_ONLY
+ return PD_INTERNAL_LVDS_MODULE_SET_POWER(ch7036_set_power, (p_ctx->internal_lvds,state));
+#endif
+
+ if (!p_ctx)
+ return PD_ERR_NULL_PTR;
+
+ if (state > PD_POWER_MODE_D3)
+ return PD_ERR_INVALID_POWER;
+
+ if (state != PD_POWER_MODE_D0) {
+
+ if(pOutput_Info->channel != CHANNEL_LVDS_HDMI_VGA_OFF)
+ p_ctx->prev_outchannel = pOutput_Info->channel; //store current output channel before temporarily powered down
+ pOutput_Info->channel = CHANNEL_LVDS_HDMI_VGA_OFF;
+
+
+ ch7036_device_set_power(p_ctx,pOutput_Info->channel);
+
+ ret = PD_INTERNAL_LVDS_MODULE_SET_POWER(ch7036_lvds_set_power, (p_ctx->internal_lvds,state));
+
+
+ }
+ else {
+
+
+ ch7036_set_output_channel(p_ctx,p_ctx->prev_outchannel); //restore previous output channel
+
+ PD_DEBUG("ch7036: ch7036_set_power()- p->ctx-hpd [0x%x]\n",p_ctx->hpd);
+ PD_DEBUG("ch7036: ch7036_set_power()- requested output channel- [%x]\n", pOutput_Info->channel);
+
+
+ PD_INTERNAL_LVDS_MODULE_SET_POWER(ch7036_lvds_set_power, (p_ctx->internal_lvds,state));
+
+ ch7036_device_set_power(p_ctx,pOutput_Info->channel);
+
+ }
+
+
+ p_ctx->pwr_state = state;
+
+ return PD_SUCCESS;
+}
+
+
+int ch7036_get_power(void *p_context, unsigned long *p_state)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+
+
+ PD_DEBUG("ch7036: ch7036_get_power()\n");
+
+#ifdef LVDS_ONLY
+ return PD_INTERNAL_LVDS_MODULE_GET_POWER(ch7036_get_power, (p_ctx->internal_lvds,p_state));
+#endif
+
+ *p_state = p_ctx->pwr_state;
+
+ return PD_SUCCESS;
+}
+
+int ch7036_save(void *p_context, void **state, unsigned long flags)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+ OUTPUT_INFO* pOutput_Info = (p_ctx->p_ch7xxx_context)->pOutput_Info;
+
+ PD_DEBUG("ch7036: ch7036_save()\n");
+
+#ifdef LVDS_ONLY
+
+ return PD_INTERNAL_LVDS_MODULE_SAVE(ch7036_save,(p_ctx->internal_lvds, state, flags));
+#endif
+
+ //in Linux, when being called @ init, it incorrectly assigned unintialized global attribute value to prev outchannel
+ //p_ctx->prev_outchannel = ch7036_get_output_channel(p_context);
+ //fixed
+ p_ctx->prev_outchannel = pOutput_Info->channel;
+
+
+ *state = NULL;
+
+ return PD_SUCCESS;
+}
+
+
+
+int ch7036_restore(void *p_context, void *state, unsigned long flags)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)p_context;
+
+ unsigned long i;
+
+
+
+ PD_DEBUG("ch7036: ch7036_restore()\n");
+
+#ifdef LVDS_ONLY
+
+ return PD_INTERNAL_LVDS_MODULE_RESTORE(ch7036_restore,(p_ctx->internal_lvds, state, flags));
+#endif
+
+ /* for CH7036: Code fix Meego hang after killall X
+ */
+#ifdef T_LINUX
+ if(p_ctx->pwr_state != PD_POWER_MODE_D1)
+ return PD_SUCCESS;
+#endif
+
+
+ if (ch7036_load_firmware(p_ctx) != SS_SUCCESS) {
+ PD_DEBUG("ch7036: ch7036_restore()- load fw is NOT a SUCCESS\n");
+ return PD_ERR_UNSUCCESSFUL;
+
+ }
+ else {
+ PD_DEBUG("ch7036: ch7036_restore()- load fw is a SUCCESS\n");
+ }
+
+
+
+ if(p_ctx->prev_outchannel == CHANNEL_LVDS_HDMI) {
+
+ ch7036_set_output_channel(p_context, p_ctx->prev_outchannel);
+ ch7036_set_mode(p_context, &(p_ctx->native_dtd), 0);
+ ch7036_post_set_mode(p_context, &(p_ctx->native_dtd), 0);
+ }
+
+
+ for(i=0;i<p_ctx->ch7036_num_attrs;i++) {
+
+ if( p_ctx->p_ch7036_attr_table[i].id == PD_ATTR_ID_REFRESH ) {
+
+
+ p_ctx->p_ch7036_attr_table[i].flags |= PD_ATTR_FLAG_VALUE_CHANGED;
+ p_ctx->p_ch7036_attr_table[i].current_value = 1;
+
+ ch7036_set_attributes(p_context, 1, &p_ctx->p_ch7036_attr_table[i]);
+ break;
+ }
+
+ }
+
+
+ return PD_SUCCESS;
+
+}
+
+
+int ch7036_get_port_status(void *context, pd_port_status_t *port_status)
+{
+ ch7036_device_context_t *p_ctx = (ch7036_device_context_t *)context;
+ OUTPUT_INFO* pOutput_Info = (p_ctx->p_ch7xxx_context)->pOutput_Info;
+
+#if 0
+ FW7036_CFG* fv = (FW7036_CFG*) p_ctx->fw;
+ int ret;
+#endif
+
+ port_status->display_type = PD_DISPLAY_LVDS_INT;
+ port_status->connected = PD_DISP_STATUS_UNKNOWN;
+
+
+ PD_DEBUG("ch7036: ch7036_get_port_status()-enter... p_ctx->hpd [%x]\n", p_ctx->hpd);
+
+#if 0
+ PD_DEBUG("Get LHFM Version Information.\r\n");
+ ret = LHFM_get_version(p_ch7xxx_context, fv);
+ if (0==ret) {
+ PD_DEBUG("Ma_ver=%d, mi_ver=%d, did=%02X, rid= %02X, capability=%s\r\n",
+ fv->ver_major, fv->ver_minor, fv->did, fv->rid, (fv->capbility & 0x2) ? "EDID+HDCP" : "EDID");
+ }
+ else {
+ PD_DEBUG("--- failed!\r\n");
+ PD_DEBUG("status: [%s]\n",ret ==-1?"timeout!":"firmware_error!");
+ }
+#endif
+
+
+#ifdef LVDS_ONLY
+
+ return PD_INTERNAL_LVDS_MODULE_GET_PORT_STATUS(ch7036_get_port_status,(p_ctx->internal_lvds, port_status));
+#endif
+
+ if(! (p_ctx->hpd & CH7036HPD_RESERVED1) ) {
+ //note: main driver check port status several times, this block is to speed things up a little
+ if ((p_ctx->init_done) && (pOutput_Info->channel == p_ctx->prev_outchannel ) ) {
+ if(p_ctx ->hpd & 0x22)
+ port_status->connected = PD_DISP_STATUS_ATTACHED;
+ PD_DEBUG("ch7036: ch7036_get_port_status()-output channel UNCHANGED- exit. p_ctx->hpd [%x]\n", p_ctx->hpd);
+ return PD_SUCCESS;
+ }
+
+ }
+
+ if(p_ctx->use_firmware) {
+
+ ch7036_get_attached_device(p_ctx);
+ if(p_ctx ->hpd & 0x22)
+ port_status->connected = PD_DISP_STATUS_ATTACHED;
+
+ ch7036_alter_display_channel(p_ctx);
+
+ }
+
+
+ p_ctx->hpd &= 0xEE;
+
+ PD_DEBUG("ch7036: ch7036_get_port_status()-exit. p_ctx->hpd [%x]\n", p_ctx->hpd);
+ return PD_SUCCESS;
+}
+
+
+
+
+int ch7036_initialize_device(ch7036_device_context_t *p_ctx)
+{
+ DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+ OUTPUT_INFO* pOutput_Info = (p_ctx->p_ch7xxx_context)->pOutput_Info;
+ PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+ uint8 reg; //,i=0;
+
+ ch7036_edid_blk_t* p_hedid;
+ ch7036_edid_blk_t* p_cedid ;
+
+
+ PD_DEBUG("ch7036: ch7036_initialize_device()- ENTER...\n");
+
+
+ p_ctx->init_done = 0;
+ p_ctx->hpd = 0;
+
+ p_ctx->downscaled[MODE_6x4_BYPASS] = 1;
+ p_ctx->downscaled[MODE_8x6_7x4_BYPASS] = 1;
+ p_ctx->dwnscal_bypass = 1;
+
+ if(p_ctx->use_firmware) {
+
+ p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+ p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+
+
+ pd_memcpy(p_cedid->etiming_I,et_I,8* sizeof(established_timings_t));
+ pd_memcpy(p_cedid->etiming_II,et_II,8* sizeof(established_timings_t));
+
+
+ p_cedid->etiming_man = &et_man;
+
+
+
+ pd_memcpy(p_hedid->etiming_I,et_I,8* sizeof(established_timings_t));
+ pd_memcpy(p_hedid->etiming_II,et_II,8* sizeof(established_timings_t));
+
+ p_hedid->etiming_man = &et_man;
+
+
+ p_cedid->is_edid = 0;
+ p_hedid->is_edid = 0;
+ p_cedid->ebn = 0;
+ p_hedid->ebn = 0;
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x04);
+ reg = I2CRead(p_ch7xxx_context,0x52);
+ reg = reg & 0xEF;
+ I2CWrite(p_ch7xxx_context,0x52, reg);
+
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x0);
+ reg = I2CRead(p_ch7xxx_context,0x07);
+ reg = reg & 0x70;
+ I2CWrite(p_ch7xxx_context,0x07, reg);
+
+ /*Fix backlight blinking during mode switching in and out of lvds*/
+ I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) & 0x7F);
+ I2CWrite(p_ch7xxx_context,0x4D,0x0);/*need to use PWM to control backlight-6/4/12*/
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x01);
+ reg = I2CRead(p_ch7xxx_context,0x0F);
+ reg = reg & 0x7F;
+ I2CWrite(p_ch7xxx_context,0x0F, reg);
+
+ I2CWrite(p_ch7xxx_context,0x03, 0x03);
+ reg = I2CRead(p_ch7xxx_context,0x6E);
+ reg = reg & 0xBF;
+ I2CWrite(p_ch7xxx_context,0x6E, reg | 0x40);
+
+
+ }
+
+
+ pOutput_Info->hdmi_fmt.is_dvi_mode = 0;
+
+ pOutput_Info->channel = CHANNEL_LVDS | CHANNEL_HDMI;
+
+
+
+ PD_DEBUG("ch7036: ch7036_initialize_device()- default output channel is [%u]\n",pOutput_Info->channel);
+
+
+
+ pOutput_Info->h_position = DEFAULT_POSITION;
+ pOutput_Info->v_position = DEFAULT_POSITION;
+
+
+ p_ctx->dither_select = DITHER_18_TO_18;
+ p_ctx->man_sel_out= 0;
+
+ ch7036_set_scaling (pOutput_Info,PD_ATTR_ID_HSCALE, HDMI_DEFAULT_UNDERSCAN);
+ ch7036_set_scaling (pOutput_Info,PD_ATTR_ID_VSCALE, HDMI_DEFAULT_UNDERSCAN);
+
+ ch7036_set_prefer_timing_info(p_ctx,pPrefer_Info);
+
+ return PD_SUCCESS;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
new file mode 100644
index 0000000..6798815
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
@@ -0,0 +1,59 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_port.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef _CH7036_PORT_H_
+#define _CH7036_PORT_H_
+
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+int ch7036_open(pd_callback_t *p_callback, void **p_context);
+int ch7036_init_device(void *p_context);
+int ch7036_get_timing_list(void *p_context, pd_timing_t *p_in_list,
+ pd_timing_t **pp_out_list);
+int ch7036_set_mode(void *p_context, pd_timing_t *p_mode, unsigned long flags);
+int ch7036_post_set_mode(void *p_context, pd_timing_t *p_mode,
+ unsigned long flags);
+
+int ch7036_get_attributes(void *p_context, unsigned long *p_num_attr,
+ pd_attr_t **pp_list);
+int ch7036_set_attributes(void *p_context, unsigned long num_attr,
+ pd_attr_t *p_list);
+unsigned long ch7036_validate(unsigned long cookie);
+int ch7036_close(void *p_context);
+
+int ch7036_set_power(void *p_context, unsigned long state);
+int ch7036_get_power(void *p_context, unsigned long *p_state);
+int ch7036_save(void *p_context, void **pp_state, unsigned long flags);
+int ch7036_restore(void *p_context, void *p_state, unsigned long flags);
+int ch7036_get_port_status(void *context, pd_port_status_t *port_status);
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
new file mode 100755
index 0000000..126480f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
@@ -0,0 +1,224 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_reg_table.c
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_reg_table.h"
+
+
+
+
+MULTI_REG g_MultiRegTable[MUL_ID_END] =
+{
+ {BASE_FLAG, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 3, 6, NOOP_INDEX, 0, 7, 0},
+
+ {HTI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0B,3, 6, 0x0D, 0, 7, 0},
+ {VTI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x11,3, 5, 0x13, 0, 7, 0},
+ {HAI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0B,0, 2, 0x0C, 0, 7, 0},
+ {VAI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x11,0, 2, 0x12, 0, 7, 0},
+ {HOI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0E,0, 2, 0x0F, 0, 7, 0},
+ {VOI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x14,0, 2, 0x15, 0, 7, 0},
+ {HWI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0E,3, 5, 0x10, 0, 7, 0},
+ {VWI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x14,3, 5, 0x16, 0, 7, 0},
+ {RCLK, NOOP_INDEX, 0, 0, 0x0F,0, 1, 0x14,0, 7, 0x15, 0, 7, 4},
+ {DITHER_SEL1_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x57, 7, 7, 4},
+ {DITHER_SEL0_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x57, 6, 6, 4},
+ {HSYNCP_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x41, 6, 6, 1},
+ {VSYNCP_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x41, 5, 5, 1},
+ {NP_INV0_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x58, 4, 4, 4},
+ {NP_INV1_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x58, 3, 3, 4},
+ {NP_INV2_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x58, 2, 2, 4},
+ {NP_INV3_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x58, 1, 1, 4},
+ {LVDS_IN_ORDER, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5F, 0, 0, 4},
+
+ {LVDS0_SEQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5E, 5, 7, 4},
+ {LVDS1_SEQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5E, 2, 4, 4},
+ {LVDS2_SEQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5F, 7, 7, 4},
+ {LVDS3_SEQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5F, 4, 6, 4},
+ {LVDSCLK_SEQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5F, 1, 3, 4},
+ {HSYNC_CNT_TH_SPP,NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 5, 6, 4},
+ {PRBS_SET_SEL_SPP,NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x61, 1, 1, 4},
+ {LVDS0_POL_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 4, 4, 4},
+ {LVDS1_POL_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 3, 3, 4},
+ {LVDS2_POL_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 2, 2, 4},
+ {LVDS3_POL_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 1, 1, 4},
+ {LVDSCLK_POL_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x59, 0, 0, 4},
+
+ {HTO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1F,3, 6, 0x21, 0, 7, 0},
+ {VTO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x25,3, 5, 0x27, 0, 7, 0},
+ {HAO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1F,0, 2, 0x20, 0, 7, 0},
+ {VAO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x25,0, 2, 0x26, 0, 7, 0},
+ {HOO_HDMI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x54,0, 2, 0x55, 0, 7, 0},
+ {VOO_HDMI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x57,0, 2, 0x58, 0, 7, 0},
+ {HWO_HDMI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x54,3, 5, 0x56, 0, 7, 0},
+ {VWO_HDMI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x57,3, 5, 0x59, 0, 7, 0},
+ {HPO_I, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x19, 5, 5, 0},
+ {VPO_I, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x19, 4, 4, 0},
+ {DEPO_I, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x19, 3, 3, 0},
+ {HPO_O, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 4, 4, 0},
+ {VPO_O, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 3, 3, 0},
+ {DEPO_O, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 5, 5, 0},
+
+ {HD_DVIB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0A, 2, 2, 0},
+ {INTLC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1E, 5, 5, 0},
+ {HD_LV_POL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x4C, 5, 5, 0},
+ {HD_LV_SEQ, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x4C, 0, 4, 0},
+ {HDMI_LVDS_SEL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x7E, 7, 7, 0},
+ {VSP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x24, 5, 5, 1},
+ {HSP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x24, 4, 4, 1},
+ {HDMIIN_HSP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x61, 6, 6, 4},
+ {HDMIIN_VSP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x61, 5, 5, 4},
+ {HDMIIN_DEP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x61, 4, 4, 4},
+ {M1M0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x3D, 2, 3, 0},
+ {C1C0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x3D, 0, 1, 0},
+ {VIC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x40, 0, 5, 0},
+ {COPY, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x4B, 6, 6, 0},
+ {SCAN_EN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6C, 0, 0, 4},
+ {HAO_SCL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6A,0, 7, 0x6B, 5, 7, 4},
+ {VAO_SCL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6B,0, 4, 0x6C, 2, 7, 4},
+
+ {I2SPOL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1E, 7, 7, 0},
+ {I2S_SPDIFB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1E, 6, 6, 0},
+ {I2S_LENGTH, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1E, 2, 3, 0},
+ {I2SFMT, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1E, 0, 1, 0},
+ {UCLK, NOOP_INDEX, 0, 0, 0x0F,4, 5, 0x10,0, 7, 0x11, 0, 7 , 4},
+
+ {PCLK_NUM, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x28, 0, 7,0x29, 0, 7, 1},
+
+ {UCLKSEC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x12, 4, 4, 1},
+ {PLL1N1, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x55, 3, 5, 4},
+ {PLL1N2, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x55, 0, 2, 4},
+ {PLL1N3, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x56, 5, 7, 4},
+ {PLL3N8, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x13, 1, 2, 1},
+ {A2, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5E, 0, 7, 0},
+ {MCLK, NOOP_INDEX, 0, 0, 0x0F,2, 3, 0x12,0, 7, 0x13, 0, 7, 4},
+ {PLL2N5, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x12,0, 1, 0x13, 7, 7, 1},
+ {PLL2N54, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6E, 2, 2, 4},
+ {PLL2N53, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6E, 1, 1, 4},
+ {PLL2N6, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x69, 5, 6, 4},
+ {PLL2N7, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x69, 3, 4, 4},
+ {DIVXTAL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6E, 3, 7, 4},
+ {A1, 0x5A,0, 7, 0x5B,0, 7, 0x5C,0, 7, 0x5D, 0, 7, 0},
+ {A3, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x60, 0, 7, 4},
+ {TXPLL_FFD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x67, 7, 7, 4},
+ {DRI_PLL_N1, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0C, 3, 4, 1},
+ {DRI_PLL_N3, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0C, 1, 2, 1},
+ {UCLKOD_SEL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x61, 7, 7, 4},
+
+ {GCKSEL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x54, 6, 6, 4},
+ {TSTEN1, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x14, 6, 6, 1},
+
+ {LNSEL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x68, 1, 2, 0},
+ {DAT16_32B, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x74, 7, 7, 0},
+ {TRUE24, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x74, 3, 3, 0},
+ {TRUE_COM, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x74, 4, 4, 0},
+ {WRLEN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2D, 6, 7, 0},
+ {ROTATE, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2D, 4, 5, 0},
+ {HFLIP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 7, 7, 0},
+ {VFLIP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 6, 6, 0},
+ {DNSMPEN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x25, 6, 6, 0},
+ {HADWSPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x60,0, 7, 0x61, 0, 2, 0},
+ {FLTBP2, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x32, 7, 7, 0},
+ {FLTBP1, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x32, 6, 6, 0},
+ {BLK_H, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x64, 0, 6, 0},
+ {FBA_INC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6B,0, 7, 0x6C, 0, 3, 0},
+ {SFM, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6A, 0, 0, 0},
+ {THREN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6A, 2, 2, 0},
+ {THRRL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6D,0, 7, 0x6E, 0, 2, 0},
+ {WRFAST, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x6E, 3, 3, 0},
+ {CHG_HL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2F, 7, 7, 0},
+ {HINCA, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2A,0, 7, 0x2B, 0, 2, 4},
+ {HINCB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2C,0, 7, 0x2D, 0, 2, 4},
+ {VINCA, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E,0, 7, 0x2F, 0, 2, 4},
+ {VINCB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x30,0, 7, 0x31, 0, 2, 4},
+ {HDINCA, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x32,0, 7, 0x33, 0, 2, 4},
+ {HDINCB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x34,0, 7, 0x35, 0, 2, 4},
+ {HINC, NOOP_INDEX, 0, 0, 0x36,0, 4, 0x37,0, 7, 0x38, 0, 7, 4},
+ {VINC, NOOP_INDEX, 0, 0, 0x39,0, 7, 0x3A,0, 7, 0x3B, 0, 7, 4},
+ {HDINC, NOOP_INDEX, 0, 0, 0x3C,0, 7, 0x3D,0, 7, 0x3E, 0, 7, 4},
+ {VSMST, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x70, 6, 7, 0},
+ {MEMINIT, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0A, 7, 7, 0},
+ {STOP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0A, 4, 4, 0},
+
+ {HDMI_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 0, 0, 0},
+ {I2S_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 6, 6, 0},
+ {SPDIF_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 0, 0, 0},
+ {DRI_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 3, 3, 0},
+ {DRI_PD_SER, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x16, 0, 0, 1},
+ {DRI_PD_PLL, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x16, 3, 3, 1},
+ {DRI_PDDRI, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x08, 4, 7, 0},
+ {CEC_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 4, 4, 0},
+ {PD_DDC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0E, 7, 7, 1},
+
+ {LVDS_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0A, 3, 3, 0},
+ {RX_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x63, 4, 7, 4},
+ {RXPLL_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x64, 0, 0, 4},
+ {TXPLL_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x66, 1, 1, 4},
+ {TXDRV_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x11, 4, 4, 1},
+ {TXSER_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x1A, 4, 4, 1},
+
+ {VGA_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 2, 2, 0},
+ {PDDAC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x08, 1, 3, 0},
+ {DACSENCE, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x57, 1, 1, 4},
+ {GCKOFF, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 6, 6, 0},
+ {TV_BP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 5, 5, 0},
+ {PDPLL1, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 1, 1, 0},
+ {PDPLL0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x54, 4, 4, 4},
+
+ {ICEN0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x11, 7, 7, 1},
+
+ {PD_PROM, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0F, 7, 7, 1},
+ {PDMIO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 2, 2, 0},
+ {PDIO, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 5, 5, 0},
+ {HPD_PD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 7, 7, 0},
+ {SCLPD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 4, 4, 0},
+ {SDPD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x09, 3, 3, 0},
+ {MEMPD, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x0A, 5, 5, 0},
+ {AUDDAC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x5C, 2, 2, 4},
+
+ {CRYS_FREQ_SPP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0,0x1C, 0, 7, 0x1D, 0, 7, 0},
+ {I2SCK_SEC, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 2, 2, 1},
+ {SP_EN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x21, 7, 7, 1},
+ {HARD_SOFTB, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x58, 5, 5, 4},
+ {MULT_I2CEN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x4E, 0, 0, 1},
+ {RXPLL_REFDLY, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x66, 5, 7, 4},
+ {RXPLL_FBDLY, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x66, 2, 4, 4},
+ {VFMT, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2B, 0, 3, 0},
+
+ {DBP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x19, 6, 6, 0},
+ {CK_TVINV, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x07, 1, 1, 1},
+ {DISPON, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x08, 0, 0, 1},
+
+ {VP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x39,4, 7, 0x3B, 0, 7, 0},
+ {HP, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x39,0, 3, 0x3A, 0, 7, 0},
+
+ {TXTEN, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x2E, 0, 2, 0},
+ {ZRCTS, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, NOOP_INDEX, 0, 0, 0x24, 1, 1, 1},
+
+};
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
new file mode 100755
index 0000000..8e0c18d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
@@ -0,0 +1,125 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_reg_table.h
+* @version 1.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_REG_TABLE_H
+#define _CH7036_REG_TABLE_H
+
+#include "ch7036_typedef.h"
+
+typedef enum{
+ BASE_FLAG = 0,
+
+
+ HTI, VTI, HAI, VAI, HOI, VOI, HWI, VWI, RCLK,
+ DITHER_SEL1_SPP, DITHER_SEL0_SPP, HSYNCP_SPP, VSYNCP_SPP,
+ NP_INV0_SPP, NP_INV1_SPP, NP_INV2_SPP, NP_INV3_SPP, LVDS_IN_ORDER,
+
+
+ LVDS0_SEQ_SPP, LVDS1_SEQ_SPP, LVDS2_SEQ_SPP, LVDS3_SEQ_SPP, LVDSCLK_SEQ_SPP,
+ HSYNC_CNT_TH_SPP, PRBS_SET_SEL_SPP,
+ LVDS0_POL_SPP, LVDS1_POL_SPP, LVDS2_POL_SPP, LVDS3_POL_SPP, LVDSCLK_POL_SPP,
+
+
+ HTO, VTO, HAO, VAO, HOO_HDMI, VOO_HDMI, HWO_HDMI, VWO_HDMI,
+ HPO_I, VPO_I, DEPO_I, HPO_O, VPO_O, DEPO_O,
+
+
+ HD_DVIB, INTLC, HD_LV_POL, HD_LV_SEQ, HDMI_LVDS_SEL,
+ VSP, HSP, HDMIIN_HSP, HDMIIN_VSP, HDMIIN_DEP,
+ M1M0, C1C0, VIC,
+ COPY, SCAN_EN, HAO_SCL, VAO_SCL,
+
+
+ I2SPOL, I2S_SPDIFB, I2S_LENGTH, I2SFMT,
+ UCLK, PCLK_NUM,
+
+
+ UCLKSEC, PLL1N1, PLL1N2, PLL1N3, PLL3N8, A2, MCLK,
+ PLL2N5, PLL2N54, PLL2N53, PLL2N6, PLL2N7, DIVXTAL,
+ A1, A3, TXPLL_FFD, DRI_PLL_N1, DRI_PLL_N3, UCLKOD_SEL,
+ GCKSEL, TSTEN1,
+
+
+ LNSEL, DAT16_32B, TRUE24, TRUE_COM, WRLEN,
+ ROTATE, HFLIP, VFLIP,
+ DNSMPEN, HADWSPP, FLTBP2, FLTBP1, BLK_H,
+ FBA_INC, SFM, THREN, THRRL, WRFAST, CHG_HL,
+ HINCA, HINCB, VINCA, VINCB, HDINCA, HDINCB,
+ HINC, VINC, HDINC,
+ VSMST, MEMINIT, STOP,
+
+
+ HDMI_PD, I2S_PD, SPDIF_PD, DRI_PD, DRI_PD_SER,
+ DRI_PD_PLL, DRI_PDDRI, CEC_PD, PD_DDC,
+ LVDS_PD, RX_PD, RXPLL_PD, TXPLL_PD, TXDRV_PD, TXSER_PD,
+ VGA_PD, PDDAC, DACSENCE, GCKOFF,
+ TV_BP, PDPLL1, PDPLL0, ICEN0, PD_PROM, PDMIO, PDIO, HPD_PD,
+ SCLPD, SDPD, MEMPD, AUDDAC,
+
+
+ CRYS_FREQ_SPP, I2SCK_SEC, SP_EN, HARD_SOFTB, MULT_I2CEN, RXPLL_REFDLY,
+ RXPLL_FBDLY, VFMT,
+
+
+ DBP, CK_TVINV, DISPON,
+
+ VP, HP,
+
+ TXTEN,
+ ZRCTS,
+
+ MUL_ID_END,
+
+}MULTI_REG_ID;
+
+typedef struct{
+ MULTI_REG_ID RegId;
+ uint8 TopRegIndex;
+ uint8 TopStartBit;
+ uint8 TopEndBit;
+ uint8 HighRegIndex;
+ uint8 HighStartBit;
+ uint8 HighEndBit;
+ uint8 MiddleRegIndex;
+ uint8 MiddleStartBit;
+ uint8 MiddleEndBit;
+ uint8 LowRegIndex;
+ uint8 LowStartBit;
+ uint8 LowEndBit;
+ uint8 PageIndex;
+}MULTI_REG, *PMULTI_REG;
+
+extern MULTI_REG g_MultiRegTable[];
+
+//issue- 11/15/11- thua
+//Intel C compiler complained negative constant (-1) comparison to unsigned char for checked build verion
+//for free build, these warnings are treated as compiling error
+//solution:
+//define NOOP_REGINDEX as 2-complement of -1
+#define NOOP_INDEX 0xFF
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
new file mode 100755
index 0000000..57c987b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
@@ -0,0 +1,472 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file ch7036_typedef.h
+* @version 1.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef _CH7036_TYPEDEF_H
+#define _CH7036_TYPEDEF_H
+
+
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+
+
+typedef unsigned long long int uint64;
+
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+
+typedef signed long long int int64;
+
+
+
+
+
+
+
+typedef uint32 ch_bool;
+#define ch_true 1
+#define ch_false 0
+
+
+
+typedef struct{
+ uint16 ht;
+ uint16 ha;
+ uint16 ho;
+ uint16 hw;
+ uint16 vt;
+ uint16 va;
+ uint16 vo;
+ uint16 vw;
+ uint16 hz;
+ uint16 stype;
+
+}TIMING, *PTIMING;
+
+
+#define PIXEL_FMT_18BIT 0
+#define PIXEL_FMT_24BIT 1
+
+#define POL_HIGH 1
+#define POL_LOW 0
+#define POL_INVERT 1
+#define POL_NO_INV 0
+
+#define AUDIO_I2S 1
+#define AUDIO_SPDIF 0
+
+#define SCANTYPE_INTERLACED 0
+#define SCANTYPE_PROGRESSIVE 1
+#define TIMING_LIST_END 2
+
+typedef struct{
+
+ TIMING timing;
+ uint32 rx_clk_khz;
+ uint8 pixel_fmt;
+ uint8 hs_pol;
+ uint8 vs_pol;
+ uint8 de_pol;
+ uint8 data_ch_pol;
+ uint8 data_ch_invert;
+
+ uint8 audio_type;
+ uint8 i2s_pol;
+ uint8 i2s_len;
+ uint8 i2s_fmt;
+}INPUT_INFO, *PINPUT_INFO;
+
+
+
+
+#define LVDS_DATA0_SEL 0
+#define LVDS_DATA1_SEL 1
+#define LVDS_DATA2_SEL 2
+#define LVDS_DATA3_SEL 3
+#define LVDS_CLOCK_SEL 4
+
+
+#define LVDS_CHANNEL_SWAP_DEF (LVDS_DATA0_SEL << 0) | (LVDS_DATA1_SEL << 4) | (LVDS_DATA2_SEL << 8) | (LVDS_DATA3_SEL << 12) | (LVDS_CLOCK_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP1 (LVDS_DATA1_SEL << 0) | (LVDS_DATA2_SEL << 4) | (LVDS_DATA3_SEL << 8) | (LVDS_CLOCK_SEL << 12) | (LVDS_DATA0_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP2 (LVDS_DATA2_SEL << 0) | (LVDS_DATA3_SEL << 4) | (LVDS_CLOCK_SEL << 8) | (LVDS_DATA0_SEL << 12) | (LVDS_DATA1_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP3 (LVDS_DATA3_SEL << 0) | (LVDS_CLOCK_SEL << 4) | (LVDS_DATA0_SEL << 8) | (LVDS_DATA1_SEL << 12) | (LVDS_DATA2_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP4 (LVDS_CLOCK_SEL << 0) | (LVDS_DATA0_SEL << 4) | (LVDS_DATA1_SEL << 8) | (LVDS_DATA2_SEL << 12) | (LVDS_DATA3_SEL << 16)
+#define LVDS_CHANNAL_SWAP_OP5 (LVDS_DATA3_SEL << 0) | (LVDS_CLOCK_SEL << 4) | (LVDS_DATA2_SEL << 8) | (LVDS_DATA1_SEL << 12) | (LVDS_DATA0_SEL << 16)
+
+typedef struct{
+ uint32 channel_swap;
+ uint32 channel_pol;
+ uint32 pixel_fmt;
+}LVDS_FMT, *PLVDS_FMT;
+
+#define AS_RATIO_4_3 1
+#define AS_RATIO_16_9 2
+
+typedef struct{
+ uint8 is_dvi_mode;
+ uint8 format_index;
+ uint8 aspect_ratio;
+ uint8 channel_swap;
+ uint8 data_pol_invert;
+ uint8 hs_pol;
+ uint8 vs_pol;
+ uint8 protect_enable;
+}HDMI_FMT, *PHDMI_FMT;
+
+typedef struct{
+ uint8 channel_swap;
+ uint8 hs_pol;
+ uint8 vs_pol;
+ uint8 de_pol;
+}VGA_FMT, *PVGA_FMT;
+
+
+#define CHANNEL_LVDS (1 << 0)
+#define CHANNEL_HDMI (1 << 1)
+#define CHANNEL_VGA (1 << 2)
+#define CHANNEL_DVI (1 << 3)
+#define CHANNEL_LVDS_HDMI (CHANNEL_LVDS | CHANNEL_HDMI)
+#define CHANNEL_LVDS_VGA (CHANNEL_LVDS | CHANNEL_VGA)
+#define CHANNEL_LVDS_DVI (CHANNEL_LVDS | CHANNEL_DVI)
+#define CHANNEL_AUTO_DETECT 0x10
+
+
+#define CHANNEL_LVDS_HDMI_VGA_OFF 0x0000
+
+
+
+#define ROTATE_0 0
+#define ROTATE_NO 0
+#define ROTATE_90 1
+#define ROTATE_180 2
+#define ROTATE_270 3
+
+typedef struct{
+ uint32 channel;
+ LVDS_FMT lvds_fmt;
+ HDMI_FMT hdmi_fmt;
+ VGA_FMT vga_fmt;
+ TIMING timing;
+ uint32 uclk_khz;
+ uint8 ds_percent_h;
+ uint8 ds_percent_v;
+ uint8 rotate;
+ uint8 h_flip;
+ uint8 v_flip;
+ uint16 h_position;
+ uint16 v_position;
+}OUTPUT_INFO, *POUTPUT_INFO;
+
+
+#define HS_TOLERANCE_LEVEL0 0
+#define HS_TOLERANCE_LEVEL1 1
+#define HS_TOLERANCE_LEVEL2 3
+#define HS_TOLERANCE_LEVEL3 7
+
+#define RST_BIT_HSYNC 0
+#define RST_BIT_VSYNC 1
+
+#define MEM_CLK_FREQ_MAX 166000
+#define FBA_INC_MAX 3000
+
+#define THRRL_ADJUST_DEF 200
+
+#define THRRL_ADJUST_OP1 250
+#define THRRL_ADJUST_OP2 300
+
+typedef struct{
+ uint32 mclk_khz;
+
+ uint8 uclkod_sel;
+ uint8 dat16_32b;
+ uint8 true24;
+ uint8 true_com;
+
+ uint8 lvds_out_hs_tolerance;
+ uint8 lvds_out_reset_bit_sel;
+
+ uint8 dither_filter_enable;
+ uint8 hscale_ratio_gate;
+
+ uint8 scale_line_adjust;
+ uint8 text_enhancement;
+
+ uint8 pll_ref_dly;
+ uint8 pll_ref_fbdly;
+ uint8 lvds_txdrv_ctrl;
+
+ uint8 eye_bgtrim ;
+ uint8 eye_dacg;
+ uint8 eye_dri_demp;
+ uint8 eye_dri_pll_cp;
+ uint8 eye_dri_damp;
+ uint8 eye_dri_pll_rlf;
+ uint8 eye_rdac;
+
+ uint8 reset;
+ uint8 vga_enable;
+
+}PREFER_INFO, *PPREFER_INFO;
+
+
+
+typedef struct{
+ uint32 DeviceID;
+ INPUT_INFO* pInput_Info;
+ OUTPUT_INFO* pOutput_Info;
+ PREFER_INFO* pPrefer_Info;
+ void* pd_context;
+}DEV_CONTEXT, *PDEV_CONTEXT;
+
+typedef struct{
+ uint32 fmt_index;
+ uint32 clk_freq;
+ uint32 aspect;
+ TIMING timing;
+}OUT_FMT, *POUT_FMT;
+
+typedef enum hdmi{
+
+ OUT_HDMI_640x480P_59 = 0,
+ OUT_HDMI_640x480P_60,
+
+ OUT_HDMI_720x480P_59,
+ OUT_HDMI_720x480P_60,
+
+ OUT_HDMI_720x576P_50,
+
+ OUT_HDMI_1280x720P_59,
+ OUT_HDMI_1280x720P_60,
+
+ OUT_HDMI_1920x1080I_59,
+ OUT_HDMI_1920x1080I_60,
+
+ OUT_HDMI_1920x1080P_59,
+ OUT_HDMI_1920x1080P_60,
+
+// OUT_HDMI_720x576P_50, //2/2/12 grouped to downscaling modes < 13x7
+ OUT_HDMI_1280x720P_50,
+ OUT_HDMI_1920x1080I_50,
+
+ OUT_HDMI_1920x1080P_50,
+
+ OUT_HDMI_1920x1080P_23,
+ OUT_HDMI_1920x1080P_24,
+ OUT_HDMI_1920x1080P_25,
+ OUT_HDMI_1920x1080P_29,
+ OUT_HDMI_1920x1080P_30,
+
+ OUT_HDMI_1920x1080I_100,
+ OUT_HDMI_1280x720P_100,
+ OUT_HDMI_720x576P_100,
+
+ OUT_HDMI_1920x1080I_119,
+ OUT_HDMI_1920x1080I_120,
+
+ OUT_HDMI_1280x720P_119,
+ OUT_HDMI_1280x720P_120,
+
+ OUT_HDMI_720x480P_119,
+ OUT_HDMI_720x480P_120,
+
+ OUT_HDMI_720x576P_200,
+ OUT_HDMI_1280x720P_239,
+ OUT_HDMI_1280x720P_240,
+ OUT_HDMI_END,
+}HDMI_OUT_MODE;
+
+typedef enum dvi {
+
+ OUT_DVI_640x480_60 = 0,
+
+ OUT_DVI_640x480_72,
+ OUT_DVI_640x480_75,
+ OUT_DVI_720x400_70,
+
+ OUT_DVI_800x600_56,
+ OUT_DVI_800x600_60,
+ OUT_DVI_800x600_72,
+ OUT_DVI_800x600_75,
+
+ OUT_DVI_1024x768_60,
+ OUT_DVI_1024x768_70,
+ OUT_DVI_1024x768_75,
+
+ OUT_DVI_1152x864_60,
+ OUT_DVI_1280x720_60,
+ OUT_DVI_1280x800_60,
+ OUT_DVI_1280x960_60,
+ OUT_DVI_1280x1024_60,
+ OUT_DVI_1280x1024_75,
+ OUT_DVI_1360x768_60,
+ OUT_DVI_1366x768_60,
+
+ OUT_DVI_1400x1050_60,
+ OUT_DVI_1400x1050_75,
+
+
+ OUT_DVI_1440x900_60,
+ OUT_DVI_1440x1050_60,
+ OUT_DVI_1600x900_60,
+ OUT_DVI_1600x1200_60,
+ OUT_DVI_1680x1050_60,
+
+ OUT_DVI_1920x1080_60,
+
+ OUT_DVI_1920x1200_60,
+
+ OUT_DVI_END,
+} DVI_OUT_MODE;
+
+typedef enum crt{
+
+ OUT_CRT_640x400_85 = 0,
+
+ OUT_CRT_640x480_60,
+
+ OUT_CRT_640x480_72,
+ OUT_CRT_640x480_75,
+ OUT_CRT_640x480_85,
+
+ OUT_CRT_720x400_85,
+
+ OUT_CRT_800x600_56,
+
+
+ OUT_CRT_800x600_60,
+ OUT_CRT_800x600_72,
+ OUT_CRT_800x600_75,
+ OUT_CRT_800x600_85,
+
+ OUT_CRT_1024x768_60,
+ OUT_CRT_1024x768_70,
+ OUT_CRT_1024x768_75,
+ OUT_CRT_1024x768_85,
+
+
+
+ OUT_CRT_1152x864_75,
+
+ OUT_CRT_1280x768_60,
+ OUT_CRT_1280x768_75,
+ OUT_CRT_1280x768_85,
+
+ OUT_CRT_1280x960_60,
+ OUT_CRT_1280x960_85,
+
+ OUT_CRT_1280x1024_60,
+ OUT_CRT_1280x1024_75,
+ OUT_CRT_1280x1024_85,
+
+ OUT_CRT_1360x768_60,
+
+ OUT_CRT_1400x1050_60,
+ OUT_CRT_1400x1050_75,
+
+
+
+ OUT_CRT_1440x900_60,
+ OUT_CRT_1440x1050_60,
+
+ OUT_CRT_1600x900_60,
+ OUT_CRT_1600x1200_60,
+
+ OUT_CRT_1920x1080_60,
+
+
+
+ OUT_CRT_END,
+}CRT_OUT_MODE;
+
+#define MAX_ATTR_LIST_SIZE 32
+
+
+
+
+#define ERR_NO_ERROR 0
+
+#define ERR_DEVICE_PREPARE 100
+#define ERR_RESOLUTION_H_ODD 101
+#define ERR_RESOLUTION_V_ODD 102
+#define ERR_BANDWIDTH_OVERFLOW 103
+#define ERR_RESOLUTION_OVERFLOW 104
+#define ERR_DEVICE_NO_EXIST 105
+#define ERR_NO_SUPPORT_TRUE24 106
+#define ERR_NO_SUPPORT_TRUECOM 107
+#define ERR_ROTATION_WITH_VAI 108
+#define ERR_FLIP_WITH_VAI 109
+
+#define ERR_DEVICE_CONFIG 200
+#define ERR_ASPECT_RATIO_NOMATCH 201
+#define ERR_PLL1N2_WRONG 202
+#define ERR_PLL1N3_WRONG 203
+#define ERR_PLL1N1_WRONG 204
+#define ERR_PLL3N8_WRONG 205
+#define ERR_PLL2N5_WRONG 206
+#define ERR_PLL2N6_WRONG 207
+#define ERR_PLL2N7_WRONG 208
+#define ERR_DMXTAL_WRONG 209
+#define ERR_HDMI_CLOCK_NO_SUPPORT 210
+
+#define ERR_DEVICE_RUNNING 300
+#define ERR_CAL_INC_DIV_ZERO 301
+#define ERR_CAL_INC_NO_MATH 302
+
+
+
+typedef enum {
+ SS_POWER_ON_STATE,
+ SS_SUCCESS,
+ SS_NOT_SUPPORTED,
+ SS_INVALID_ARGUMENT,
+ SS_PENDING,
+ SS_TARGET_UNSPECIFIED,
+ SS_SCALING_UNSUPPORTED,
+
+ SS_MEM_ALLOC_ERR,
+
+
+ SS_UNSUCCESSFUL = 10,
+ SS_INVALID_RETURN,
+ SS_WRITE_FAILED,
+ SS_READ_FAILED,
+
+ SS_FIRMWARE_ERR,
+ SS_FIRMWARE_TIMEOUT,
+
+ SS_CRT_HPD_NOTCONNECTED,
+ SS_CRT_HPD_CONNECTED_TO_GRD,
+ SS_DISPLAY_CHOICE_NOT_ALLOWED,
+
+
+} ch7036_status_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
new file mode 100644
index 0000000..99949e8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
@@ -0,0 +1,73 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file config_.h
+* @version 1.2.3
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+
+#define T_LVDS_OPEN
+#define T_LVDS_INIT
+#define T_POST_SETMODE
+#define T_LVDS_CLOSE
+
+#define T_SET_TIMING
+
+#define T_PD_DISPLAY_LVDS_INT
+
+#define T_DEVICE_DETECTION
+#define T_RES_DEALLOC
+
+#define T_TEST_HW
+#define T_RESET
+
+
+#define T_HDMI_TIMING_TABLE
+#define T_VGA_TIMING_TABLE
+#define T_PANEL_NATIVE_DTD
+
+
+#define T_LH_POWER_ON_OFF
+
+#define T_CH7036_USE_LVDS_ATTR_TABLE
+
+#define T_CH7036_INIT_ATTR_TABLE
+
+
+#define T_CH7036_USE_FIRMWARE
+
+#define T_CH7036_EDID_DUMP
+#undef T_CH7036_EDID_DUMP
+
+#define T_SHOW_EDID_DISPLAY_ATTR
+#undef T_SHOW_EDID_DISPLAY_ATTR
+
+#define T_LINUX
+//#undef T_LINUX
+
+#define T_CONFIG_PLB
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car b/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
new file mode 100644
index 0000000..b7da904
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
@@ -0,0 +1,3362 @@
+unsigned char lhfm_array[]= {
+ 0x02,
+ 0x0D,
+ 0x14,
+ 0x02,
+ 0x0A,
+ 0xBC,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x02,
+ 0x09,
+ 0x83,
+ 0x75,
+ 0x50,
+ 0x66,
+ 0xE4,
+ 0xF5,
+ 0x26,
+ 0xF5,
+ 0x27,
+ 0xC2,
+ 0x01,
+ 0xF5,
+ 0x25,
+ 0xF5,
+ 0x28,
+ 0xFF,
+ 0x12,
+ 0x09,
+ 0xF4,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x3E,
+ 0xF8,
+ 0xE6,
+ 0xF5,
+ 0x4A,
+ 0x7B,
+ 0x02,
+ 0x7D,
+ 0x23,
+ 0xE4,
+ 0xFF,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xA8,
+ 0x50,
+ 0xE6,
+ 0x30,
+ 0xE0,
+ 0x03,
+ 0x43,
+ 0x28,
+ 0x01,
+ 0xE8,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0xFF,
+ 0x54,
+ 0x0E,
+ 0x60,
+ 0x03,
+ 0x43,
+ 0x28,
+ 0x02,
+ 0xEF,
+ 0x30,
+ 0xE0,
+ 0x03,
+ 0x43,
+ 0x28,
+ 0x04,
+ 0x75,
+ 0x4B,
+ 0x26,
+ 0xE4,
+ 0xF5,
+ 0x4F,
+ 0x7B,
+ 0x02,
+ 0xAD,
+ 0x4B,
+ 0xE4,
+ 0xFF,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x50,
+ 0x36,
+ 0x05,
+ 0x4B,
+ 0x05,
+ 0x4B,
+ 0xA8,
+ 0x50,
+ 0xE6,
+ 0xFF,
+ 0xB4,
+ 0x01,
+ 0x08,
+ 0xE8,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0x64,
+ 0x01,
+ 0x60,
+ 0x23,
+ 0xE5,
+ 0x50,
+ 0x04,
+ 0xF8,
+ 0x74,
+ 0xC0,
+ 0x56,
+ 0xF6,
+ 0xEF,
+ 0xB4,
+ 0x81,
+ 0x09,
+ 0xE5,
+ 0x50,
+ 0x04,
+ 0xF8,
+ 0x76,
+ 0x80,
+ 0x43,
+ 0x28,
+ 0x04,
+ 0xA8,
+ 0x50,
+ 0xE6,
+ 0xB4,
+ 0xA9,
+ 0x08,
+ 0xE8,
+ 0x04,
+ 0xF8,
+ 0x76,
+ 0x40,
+ 0x43,
+ 0x28,
+ 0x10,
+ 0x05,
+ 0x4F,
+ 0xE5,
+ 0x4F,
+ 0xC3,
+ 0x94,
+ 0x08,
+ 0x40,
+ 0xB6,
+ 0x7B,
+ 0x06,
+ 0x7D,
+ 0x38,
+ 0xE4,
+ 0xFF,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x40,
+ 0x03,
+ 0x02,
+ 0x01,
+ 0x30,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x02,
+ 0xF8,
+ 0xE6,
+ 0x54,
+ 0xF0,
+ 0xFF,
+ 0xE5,
+ 0x50,
+ 0x04,
+ 0xF8,
+ 0xA6,
+ 0x07,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x03,
+ 0xF8,
+ 0xE6,
+ 0xFF,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x02,
+ 0xF8,
+ 0xA6,
+ 0x07,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x05,
+ 0xF8,
+ 0xE6,
+ 0x54,
+ 0xF0,
+ 0xFF,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x03,
+ 0xF8,
+ 0xA6,
+ 0x07,
+ 0xE4,
+ 0xF5,
+ 0x4F,
+ 0xE4,
+ 0xF5,
+ 0x4C,
+ 0xE5,
+ 0x4F,
+ 0x75,
+ 0xF0,
+ 0x05,
+ 0xA4,
+ 0x24,
+ 0xBA,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x34,
+ 0x05,
+ 0xF5,
+ 0x83,
+ 0xE5,
+ 0x82,
+ 0x25,
+ 0x4C,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x35,
+ 0x83,
+ 0xF5,
+ 0x83,
+ 0xE4,
+ 0x93,
+ 0xFF,
+ 0xE5,
+ 0x50,
+ 0x25,
+ 0x4C,
+ 0xF8,
+ 0xE6,
+ 0xB5,
+ 0x07,
+ 0x07,
+ 0x05,
+ 0x4C,
+ 0xE5,
+ 0x4C,
+ 0xB4,
+ 0x04,
+ 0xD3,
+ 0xE5,
+ 0x4C,
+ 0xB4,
+ 0x04,
+ 0x13,
+ 0xE5,
+ 0x4F,
+ 0x75,
+ 0xF0,
+ 0x05,
+ 0xA4,
+ 0x24,
+ 0xBF,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x34,
+ 0x05,
+ 0xF5,
+ 0x83,
+ 0xE4,
+ 0x93,
+ 0x42,
+ 0x28,
+ 0x05,
+ 0x4F,
+ 0xE5,
+ 0x4F,
+ 0xB4,
+ 0x03,
+ 0xB1,
+ 0xD2,
+ 0x04,
+ 0xE5,
+ 0x4A,
+ 0x70,
+ 0x02,
+ 0xC3,
+ 0x22,
+ 0x75,
+ 0x4F,
+ 0x01,
+ 0xE5,
+ 0x4F,
+ 0xD3,
+ 0x95,
+ 0x4A,
+ 0x40,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0x61,
+ 0xE5,
+ 0x4F,
+ 0x30,
+ 0xE0,
+ 0x04,
+ 0x7F,
+ 0x80,
+ 0x80,
+ 0x02,
+ 0x7F,
+ 0x00,
+ 0x8F,
+ 0x51,
+ 0xAF,
+ 0x4F,
+ 0x12,
+ 0x09,
+ 0xF4,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xE5,
+ 0x4F,
+ 0xC3,
+ 0x13,
+ 0xF5,
+ 0x4E,
+ 0x7B,
+ 0x05,
+ 0xAD,
+ 0x51,
+ 0xFF,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xA8,
+ 0x50,
+ 0xE6,
+ 0x64,
+ 0x02,
+ 0x60,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0x5C,
+ 0xE8,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0x64,
+ 0x03,
+ 0x60,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0x5C,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x02,
+ 0xF8,
+ 0xE6,
+ 0xFF,
+ 0xD3,
+ 0x94,
+ 0x04,
+ 0x50,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0x5C,
+ 0x8F,
+ 0x4B,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0xF5,
+ 0x4C,
+ 0x75,
+ 0x4D,
+ 0x04,
+ 0xE5,
+ 0x4C,
+ 0x54,
+ 0xE0,
+ 0x64,
+ 0x60,
+ 0x70,
+ 0x37,
+ 0xE5,
+ 0x4D,
+ 0x7B,
+ 0x06,
+ 0x12,
+ 0x09,
+ 0x10,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xE5,
+ 0x50,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0x64,
+ 0x03,
+ 0x70,
+ 0x24,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x02,
+ 0xF8,
+ 0xE6,
+ 0x64,
+ 0x0C,
+ 0x70,
+ 0x1A,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x03,
+ 0xF8,
+ 0xE6,
+ 0x70,
+ 0x12,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x04,
+ 0xF8,
+ 0xE6,
+ 0xF5,
+ 0x26,
+ 0xE5,
+ 0x50,
+ 0x24,
+ 0x05,
+ 0xF8,
+ 0xE6,
+ 0xF5,
+ 0x27,
+ 0xD2,
+ 0x01,
+ 0xE5,
+ 0x4C,
+ 0x54,
+ 0xE0,
+ 0x64,
+ 0x40,
+ 0x70,
+ 0x59,
+ 0xE5,
+ 0x4C,
+ 0x54,
+ 0x1F,
+ 0xF5,
+ 0x52,
+ 0xE5,
+ 0x4D,
+ 0x25,
+ 0x51,
+ 0x04,
+ 0xFD,
+ 0xAB,
+ 0x52,
+ 0xAF,
+ 0x4E,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x50,
+ 0x64,
+ 0xE4,
+ 0xF5,
+ 0x53,
+ 0xE5,
+ 0x53,
+ 0xC3,
+ 0x95,
+ 0x52,
+ 0x50,
+ 0x3A,
+ 0xE4,
+ 0xF5,
+ 0x54,
+ 0xE5,
+ 0x50,
+ 0x25,
+ 0x53,
+ 0xF8,
+ 0xE6,
+ 0x54,
+ 0x7F,
+ 0xFF,
+ 0xE5,
+ 0x54,
+ 0x25,
+ 0xE0,
+ 0x24,
+ 0xA6,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x34,
+ 0x05,
+ 0xF5,
+ 0x83,
+ 0xE4,
+ 0x93,
+ 0xB5,
+ 0x07,
+ 0x11,
+ 0xE5,
+ 0x54,
+ 0x25,
+ 0xE0,
+ 0x24,
+ 0xA7,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x34,
+ 0x05,
+ 0xF5,
+ 0x83,
+ 0xE4,
+ 0x93,
+ 0x42,
+ 0x25,
+ 0x05,
+ 0x54,
+ 0xE5,
+ 0x54,
+ 0xB4,
+ 0x0A,
+ 0xCD,
+ 0x05,
+ 0x53,
+ 0x80,
+ 0xBF,
+ 0xE5,
+ 0x4C,
+ 0x54,
+ 0x1F,
+ 0x25,
+ 0x4D,
+ 0x04,
+ 0xF5,
+ 0x4D,
+ 0x7B,
+ 0x01,
+ 0x12,
+ 0x09,
+ 0x10,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xA8,
+ 0x50,
+ 0xE6,
+ 0xF5,
+ 0x4C,
+ 0xE5,
+ 0x4D,
+ 0xC3,
+ 0x95,
+ 0x4B,
+ 0x50,
+ 0x03,
+ 0x02,
+ 0x01,
+ 0x9C,
+ 0x05,
+ 0x4F,
+ 0x02,
+ 0x01,
+ 0x3B,
+ 0xA2,
+ 0x01,
+ 0x22,
+ 0xE4,
+ 0xF5,
+ 0xA8,
+ 0xF5,
+ 0xA0,
+ 0x75,
+ 0x90,
+ 0xC0,
+ 0xD2,
+ 0x8A,
+ 0xD2,
+ 0x88,
+ 0xD2,
+ 0xA8,
+ 0xD2,
+ 0xB8,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x4F,
+ 0x12,
+ 0x06,
+ 0x63,
+ 0xC2,
+ 0x0D,
+ 0xC2,
+ 0x04,
+ 0xC2,
+ 0x07,
+ 0xC2,
+ 0x0F,
+ 0xC2,
+ 0x02,
+ 0xE4,
+ 0xF5,
+ 0x47,
+ 0xD2,
+ 0x0A,
+ 0xD2,
+ 0x00,
+ 0xD2,
+ 0x09,
+ 0xD2,
+ 0x0C,
+ 0xC2,
+ 0x05,
+ 0xC2,
+ 0x08,
+ 0xC2,
+ 0x0B,
+ 0x7E,
+ 0x05,
+ 0x7F,
+ 0x7B,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x0C,
+ 0xB4,
+ 0x12,
+ 0x07,
+ 0x69,
+ 0x75,
+ 0x15,
+ 0x19,
+ 0x75,
+ 0x16,
+ 0x19,
+ 0x75,
+ 0x17,
+ 0x0C,
+ 0x12,
+ 0x0C,
+ 0x23,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x0C,
+ 0x92,
+ 0xE5,
+ 0x47,
+ 0x24,
+ 0xFF,
+ 0x92,
+ 0x05,
+ 0x7D,
+ 0xC0,
+ 0x7F,
+ 0x6E,
+ 0x12,
+ 0x06,
+ 0x75,
+ 0xAF,
+ 0x47,
+ 0x12,
+ 0x0B,
+ 0xF9,
+ 0xC2,
+ 0x06,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x4F,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x75,
+ 0x23,
+ 0x00,
+ 0x75,
+ 0x24,
+ 0x01,
+ 0xE4,
+ 0xF5,
+ 0x46,
+ 0x12,
+ 0x06,
+ 0xC6,
+ 0x30,
+ 0x0D,
+ 0x05,
+ 0x7F,
+ 0xFF,
+ 0x12,
+ 0x08,
+ 0x97,
+ 0x30,
+ 0x07,
+ 0x30,
+ 0x20,
+ 0x04,
+ 0x0C,
+ 0x7F,
+ 0x25,
+ 0x12,
+ 0x0C,
+ 0x77,
+ 0xEF,
+ 0x30,
+ 0xE4,
+ 0x03,
+ 0x12,
+ 0x00,
+ 0x0E,
+ 0x7B,
+ 0x12,
+ 0x7D,
+ 0x36,
+ 0x7C,
+ 0x00,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x0B,
+ 0x9F,
+ 0x92,
+ 0x10,
+ 0x85,
+ 0x3A,
+ 0x35,
+ 0x85,
+ 0x25,
+ 0x36,
+ 0x85,
+ 0x28,
+ 0x37,
+ 0xA2,
+ 0x10,
+ 0x92,
+ 0x13,
+ 0x7F,
+ 0x0F,
+ 0x12,
+ 0x0A,
+ 0xFF,
+ 0xC2,
+ 0x07,
+ 0xE5,
+ 0x16,
+ 0x60,
+ 0x03,
+ 0x02,
+ 0x03,
+ 0xA3,
+ 0x30,
+ 0x02,
+ 0x2D,
+ 0xC2,
+ 0xA8,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x0C,
+ 0x92,
+ 0xC2,
+ 0x02,
+ 0x30,
+ 0x05,
+ 0x0C,
+ 0xE5,
+ 0x47,
+ 0x60,
+ 0x04,
+ 0xD2,
+ 0x03,
+ 0x80,
+ 0x0C,
+ 0xAF,
+ 0x47,
+ 0x80,
+ 0x05,
+ 0xE5,
+ 0x47,
+ 0x60,
+ 0x04,
+ 0xFF,
+ 0x12,
+ 0x0B,
+ 0xF9,
+ 0xE5,
+ 0x47,
+ 0x24,
+ 0xFF,
+ 0x92,
+ 0x05,
+ 0x75,
+ 0x16,
+ 0x19,
+ 0xD2,
+ 0xA8,
+ 0x80,
+ 0x54,
+ 0x20,
+ 0x0B,
+ 0x1A,
+ 0x30,
+ 0x05,
+ 0x09,
+ 0x7F,
+ 0x09,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xEF,
+ 0x13,
+ 0x92,
+ 0x09,
+ 0xD2,
+ 0x0C,
+ 0x7F,
+ 0x08,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xEF,
+ 0x54,
+ 0x0E,
+ 0x70,
+ 0x02,
+ 0xC2,
+ 0x0C,
+ 0xE5,
+ 0x47,
+ 0x60,
+ 0x22,
+ 0x7F,
+ 0x09,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xEF,
+ 0x20,
+ 0xE0,
+ 0x19,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xEF,
+ 0x30,
+ 0xE2,
+ 0x10,
+ 0x7D,
+ 0x04,
+ 0x7F,
+ 0x5C,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x07,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x80,
+ 0x0E,
+ 0x7D,
+ 0x04,
+ 0x7F,
+ 0x5C,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x07,
+ 0x12,
+ 0x06,
+ 0x63,
+ 0x75,
+ 0x16,
+ 0x4B,
+ 0xE5,
+ 0x17,
+ 0x70,
+ 0x2C,
+ 0x7F,
+ 0x7F,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x54,
+ 0x04,
+ 0xF5,
+ 0x49,
+ 0x65,
+ 0x3D,
+ 0x60,
+ 0x1B,
+ 0x85,
+ 0x3D,
+ 0x49,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x0C,
+ 0xB4,
+ 0xE5,
+ 0x3D,
+ 0x65,
+ 0x49,
+ 0x60,
+ 0x0D,
+ 0xE5,
+ 0x3D,
+ 0x70,
+ 0x03,
+ 0xD3,
+ 0x80,
+ 0x01,
+ 0xC3,
+ 0x92,
+ 0x11,
+ 0x12,
+ 0x0B,
+ 0xCD,
+ 0x75,
+ 0x17,
+ 0x19,
+ 0x05,
+ 0x24,
+ 0xE5,
+ 0x24,
+ 0xAE,
+ 0x23,
+ 0x70,
+ 0x02,
+ 0x05,
+ 0x23,
+ 0x14,
+ 0x4E,
+ 0x60,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0xDA,
+ 0x75,
+ 0x13,
+ 0x07,
+ 0x75,
+ 0x14,
+ 0xD0,
+ 0x05,
+ 0x46,
+ 0xE5,
+ 0x46,
+ 0x20,
+ 0xE0,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0xDA,
+ 0x02,
+ 0x02,
+ 0xDA,
+ 0x02,
+ 0x05,
+ 0x4B,
+ 0xEC,
+ 0x5D,
+ 0x04,
+ 0x60,
+ 0x05,
+ 0xE8,
+ 0x59,
+ 0x04,
+ 0x70,
+ 0x03,
+ 0x02,
+ 0x05,
+ 0x41,
+ 0x12,
+ 0x05,
+ 0x0C,
+ 0x58,
+ 0x04,
+ 0x60,
+ 0xF6,
+ 0xEC,
+ 0x48,
+ 0x60,
+ 0xF2,
+ 0xEC,
+ 0x70,
+ 0x04,
+ 0xFD,
+ 0xFE,
+ 0xFF,
+ 0x22,
+ 0xC8,
+ 0x60,
+ 0xDB,
+ 0x24,
+ 0x81,
+ 0xC8,
+ 0x50,
+ 0x09,
+ 0xC3,
+ 0x98,
+ 0x60,
+ 0x02,
+ 0x50,
+ 0x06,
+ 0x02,
+ 0x05,
+ 0x48,
+ 0x98,
+ 0x50,
+ 0xCA,
+ 0xF5,
+ 0x82,
+ 0xE9,
+ 0x29,
+ 0x4B,
+ 0x4A,
+ 0x70,
+ 0x05,
+ 0xAB,
+ 0x82,
+ 0x02,
+ 0x05,
+ 0x37,
+ 0x75,
+ 0xF0,
+ 0x00,
+ 0x7C,
+ 0x1A,
+ 0x78,
+ 0x80,
+ 0xC3,
+ 0xEF,
+ 0x9B,
+ 0xEE,
+ 0x9A,
+ 0xED,
+ 0x99,
+ 0x40,
+ 0x0D,
+ 0xC3,
+ 0xEF,
+ 0x9B,
+ 0xFF,
+ 0xEE,
+ 0x9A,
+ 0xFE,
+ 0xED,
+ 0x99,
+ 0xFD,
+ 0xE8,
+ 0x42,
+ 0xF0,
+ 0xDC,
+ 0x23,
+ 0xAC,
+ 0xF0,
+ 0xD0,
+ 0xE0,
+ 0xFF,
+ 0xD0,
+ 0xE0,
+ 0xFE,
+ 0xD0,
+ 0xE0,
+ 0xFD,
+ 0xAB,
+ 0x82,
+ 0x20,
+ 0xE7,
+ 0x10,
+ 0x1B,
+ 0xEB,
+ 0x60,
+ 0xBA,
+ 0xEC,
+ 0x2C,
+ 0xFC,
+ 0xEF,
+ 0x33,
+ 0xFF,
+ 0xEE,
+ 0x33,
+ 0xFE,
+ 0xED,
+ 0x33,
+ 0xFD,
+ 0x02,
+ 0x05,
+ 0x23,
+ 0xE8,
+ 0x03,
+ 0xF8,
+ 0x30,
+ 0xE7,
+ 0x05,
+ 0xC0,
+ 0xF0,
+ 0x75,
+ 0xF0,
+ 0x00,
+ 0xEF,
+ 0x2F,
+ 0xFF,
+ 0xEE,
+ 0x33,
+ 0xFE,
+ 0xED,
+ 0x33,
+ 0xFD,
+ 0x40,
+ 0xB8,
+ 0x30,
+ 0xE7,
+ 0xC2,
+ 0x80,
+ 0xAA,
+ 0x75,
+ 0xF0,
+ 0x20,
+ 0x80,
+ 0x0E,
+ 0x75,
+ 0xF0,
+ 0x10,
+ 0x80,
+ 0x05,
+ 0x75,
+ 0xF0,
+ 0x08,
+ 0x7D,
+ 0x00,
+ 0x7E,
+ 0x00,
+ 0x7F,
+ 0x00,
+ 0x33,
+ 0x92,
+ 0xD5,
+ 0x30,
+ 0xD5,
+ 0x03,
+ 0x12,
+ 0x05,
+ 0x56,
+ 0xEC,
+ 0x33,
+ 0x40,
+ 0x10,
+ 0xEF,
+ 0x33,
+ 0xFF,
+ 0xEE,
+ 0x33,
+ 0xFE,
+ 0xED,
+ 0x33,
+ 0xFD,
+ 0xEC,
+ 0x33,
+ 0xFC,
+ 0xD5,
+ 0xF0,
+ 0xED,
+ 0x22,
+ 0xE5,
+ 0xF0,
+ 0x24,
+ 0x7E,
+ 0xA2,
+ 0xD5,
+ 0x13,
+ 0xCC,
+ 0x92,
+ 0xE7,
+ 0xCD,
+ 0xCE,
+ 0xFF,
+ 0x22,
+ 0xED,
+ 0xD2,
+ 0xE7,
+ 0xCD,
+ 0x33,
+ 0xEC,
+ 0x33,
+ 0x92,
+ 0xD5,
+ 0x24,
+ 0x81,
+ 0x40,
+ 0x06,
+ 0xE4,
+ 0xFF,
+ 0xFE,
+ 0xFD,
+ 0xFC,
+ 0x22,
+ 0xFC,
+ 0xE4,
+ 0xCF,
+ 0xCE,
+ 0xCD,
+ 0xCC,
+ 0x24,
+ 0xE0,
+ 0x50,
+ 0x11,
+ 0x74,
+ 0xFF,
+ 0x80,
+ 0xED,
+ 0xC3,
+ 0xCC,
+ 0x13,
+ 0xCC,
+ 0xCD,
+ 0x13,
+ 0xCD,
+ 0xCE,
+ 0x13,
+ 0xCE,
+ 0xCF,
+ 0x13,
+ 0xCF,
+ 0x04,
+ 0x70,
+ 0xF0,
+ 0x30,
+ 0xD5,
+ 0xDE,
+ 0x02,
+ 0x05,
+ 0x56,
+ 0xE9,
+ 0xD2,
+ 0xE7,
+ 0xC9,
+ 0x33,
+ 0xE8,
+ 0x33,
+ 0xF8,
+ 0x92,
+ 0xD5,
+ 0xED,
+ 0xD2,
+ 0xE7,
+ 0xCD,
+ 0x33,
+ 0xEC,
+ 0x33,
+ 0xFC,
+ 0x50,
+ 0x02,
+ 0xB2,
+ 0xD5,
+ 0x22,
+ 0xEC,
+ 0x30,
+ 0xE7,
+ 0x10,
+ 0x0F,
+ 0xBF,
+ 0x00,
+ 0x0C,
+ 0x0E,
+ 0xBE,
+ 0x00,
+ 0x08,
+ 0x0D,
+ 0xBD,
+ 0x00,
+ 0x04,
+ 0x0B,
+ 0xEB,
+ 0x60,
+ 0x14,
+ 0xA2,
+ 0xD5,
+ 0xEB,
+ 0x13,
+ 0xFC,
+ 0xED,
+ 0x92,
+ 0xE7,
+ 0xFD,
+ 0x22,
+ 0x74,
+ 0xFF,
+ 0xFC,
+ 0xFD,
+ 0xFE,
+ 0xFF,
+ 0x22,
+ 0xE4,
+ 0x80,
+ 0xF8,
+ 0xA2,
+ 0xD5,
+ 0x74,
+ 0xFF,
+ 0x13,
+ 0xFC,
+ 0x7D,
+ 0x80,
+ 0xE4,
+ 0x80,
+ 0xEF,
+ 0xC3,
+ 0xE4,
+ 0x9F,
+ 0xFF,
+ 0xE4,
+ 0x9E,
+ 0xFE,
+ 0xE4,
+ 0x9D,
+ 0xFD,
+ 0xE4,
+ 0x9C,
+ 0xFC,
+ 0x22,
+ 0x26,
+ 0x27,
+ 0x42,
+ 0x43,
+ 0x44,
+ 0x45,
+ 0x46,
+ 0x47,
+ 0x6A,
+ 0x51,
+ 0x52,
+ 0x53,
+ 0x57,
+ 0x58,
+ 0x59,
+ 0x5A,
+ 0x07,
+ 0x01,
+ 0x2B,
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x00,
+ 0x14,
+ 0x5A,
+ 0x00,
+ 0x20,
+ 0x07,
+ 0x10,
+ 0x11,
+ 0x0E,
+ 0x80,
+ 0x14,
+ 0x59,
+ 0xE0,
+ 0x24,
+ 0x59,
+ 0x60,
+ 0x10,
+ 0x19,
+ 0x04,
+ 0x00,
+ 0x1C,
+ 0x69,
+ 0x00,
+ 0x1D,
+ 0x78,
+ 0x04,
+ 0x76,
+ 0x00,
+ 0x04,
+ 0x77,
+ 0x20,
+ 0x04,
+ 0x75,
+ 0x08,
+ 0x14,
+ 0x52,
+ 0x10,
+ 0x23,
+ 0x10,
+ 0x01,
+ 0x13,
+ 0x0F,
+ 0x20,
+ 0xF0,
+ 0x10,
+ 0x80,
+ 0x1F,
+ 0x40,
+ 0x04,
+ 0x20,
+ 0x13,
+ 0x10,
+ 0x05,
+ 0x08,
+ 0x14,
+ 0x04,
+ 0x03,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x12,
+ 0x01,
+ 0x11,
+ 0x01,
+ 0x00,
+ 0x50,
+ 0x00,
+ 0x40,
+ 0x04,
+ 0x66,
+ 0x50,
+ 0x00,
+ 0x30,
+ 0x08,
+ 0x40,
+ 0x60,
+ 0xB0,
+ 0x40,
+ 0x10,
+ 0x20,
+ 0x09,
+ 0x01,
+ 0x20,
+ 0x08,
+ 0xF0,
+ 0x20,
+ 0x07,
+ 0x19,
+ 0x21,
+ 0x0D,
+ 0x80,
+ 0x21,
+ 0x16,
+ 0x01,
+ 0xF0,
+ 0x10,
+ 0x08,
+ 0x0E,
+ 0x10,
+ 0x09,
+ 0x04,
+ 0xF0,
+ 0x20,
+ 0x08,
+ 0x0E,
+ 0x20,
+ 0x09,
+ 0x04,
+ 0xF0,
+ 0x20,
+ 0x09,
+ 0x5D,
+ 0x20,
+ 0x08,
+ 0xFE,
+ 0x20,
+ 0x07,
+ 0x1D,
+ 0x20,
+ 0x0A,
+ 0x20,
+ 0x20,
+ 0x07,
+ 0x02,
+ 0x24,
+ 0x54,
+ 0x10,
+ 0x21,
+ 0x11,
+ 0x80,
+ 0x10,
+ 0x0A,
+ 0x04,
+ 0xF0,
+ 0x11,
+ 0x11,
+ 0x80,
+ 0x10,
+ 0x07,
+ 0x02,
+ 0x14,
+ 0x54,
+ 0x10,
+ 0x10,
+ 0x07,
+ 0x1D,
+ 0x10,
+ 0x0A,
+ 0x20,
+ 0x11,
+ 0x16,
+ 0x01,
+ 0x11,
+ 0x0D,
+ 0x80,
+ 0x10,
+ 0x08,
+ 0xF0,
+ 0x10,
+ 0x09,
+ 0x5D,
+ 0x14,
+ 0x52,
+ 0x01,
+ 0x24,
+ 0x52,
+ 0x01,
+ 0xF0,
+ 0x7B,
+ 0x00,
+ 0x80,
+ 0x0A,
+ 0x7B,
+ 0x01,
+ 0x80,
+ 0x06,
+ 0x7B,
+ 0x03,
+ 0x80,
+ 0x02,
+ 0x7B,
+ 0x04,
+ 0x7C,
+ 0x00,
+ 0x80,
+ 0x00,
+ 0x12,
+ 0x06,
+ 0x42,
+ 0xE2,
+ 0x5C,
+ 0x4D,
+ 0xF2,
+ 0x78,
+ 0x03,
+ 0xEB,
+ 0xF2,
+ 0xD2,
+ 0xAF,
+ 0x22,
+ 0xC2,
+ 0xAF,
+ 0x78,
+ 0x83,
+ 0xE2,
+ 0xCB,
+ 0xF2,
+ 0x74,
+ 0x80,
+ 0x2F,
+ 0xF8,
+ 0x22,
+ 0x7B,
+ 0x00,
+ 0x80,
+ 0x0A,
+ 0x7B,
+ 0x01,
+ 0x80,
+ 0x06,
+ 0x7B,
+ 0x03,
+ 0x80,
+ 0x02,
+ 0x7B,
+ 0x04,
+ 0xED,
+ 0xF4,
+ 0xFC,
+ 0x7D,
+ 0x00,
+ 0x80,
+ 0xD1,
+ 0x7B,
+ 0x00,
+ 0x80,
+ 0x0A,
+ 0x7B,
+ 0x01,
+ 0x80,
+ 0x06,
+ 0x7B,
+ 0x03,
+ 0x80,
+ 0x02,
+ 0x7B,
+ 0x04,
+ 0x7C,
+ 0xFF,
+ 0x80,
+ 0xBF,
+ 0x7B,
+ 0x03,
+ 0x80,
+ 0x02,
+ 0x7B,
+ 0x04,
+ 0x12,
+ 0x06,
+ 0x42,
+ 0xED,
+ 0xF4,
+ 0xFF,
+ 0xE2,
+ 0x5F,
+ 0xF2,
+ 0x4D,
+ 0xF2,
+ 0x5F,
+ 0xF2,
+ 0x80,
+ 0xB1,
+ 0x8E,
+ 0x83,
+ 0x8F,
+ 0x82,
+ 0xE4,
+ 0x93,
+ 0xA3,
+ 0xFB,
+ 0x54,
+ 0x0F,
+ 0xCB,
+ 0x54,
+ 0xF0,
+ 0xB4,
+ 0xF0,
+ 0x01,
+ 0x22,
+ 0xFD,
+ 0xE4,
+ 0x93,
+ 0xA3,
+ 0xFF,
+ 0xE4,
+ 0x93,
+ 0xA3,
+ 0xCD,
+ 0xB4,
+ 0x00,
+ 0x05,
+ 0x12,
+ 0x06,
+ 0x30,
+ 0x80,
+ 0xE2,
+ 0xB4,
+ 0x10,
+ 0x05,
+ 0x12,
+ 0x06,
+ 0x5C,
+ 0x80,
+ 0xDA,
+ 0xB4,
+ 0x20,
+ 0x05,
+ 0x12,
+ 0x06,
+ 0x71,
+ 0x80,
+ 0xD2,
+ 0xB4,
+ 0x30,
+ 0x05,
+ 0x12,
+ 0x06,
+ 0x7B,
+ 0x80,
+ 0xCA,
+ 0x80,
+ 0xC8,
+ 0xD2,
+ 0x11,
+ 0xD2,
+ 0x12,
+ 0x30,
+ 0x06,
+ 0x03,
+ 0x02,
+ 0x07,
+ 0x66,
+ 0x7F,
+ 0x4F,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0x8F,
+ 0x4A,
+ 0xE5,
+ 0x4A,
+ 0x20,
+ 0xE6,
+ 0x03,
+ 0x02,
+ 0x07,
+ 0x66,
+ 0xD2,
+ 0x06,
+ 0x53,
+ 0x4A,
+ 0x3F,
+ 0xE5,
+ 0x4A,
+ 0x24,
+ 0xFD,
+ 0x60,
+ 0x12,
+ 0x24,
+ 0xFD,
+ 0x60,
+ 0x14,
+ 0x24,
+ 0xE7,
+ 0x60,
+ 0x2E,
+ 0x24,
+ 0x1E,
+ 0x70,
+ 0x5F,
+ 0xD2,
+ 0x0D,
+ 0xC2,
+ 0x11,
+ 0x80,
+ 0x5E,
+ 0xD2,
+ 0x07,
+ 0xC2,
+ 0x11,
+ 0x80,
+ 0x58,
+ 0x30,
+ 0x0A,
+ 0x04,
+ 0x7F,
+ 0x80,
+ 0x80,
+ 0x02,
+ 0x7F,
+ 0x00,
+ 0x8F,
+ 0x29,
+ 0x7F,
+ 0x25,
+ 0x12,
+ 0x0C,
+ 0x77,
+ 0xEF,
+ 0x30,
+ 0xE4,
+ 0x03,
+ 0x43,
+ 0x29,
+ 0x01,
+ 0xC2,
+ 0x0A,
+ 0x75,
+ 0x4A,
+ 0x01,
+ 0x80,
+ 0x3A,
+ 0x75,
+ 0x4B,
+ 0x05,
+ 0x75,
+ 0x4C,
+ 0x74,
+ 0xE4,
+ 0xFF,
+ 0xE5,
+ 0x4C,
+ 0x2F,
+ 0xF5,
+ 0x82,
+ 0xE4,
+ 0x35,
+ 0x4B,
+ 0xF5,
+ 0x83,
+ 0xE4,
+ 0x93,
+ 0xFE,
+ 0x74,
+ 0x29,
+ 0x2F,
+ 0xF8,
+ 0xA6,
+ 0x06,
+ 0x0F,
+ 0xBF,
+ 0x07,
+ 0xE9,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0x8F,
+ 0x2C,
+ 0x7F,
+ 0x51,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x54,
+ 0x0F,
+ 0xF5,
+ 0x2D,
+ 0x75,
+ 0x4A,
+ 0x07,
+ 0x80,
+ 0x05,
+ 0xE4,
+ 0xF5,
+ 0x4A,
+ 0xC2,
+ 0x12,
+ 0x30,
+ 0x11,
+ 0x09,
+ 0xA2,
+ 0x12,
+ 0x92,
+ 0x13,
+ 0xAF,
+ 0x4A,
+ 0x12,
+ 0x0A,
+ 0xFF,
+ 0xA2,
+ 0x06,
+ 0x22,
+ 0xC2,
+ 0x96,
+ 0xD2,
+ 0x97,
+ 0xD2,
+ 0x96,
+ 0x22,
+ 0x22,
+ 0xC2,
+ 0x97,
+ 0xD2,
+ 0x96,
+ 0x74,
+ 0x28,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xD2,
+ 0x97,
+ 0x74,
+ 0x1E,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0x22,
+ 0xC2,
+ 0x97,
+ 0xD2,
+ 0x97,
+ 0x74,
+ 0x1E,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xD2,
+ 0x96,
+ 0x74,
+ 0x28,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0x22,
+ 0xD2,
+ 0x97,
+ 0xD2,
+ 0x96,
+ 0x74,
+ 0x28,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xC2,
+ 0x97,
+ 0x74,
+ 0x1E,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xC2,
+ 0x96,
+ 0x74,
+ 0x1E,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0x22,
+ 0xEF,
+ 0x7E,
+ 0x08,
+ 0x33,
+ 0xC0,
+ 0xE0,
+ 0x40,
+ 0x04,
+ 0xC2,
+ 0x97,
+ 0x80,
+ 0x02,
+ 0xD2,
+ 0x97,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xD2,
+ 0x96,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xC2,
+ 0x96,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xD0,
+ 0xE0,
+ 0xDE,
+ 0xD8,
+ 0xD2,
+ 0x97,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xD2,
+ 0x96,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xA2,
+ 0x97,
+ 0xE4,
+ 0x92,
+ 0xE0,
+ 0xFE,
+ 0xC2,
+ 0x96,
+ 0x74,
+ 0x11,
+ 0x00,
+ 0x00,
+ 0xD5,
+ 0xE0,
+ 0xFB,
+ 0xEE,
+ 0x22,
+ 0x8F,
+ 0x5E,
+ 0x8D,
+ 0x5F,
+ 0x7F,
+ 0x5A,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x54,
+ 0x80,
+ 0xF5,
+ 0x62,
+ 0xE5,
+ 0x5E,
+ 0xB4,
+ 0x01,
+ 0x04,
+ 0x7F,
+ 0x40,
+ 0x80,
+ 0x02,
+ 0x7F,
+ 0x00,
+ 0x8F,
+ 0x60,
+ 0x43,
+ 0x60,
+ 0x80,
+ 0xAD,
+ 0x60,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xE5,
+ 0x60,
+ 0x44,
+ 0x20,
+ 0xFD,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xAD,
+ 0x60,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0x7F,
+ 0x0E,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x20,
+ 0xE7,
+ 0x4E,
+ 0x7F,
+ 0x5A,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x54,
+ 0x80,
+ 0x65,
+ 0x62,
+ 0x60,
+ 0x03,
+ 0x7F,
+ 0xFF,
+ 0x22,
+ 0x7F,
+ 0x0E,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x30,
+ 0xE6,
+ 0x03,
+ 0x7F,
+ 0x01,
+ 0x22,
+ 0x85,
+ 0x60,
+ 0x61,
+ 0x7F,
+ 0x0C,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0x8F,
+ 0x60,
+ 0xE5,
+ 0x61,
+ 0x65,
+ 0x60,
+ 0x60,
+ 0x04,
+ 0x7F,
+ 0x01,
+ 0x80,
+ 0x02,
+ 0x7F,
+ 0x00,
+ 0xE5,
+ 0x60,
+ 0x60,
+ 0x04,
+ 0x7E,
+ 0x01,
+ 0x80,
+ 0x02,
+ 0x7E,
+ 0x00,
+ 0xEE,
+ 0x5F,
+ 0x60,
+ 0xB8,
+ 0x7F,
+ 0x0D,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xE5,
+ 0x60,
+ 0x14,
+ 0x25,
+ 0x5F,
+ 0xF8,
+ 0xA6,
+ 0x07,
+ 0x80,
+ 0xA9,
+ 0x7F,
+ 0x00,
+ 0x22,
+ 0xAD,
+ 0x07,
+ 0x8D,
+ 0x4A,
+ 0xBD,
+ 0xFF,
+ 0x07,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xAD,
+ 0x07,
+ 0xED,
+ 0x54,
+ 0x80,
+ 0xFF,
+ 0x53,
+ 0x05,
+ 0x7F,
+ 0xED,
+ 0xC4,
+ 0x54,
+ 0x0F,
+ 0xFE,
+ 0xED,
+ 0x54,
+ 0x0F,
+ 0xC4,
+ 0x54,
+ 0xF0,
+ 0xFD,
+ 0xEF,
+ 0x4E,
+ 0xFF,
+ 0x7B,
+ 0x10,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x92,
+ 0x11,
+ 0xAD,
+ 0x4A,
+ 0x7F,
+ 0x66,
+ 0xE4,
+ 0xF5,
+ 0x4A,
+ 0x30,
+ 0x11,
+ 0x08,
+ 0xEF,
+ 0x25,
+ 0x4A,
+ 0xF8,
+ 0xE6,
+ 0xFE,
+ 0x80,
+ 0x02,
+ 0x7E,
+ 0x00,
+ 0x74,
+ 0x29,
+ 0x25,
+ 0x4A,
+ 0xF8,
+ 0xA6,
+ 0x06,
+ 0x05,
+ 0x4A,
+ 0xE5,
+ 0x4A,
+ 0xB4,
+ 0x10,
+ 0xE5,
+ 0xED,
+ 0xF4,
+ 0x70,
+ 0x25,
+ 0xA2,
+ 0x11,
+ 0x92,
+ 0x13,
+ 0x7F,
+ 0x10,
+ 0x12,
+ 0x0A,
+ 0xFF,
+ 0xC2,
+ 0x0D,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x4F,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x30,
+ 0x11,
+ 0x09,
+ 0x7D,
+ 0x80,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x80,
+ 0x07,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x06,
+ 0x63,
+ 0xA2,
+ 0x11,
+ 0x22,
+ 0x25,
+ 0x51,
+ 0xFD,
+ 0xAF,
+ 0x4E,
+ 0x8F,
+ 0x59,
+ 0x8D,
+ 0x5A,
+ 0x8B,
+ 0x5B,
+ 0x75,
+ 0x5C,
+ 0x03,
+ 0xE5,
+ 0x59,
+ 0x30,
+ 0xE7,
+ 0x04,
+ 0x7F,
+ 0x01,
+ 0x80,
+ 0x02,
+ 0x7F,
+ 0x00,
+ 0x8F,
+ 0x5D,
+ 0x53,
+ 0x59,
+ 0x7F,
+ 0xAF,
+ 0x5C,
+ 0x15,
+ 0x5C,
+ 0xEF,
+ 0x60,
+ 0x4C,
+ 0xE5,
+ 0x5D,
+ 0x70,
+ 0x1D,
+ 0xE5,
+ 0x59,
+ 0xD3,
+ 0x94,
+ 0x00,
+ 0x40,
+ 0x16,
+ 0x12,
+ 0x07,
+ 0x70,
+ 0x12,
+ 0x07,
+ 0x9B,
+ 0x7F,
+ 0x60,
+ 0x12,
+ 0x07,
+ 0xB9,
+ 0xAF,
+ 0x59,
+ 0x12,
+ 0x07,
+ 0xB9,
+ 0x12,
+ 0x07,
+ 0x86,
+ 0x12,
+ 0x07,
+ 0x70,
+ 0xE5,
+ 0x5D,
+ 0x60,
+ 0x0D,
+ 0xE5,
+ 0x5A,
+ 0xFD,
+ 0x7C,
+ 0x00,
+ 0xAB,
+ 0x5B,
+ 0x7F,
+ 0x50,
+ 0x7E,
+ 0x02,
+ 0x80,
+ 0x0B,
+ 0xE5,
+ 0x5A,
+ 0xFD,
+ 0x7C,
+ 0x00,
+ 0xAB,
+ 0x5B,
+ 0x7F,
+ 0x50,
+ 0x7E,
+ 0x00,
+ 0x12,
+ 0x0A,
+ 0x61,
+ 0x7D,
+ 0x66,
+ 0xE4,
+ 0xFF,
+ 0x12,
+ 0x08,
+ 0x07,
+ 0xEF,
+ 0x70,
+ 0xAF,
+ 0xD3,
+ 0x22,
+ 0xC3,
+ 0x22,
+ 0xC0,
+ 0xE0,
+ 0xC0,
+ 0xD0,
+ 0xC2,
+ 0x8C,
+ 0x75,
+ 0x8A,
+ 0x40,
+ 0x75,
+ 0x8C,
+ 0x7C,
+ 0xD2,
+ 0x8C,
+ 0x05,
+ 0x18,
+ 0xE5,
+ 0x18,
+ 0x70,
+ 0x19,
+ 0x05,
+ 0x10,
+ 0xE5,
+ 0x10,
+ 0xD3,
+ 0x94,
+ 0x02,
+ 0x40,
+ 0x05,
+ 0x75,
+ 0x10,
+ 0x00,
+ 0xD2,
+ 0x0E,
+ 0xE5,
+ 0x10,
+ 0xB4,
+ 0x01,
+ 0x03,
+ 0xD3,
+ 0x80,
+ 0x01,
+ 0xC3,
+ 0x92,
+ 0x03,
+ 0xE5,
+ 0x11,
+ 0x60,
+ 0x02,
+ 0x15,
+ 0x11,
+ 0xE5,
+ 0x12,
+ 0x60,
+ 0x02,
+ 0x15,
+ 0x12,
+ 0xE5,
+ 0x15,
+ 0x60,
+ 0x02,
+ 0x15,
+ 0x15,
+ 0xE5,
+ 0x16,
+ 0x60,
+ 0x02,
+ 0x15,
+ 0x16,
+ 0xE5,
+ 0x17,
+ 0x60,
+ 0x02,
+ 0x15,
+ 0x17,
+ 0xE5,
+ 0x14,
+ 0x45,
+ 0x13,
+ 0x60,
+ 0x0A,
+ 0xE5,
+ 0x14,
+ 0x15,
+ 0x14,
+ 0x70,
+ 0x0C,
+ 0x15,
+ 0x13,
+ 0x80,
+ 0x08,
+ 0xC2,
+ 0xAF,
+ 0x12,
+ 0x0C,
+ 0x91,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x74,
+ 0x81,
+ 0xB5,
+ 0x81,
+ 0x00,
+ 0x40,
+ 0x02,
+ 0x80,
+ 0xEF,
+ 0xD0,
+ 0xD0,
+ 0xD0,
+ 0xE0,
+ 0x32,
+ 0x8F,
+ 0x55,
+ 0x75,
+ 0x58,
+ 0x66,
+ 0xE4,
+ 0xF5,
+ 0x56,
+ 0xE5,
+ 0x55,
+ 0xC3,
+ 0x13,
+ 0xFF,
+ 0xE5,
+ 0x55,
+ 0x30,
+ 0xE0,
+ 0x04,
+ 0x7D,
+ 0x80,
+ 0x80,
+ 0x02,
+ 0x7D,
+ 0x00,
+ 0x7B,
+ 0x40,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xE4,
+ 0xF5,
+ 0x57,
+ 0xE5,
+ 0x58,
+ 0x25,
+ 0x57,
+ 0xF8,
+ 0xE6,
+ 0x25,
+ 0x56,
+ 0xF5,
+ 0x56,
+ 0x05,
+ 0x57,
+ 0xE5,
+ 0x57,
+ 0xB4,
+ 0x40,
+ 0xEF,
+ 0xE5,
+ 0x55,
+ 0xC3,
+ 0x13,
+ 0xFF,
+ 0xE5,
+ 0x55,
+ 0x30,
+ 0xE0,
+ 0x04,
+ 0x7E,
+ 0x80,
+ 0x80,
+ 0x02,
+ 0x7E,
+ 0x00,
+ 0xEE,
+ 0x24,
+ 0x40,
+ 0xFD,
+ 0x7B,
+ 0x40,
+ 0x12,
+ 0x09,
+ 0x15,
+ 0x40,
+ 0x01,
+ 0x22,
+ 0xE4,
+ 0xF5,
+ 0x57,
+ 0xE5,
+ 0x58,
+ 0x25,
+ 0x57,
+ 0xF8,
+ 0xE6,
+ 0x25,
+ 0x56,
+ 0xF5,
+ 0x56,
+ 0x05,
+ 0x57,
+ 0xE5,
+ 0x57,
+ 0xB4,
+ 0x40,
+ 0xEF,
+ 0xE5,
+ 0x56,
+ 0x70,
+ 0x03,
+ 0xD3,
+ 0x80,
+ 0x01,
+ 0xC3,
+ 0x22,
+ 0x8E,
+ 0x5E,
+ 0x8F,
+ 0x5F,
+ 0x8C,
+ 0x60,
+ 0x8D,
+ 0x61,
+ 0x8B,
+ 0x62,
+ 0xE5,
+ 0x5E,
+ 0xF5,
+ 0x63,
+ 0xEF,
+ 0xF5,
+ 0x64,
+ 0xE5,
+ 0x63,
+ 0x7D,
+ 0x80,
+ 0x7F,
+ 0x5A,
+ 0x30,
+ 0xE1,
+ 0x05,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x80,
+ 0x03,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x53,
+ 0x63,
+ 0x01,
+ 0xE5,
+ 0x63,
+ 0x70,
+ 0x0B,
+ 0xE5,
+ 0x60,
+ 0x25,
+ 0x64,
+ 0xF5,
+ 0x64,
+ 0xE4,
+ 0xF5,
+ 0x65,
+ 0x80,
+ 0x04,
+ 0xE5,
+ 0x60,
+ 0xF5,
+ 0x65,
+ 0xAD,
+ 0x64,
+ 0x7F,
+ 0x28,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xAD,
+ 0x65,
+ 0x7F,
+ 0x40,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xE5,
+ 0x61,
+ 0xF5,
+ 0x65,
+ 0xAD,
+ 0x65,
+ 0x7F,
+ 0x29,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xAD,
+ 0x62,
+ 0x7F,
+ 0x08,
+ 0x12,
+ 0x06,
+ 0x2E,
+ 0xAF,
+ 0x63,
+ 0x22,
+ 0xC0,
+ 0xE0,
+ 0xC0,
+ 0xF0,
+ 0xC0,
+ 0x83,
+ 0xC0,
+ 0x82,
+ 0xC0,
+ 0xD0,
+ 0x75,
+ 0xD0,
+ 0x08,
+ 0x7F,
+ 0x25,
+ 0x12,
+ 0x0C,
+ 0x77,
+ 0xEF,
+ 0x54,
+ 0x10,
+ 0xF5,
+ 0x48,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x6E,
+ 0x12,
+ 0x06,
+ 0x75,
+ 0x30,
+ 0x00,
+ 0x17,
+ 0xE5,
+ 0x48,
+ 0x65,
+ 0x47,
+ 0x60,
+ 0x11,
+ 0x85,
+ 0x48,
+ 0x47,
+ 0xD2,
+ 0x02,
+ 0xD2,
+ 0x0A,
+ 0xE5,
+ 0x16,
+ 0xD3,
+ 0x94,
+ 0x03,
+ 0x40,
+ 0x03,
+ 0x75,
+ 0x16,
+ 0x03,
+ 0xD0,
+ 0xD0,
+ 0xD0,
+ 0x82,
+ 0xD0,
+ 0x83,
+ 0xD0,
+ 0xF0,
+ 0xD0,
+ 0xE0,
+ 0x32,
+ 0x8F,
+ 0x4D,
+ 0xE4,
+ 0xF5,
+ 0x4E,
+ 0xE5,
+ 0x4E,
+ 0xC3,
+ 0x95,
+ 0x4D,
+ 0x50,
+ 0x15,
+ 0xE5,
+ 0x4E,
+ 0x90,
+ 0x05,
+ 0x64,
+ 0x93,
+ 0xFF,
+ 0x74,
+ 0x29,
+ 0x25,
+ 0x4E,
+ 0xF8,
+ 0xE6,
+ 0xFD,
+ 0x12,
+ 0x06,
+ 0x26,
+ 0x05,
+ 0x4E,
+ 0x80,
+ 0xE4,
+ 0x20,
+ 0x13,
+ 0x03,
+ 0x43,
+ 0x4D,
+ 0x80,
+ 0xAD,
+ 0x4D,
+ 0x7F,
+ 0x50,
+ 0x12,
+ 0x06,
+ 0x22,
+ 0x7D,
+ 0x40,
+ 0x7F,
+ 0x4F,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0xC2,
+ 0x06,
+ 0x22,
+ 0x20,
+ 0x12,
+ 0x15,
+ 0x7D,
+ 0x08,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x06,
+ 0x63,
+ 0x7D,
+ 0xFC,
+ 0x7F,
+ 0x63,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x64,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x7D,
+ 0x02,
+ 0x7F,
+ 0x66,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x7D,
+ 0x10,
+ 0x7F,
+ 0x11,
+ 0x12,
+ 0x06,
+ 0x67,
+ 0x7D,
+ 0x10,
+ 0x7F,
+ 0x1A,
+ 0x12,
+ 0x06,
+ 0x67,
+ 0x7D,
+ 0x08,
+ 0x7F,
+ 0x16,
+ 0x02,
+ 0x06,
+ 0x67,
+ 0x20,
+ 0x12,
+ 0x15,
+ 0x7D,
+ 0x08,
+ 0x7F,
+ 0x0A,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x7D,
+ 0xFC,
+ 0x7F,
+ 0x63,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x64,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x7D,
+ 0x02,
+ 0x7F,
+ 0x66,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x7D,
+ 0x10,
+ 0x7F,
+ 0x11,
+ 0x12,
+ 0x06,
+ 0x52,
+ 0x7D,
+ 0x10,
+ 0x7F,
+ 0x1A,
+ 0x12,
+ 0x06,
+ 0x52,
+ 0x7D,
+ 0x08,
+ 0x7F,
+ 0x16,
+ 0x02,
+ 0x06,
+ 0x52,
+ 0x8F,
+ 0x4A,
+ 0x8C,
+ 0x4B,
+ 0x8D,
+ 0x4C,
+ 0x8B,
+ 0x4D,
+ 0xE4,
+ 0xF5,
+ 0x4E,
+ 0xAF,
+ 0x4A,
+ 0x7E,
+ 0x00,
+ 0xAB,
+ 0x4D,
+ 0xAD,
+ 0x4C,
+ 0xAC,
+ 0x4B,
+ 0x12,
+ 0x0A,
+ 0x61,
+ 0x7D,
+ 0x29,
+ 0xE4,
+ 0xFF,
+ 0x12,
+ 0x08,
+ 0x07,
+ 0xEF,
+ 0x70,
+ 0x02,
+ 0xD3,
+ 0x22,
+ 0x05,
+ 0x4E,
+ 0xE5,
+ 0x4E,
+ 0xD3,
+ 0x94,
+ 0x02,
+ 0x40,
+ 0xDE,
+ 0x22,
+ 0xA2,
+ 0x11,
+ 0x92,
+ 0x0B,
+ 0x30,
+ 0x11,
+ 0x0F,
+ 0x12,
+ 0x0C,
+ 0x49,
+ 0x7E,
+ 0x05,
+ 0x7F,
+ 0xE0,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0xD2,
+ 0x12,
+ 0x02,
+ 0x0B,
+ 0x37,
+ 0xD2,
+ 0x12,
+ 0x12,
+ 0x0B,
+ 0x6B,
+ 0x20,
+ 0x09,
+ 0x03,
+ 0x12,
+ 0x0C,
+ 0xD6,
+ 0x20,
+ 0x0C,
+ 0x07,
+ 0x7E,
+ 0x05,
+ 0x7F,
+ 0xD9,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0x22,
+ 0xC2,
+ 0x04,
+ 0xEF,
+ 0x60,
+ 0x1A,
+ 0x7D,
+ 0x80,
+ 0x7F,
+ 0x0E,
+ 0x12,
+ 0x06,
+ 0x52,
+ 0x7F,
+ 0x64,
+ 0x7E,
+ 0x00,
+ 0x12,
+ 0x0C,
+ 0xF8,
+ 0x12,
+ 0x00,
+ 0x0E,
+ 0x20,
+ 0x09,
+ 0x03,
+ 0x12,
+ 0x0C,
+ 0xD6,
+ 0xD2,
+ 0x03,
+ 0x22,
+ 0x12,
+ 0x0C,
+ 0x49,
+ 0x7D,
+ 0x80,
+ 0x7F,
+ 0x0E,
+ 0x12,
+ 0x06,
+ 0x67,
+ 0x22,
+ 0xC2,
+ 0xAF,
+ 0xE4,
+ 0xF5,
+ 0x11,
+ 0xF5,
+ 0x12,
+ 0x75,
+ 0x13,
+ 0x07,
+ 0x75,
+ 0x14,
+ 0xD0,
+ 0xF5,
+ 0x18,
+ 0xF5,
+ 0x10,
+ 0xC2,
+ 0x8C,
+ 0x53,
+ 0x89,
+ 0xF0,
+ 0x43,
+ 0x89,
+ 0x01,
+ 0x75,
+ 0x8A,
+ 0x40,
+ 0x75,
+ 0x8C,
+ 0x7C,
+ 0xD2,
+ 0xA9,
+ 0xD2,
+ 0x8C,
+ 0xD2,
+ 0xAF,
+ 0x22,
+ 0x7E,
+ 0x05,
+ 0x7F,
+ 0xC9,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0x7F,
+ 0x08,
+ 0x12,
+ 0x0C,
+ 0x6F,
+ 0xEF,
+ 0x54,
+ 0x0E,
+ 0x60,
+ 0x07,
+ 0x7E,
+ 0x05,
+ 0x7F,
+ 0xE0,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0x7D,
+ 0x04,
+ 0x7F,
+ 0x5C,
+ 0x12,
+ 0x06,
+ 0x5A,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x07,
+ 0x02,
+ 0x06,
+ 0x63,
+ 0x7D,
+ 0x00,
+ 0x80,
+ 0x0A,
+ 0x7D,
+ 0x01,
+ 0x80,
+ 0x06,
+ 0x7D,
+ 0x03,
+ 0x80,
+ 0x02,
+ 0x7D,
+ 0x04,
+ 0xC2,
+ 0xAF,
+ 0x78,
+ 0x83,
+ 0xE2,
+ 0xCD,
+ 0xF2,
+ 0x74,
+ 0x80,
+ 0x2F,
+ 0xF8,
+ 0xE2,
+ 0x78,
+ 0x03,
+ 0xFF,
+ 0xED,
+ 0xF2,
+ 0xD2,
+ 0xAF,
+ 0x22,
+ 0x32,
+ 0x8F,
+ 0x4A,
+ 0x80,
+ 0x18,
+ 0xE5,
+ 0x4C,
+ 0x60,
+ 0x19,
+ 0x7F,
+ 0x25,
+ 0x12,
+ 0x0C,
+ 0x77,
+ 0xEF,
+ 0x54,
+ 0x10,
+ 0xF5,
+ 0x4B,
+ 0xB5,
+ 0x47,
+ 0x04,
+ 0x15,
+ 0x4C,
+ 0x80,
+ 0xEB,
+ 0x85,
+ 0x4B,
+ 0x47,
+ 0x85,
+ 0x4A,
+ 0x4C,
+ 0x80,
+ 0xE3,
+ 0x22,
+ 0x8F,
+ 0x4A,
+ 0x80,
+ 0x18,
+ 0xE5,
+ 0x4C,
+ 0x60,
+ 0x19,
+ 0x7F,
+ 0x7F,
+ 0x12,
+ 0x0C,
+ 0x7B,
+ 0xEF,
+ 0x54,
+ 0x04,
+ 0xF5,
+ 0x4B,
+ 0xB5,
+ 0x3D,
+ 0x04,
+ 0x15,
+ 0x4C,
+ 0x80,
+ 0xEB,
+ 0x85,
+ 0x4B,
+ 0x3D,
+ 0x85,
+ 0x4A,
+ 0x4C,
+ 0x80,
+ 0xE3,
+ 0x22,
+ 0x7E,
+ 0x06,
+ 0x7F,
+ 0x00,
+ 0x12,
+ 0x06,
+ 0x8A,
+ 0x7D,
+ 0x04,
+ 0x7F,
+ 0x0A,
+ 0x30,
+ 0x01,
+ 0x10,
+ 0x12,
+ 0x06,
+ 0x63,
+ 0x7D,
+ 0x04,
+ 0x7F,
+ 0x5C,
+ 0x12,
+ 0x06,
+ 0x6F,
+ 0x7D,
+ 0x01,
+ 0x7F,
+ 0x07,
+ 0x80,
+ 0x00,
+ 0x12,
+ 0x06,
+ 0x4E,
+ 0x22,
+ 0xAD,
+ 0x07,
+ 0xAC,
+ 0x06,
+ 0xE4,
+ 0x12,
+ 0x04,
+ 0x9C,
+ 0xE4,
+ 0xFB,
+ 0xFA,
+ 0x79,
+ 0x20,
+ 0x78,
+ 0x40,
+ 0x12,
+ 0x03,
+ 0xFA,
+ 0x12,
+ 0x04,
+ 0xD5,
+ 0x8F,
+ 0x11,
+ 0xE5,
+ 0x11,
+ 0x70,
+ 0xFC,
+ 0x22,
+ 0x78,
+ 0x7F,
+ 0xE4,
+ 0xF6,
+ 0xD8,
+ 0xFD,
+ 0x75,
+ 0x81,
+ 0xA5,
+ 0x02,
+ 0x02,
+ 0x64
+};
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
new file mode 100644
index 0000000..2b92556
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
@@ -0,0 +1,1587 @@
+/* -*- pse-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.c
+ * $Revision: 1.3 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is contains all necessary functions for Internal
+ * LVDS PORT DRIVER.
+ * This is written according to the port interface defined in pd.h.
+ *-----------------------------------------------------------------------------
+ */
+
+#pragma optimize ("",off)
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+#include "lvds.h"
+
+
+#ifdef T_LINUX
+ #include <linux/kernel.h>
+
+ #define PD_DEBUG printk
+ #define PD_ERROR printk
+#else
+ #define CONFIG_PLB
+// #define CONFIG_TNC
+#endif
+
+/* One space between the #define and the backslash,else compilers complain */
+#define PTR_OFFSET_UCHAR(ptr,offset) (*((unsigned char *)ptr + offset))
+#define PTR_OFFSET_USHORT(ptr, offset) (*(unsigned short *)((unsigned char *)ptr + offset))
+
+#define PTR_OFFSET_ULONG(ptr, offset) (*(unsigned long *)((unsigned char *)ptr + offset))
+/* END OF OPTIMIZATION MACROS */
+
+/* This constant = 10,000,000. The value is used to
+ * get effective results from the integer math, and
+ * to not divide by 0. */
+#define PWM_FREQ_CALC_CONSTANT_1 0x00989680
+/* This constant is 1,000,000 - to multiply to get
+ * the Display Clock Frequency to the order of Mhz */
+#define PWM_FREQ_CALC_CONSTANT_2 0x000F4240
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+static pd_version_t internal_lvds_version = {11, 0, 0, 0}; /* driver version */
+static unsigned long internal_lvds_dab_list[] = {
+ PD_DAB_LIST_END
+}; /* dab list */
+
+static unsigned long supported_chipset[] =
+{
+#ifdef CONFIG_855
+ PCI_DEVICE_ID_VGA_855,
+#endif
+#ifdef CONFIG_915AL
+ PCI_DEVICE_ID_VGA_915AL,
+#endif
+#ifdef CONFIG_945GM
+ PCI_DEVICE_ID_VGA_945GM,
+ PCI_DEVICE_ID_VGA_945GME,
+#endif
+#ifdef CONFIG_965GM
+ PCI_DEVICE_ID_VGA_GM965,
+ PCI_DEVICE_ID_VGA_GME965,
+#endif
+#ifdef CONFIG_CTG
+ PCI_DEVICE_ID_VGA_CTG,
+#endif
+#ifdef CONFIG_PLB
+ PCI_DEVICE_ID_VGA_PLB,
+#endif
+#ifdef CONFIG_TNC
+ PCI_DEVICE_ID_VGA_TNC,
+ PCI_DEVICE_ID_VGA_TNC_A0,
+ PCI_DEVICE_ID_VGA_LNC,
+#endif
+};
+
+static pd_driver_t internal_lvds_driver = {
+ PD_SDK_VERSION,
+ "Internal LVDS Port Driver",
+ 0,
+ &internal_lvds_version,
+ PD_DISPLAY_LVDS_INT,
+ PD_FLAG_UP_SCALING,
+ internal_lvds_dab_list,
+ 100,
+ internal_lvds_validate,
+ internal_lvds_open,
+ internal_lvds_init_device,
+ internal_lvds_close,
+ internal_lvds_set_mode,
+ internal_lvds_post_set_mode,
+ internal_lvds_set_attrs,
+ internal_lvds_get_attrs,
+ internal_lvds_get_timing_list,
+ internal_lvds_set_power,
+ internal_lvds_get_power,
+ internal_lvds_save,
+ internal_lvds_restore,
+ internal_lvds_get_port_status
+};
+
+/* This is a common attribute table for all chipsets. At the end of the table
+ * there are multiple end entries to add chipset specific attributes.
+ * Chipset specific attributes:
+ * 965GM/GM45- Maintain aspect ratio
+ * Note:
+ * 1. Make sure to update the chipset_attr_index whenever adding a
+ * chipset specific new attr.
+ */
+static pd_attr_t internal_lvds_attrs[] =
+{
+ /* Range attributes */
+
+ /*<-------ID-----------> <----TYPE--------> <---NAME-----> <----flag----> <---DEF_VAL----> <--CURR_VALUE--> min max st */
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T1, PD_ATTR_TYPE_RANGE, "FP Power T1", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T2, PD_ATTR_TYPE_RANGE, "FP Power T2", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T3, PD_ATTR_TYPE_RANGE, "FP Power T3", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T4, PD_ATTR_TYPE_RANGE, "FP Power T4", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T5, PD_ATTR_TYPE_RANGE, "FP Power T5", PD_ATTR_FLAG_USER_INVISIBLE, 400, 400, 0, 3000, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_PANEL_DEPTH, PD_ATTR_TYPE_RANGE, "Panel Depth", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_DEPTH, LVDS_DEF_PANEL_DEPTH, 18, 24, 6),
+
+ PD_MAKE_ATTR (PD_ATTR_ID_PWM_INTENSITY, PD_ATTR_TYPE_RANGE, "PWM cycle", PD_ATTR_FLAG_USER_INVISIBLE, 100, 0, 0, 100, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_INVERTER_FREQ, PD_ATTR_TYPE_RANGE, "Inverter Frequency", PD_ATTR_FLAG_USER_INVISIBLE, 100, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_BLM_LEGACY_MODE, PD_ATTR_TYPE_BOOL, "Backlight Legacy mode", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+ /*<-------ID------------> <----TYPE--------> <---NAME-----> <------flag---------------> <---DEF_VAL----> <--CURR_VALUE--> <---pad--> */
+ PD_MAKE_ATTR (PD_ATTR_ID_2_CHANNEL_PANEL, PD_ATTR_TYPE_BOOL, "Dual-channel panel", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_LVDS_PANEL_TYPE, PD_ATTR_TYPE_BOOL, "Panel Type", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_PANEL_FIT, PD_ATTR_TYPE_BOOL, "Panel Upscale", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_FIT,LVDS_DEF_PANEL_FIT,0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_DITHER, PD_ATTR_TYPE_BOOL, "Dither", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_DITHER, LVDS_DEF_DITHER, 0, 0, 0),
+ PD_MAKE_ATTR (LVDS_ATTR_ID_TC_LVDS_CLK, PD_ATTR_TYPE_BOOL, "TC LVDS CLK 110MHz", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+ /* Start of chipset specific attributes */
+ /* Maintain aspect ratio */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0),
+ /* Text tuning */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0),
+
+ /* Attribute list end */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0)
+};
+
+/* Rightnow it is -3 to reach starting of chipset specific attributes */
+static unsigned short chipset_attr_index = (unsigned short)
+ sizeof(internal_lvds_attrs)/sizeof(pd_attr_t) - 3;
+
+#if 0
+static pd_attr_t internal_lvds_965gm_attrs[] = {
+ PD_MAKE_ATTR (PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,PD_ATTR_TYPE_BOOL, "Maintain Aspect Ratio",0, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_TEXT_TUNING, PD_ATTR_TYPE_RANGE, "Text Enhancement", 0, 0, 0, 0, 2, 1),
+};
+#endif
+
+static void internal_lvds_write_reg(internal_lvds_context_t *pd_context, unsigned long reg,
+ unsigned long value, unsigned long change_bits, unsigned long reg_type);
+
+static unsigned long internal_lvds_read_reg(internal_lvds_context_t *pd_context,
+ unsigned long reg, unsigned long reg_type);
+static void internal_lvds_panel_fit(internal_lvds_context_t *pd_context);
+
+static void internal_lvds_get_dclk(internal_lvds_context_t *pd_context, pd_dvo_info_t *internal_lvds_info);
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_INIT(internal_lvds_init)
+ *
+ * Description:
+ * This is the entry function into LVDS port driver when
+ * it first loads. This will call pd_register() to register
+ * with Display driver. Only the driver object is initialized in this
+ * function, similar to DrverEntry() in a WDM driver.
+ *
+ * Parameters:
+ * [OUT] *handle: Not used. Place holder for supporting dynamic pd
+ *
+ * Return:
+ * PD_SUCCESS(0) success
+ * PD_ERR_XXXXXX otherwise
+ *
+ *----------------------------------------------------------------------------
+ */
+#ifdef T_LINUX //thua- 9/16/11
+
+int PD_MODULE_INIT(internal_lvds_init, (void *handle))
+{
+ /* register the LVDS driver */
+ return pd_register(handle, &internal_lvds_driver);
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_EXIT(internal_lvds_exit, (void))
+ *
+ * Description:
+ * This function cleans up resources used by the LVDS driver
+ *
+ * Parameters:
+ * None
+ *
+ * Return:
+ * PD_SUCCESS(0): always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+#ifdef T_LINUX //thua- 9/16/11
+int PD_MODULE_EXIT(internal_lvds_exit, (void))
+{
+ return PD_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_validate
+ *
+ * Description:
+ * Place holder for a future function
+ *
+ * Parameters:
+ * TBD
+ *
+ * Return:
+ * TBD
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned long internal_lvds_validate (unsigned long cookie)
+{ /* internal_lvds_validate */
+ /* Validate magic cookie */
+ /* TODO: Implement the magic cookie algorithm */
+ return cookie;
+} /* internal_lvds_validate */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_open
+ *
+ * Description:
+ * This function creates an LVDS context and intialize it with LVDS
+ * attributes.
+ *
+ * Internal LVDS port is available only on MGM platform, this port driver
+ * reads the GMCH device ID with pd_read_regs(PD_REG_PCI) to verify that
+ * it is supported on the current platform.
+ *
+ * Parameters:
+ * [IN] callback: callback context
+ * [INOUT] context: Device context. This function will set the attributes
+ * for this context, provided it is already allocated,
+ * i.e. not NULL.
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if either of the parameters is NULL
+ * PD_ERR_NODEV: if an LVDS device is already up and running
+ * PD_ERR_NOMEM: if a memory allocation failed
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* lvds context structure being declared and initialized */
+
+static internal_lvds_context_t internal_lvds_context = { /* lvds context structure */
+ 0, /* fp_width */
+ 0, /* fp_height */
+ 0, /* dual_channel: Default single channel */
+ 0, /* panel_type : 0-SPWG 1-OpenLDI*/
+ LVDS_DEF_PANEL_FIT, /* panel_fit */
+ LVDS_DEF_PANEL_DEPTH,/* panel_depth */
+ 0xFFFF, /* dither */
+ 0, /* Main aspect ratio, default no */
+ 0, /* panel filter: Default fuzzy filtering */
+ 100, /* PWM Intensity */
+ 0xFFFF, /* Inverter Frequency*/
+ 0, /* BLM Legacy Mode */
+
+ PD_POWER_MODE_D0, /* power_state */
+ 0, /* chipset */
+ 0, /* init_done */
+ 0, /* num_attrs */
+ 0, /* PIPE flags */
+ 0, /* Graphics Frequency */
+ 0, /* is gn4 based LVDS controller? */
+ 0, /* is pwm_done? */
+ 0, /* is tc_110MHz_clk? i.e., TC max LVDS to 110MHz*/
+
+ NULL, /* ptr to callback */
+ NULL, /* ptr to timing table */
+ internal_lvds_attrs, /* ptr to attribute list */
+ NULL, /* ptr to native timing */
+ NULL, /* current mode */
+};
+
+int internal_lvds_open(pd_callback_t *callback, void **context)
+{ /* internal_lvds_open */
+ internal_lvds_context_t *pd_context = (internal_lvds_context_t*) &(internal_lvds_context); /* static Global */
+ pd_reg_t reg_list[2];
+ int ret, i, valid_chipset = 0;
+ unsigned short chipset;
+
+ PD_TRACE_ENTER;
+
+
+
+ /* make sure parameters are valid */
+ if (!callback || !context) {
+ PD_ERROR("invalid parameter");
+ return (PD_ERR_NULL_PTR);
+ }
+ /* GMCH cannot support more than one device */
+ if (internal_lvds_driver.num_devices > 0) {
+ return (PD_ERR_NODEV);
+ }
+ /* Verify that this is an GMCH with Internal LVDS available */
+ reg_list[0].reg = 2;
+ reg_list[1].reg = PD_REG_LIST_END;
+ ret = callback->read_regs(callback->callback_context, reg_list, PD_REG_PCI);
+ if(ret != PD_SUCCESS) {
+ return ret;
+ }
+ chipset = (unsigned short)(reg_list[0].value & 0xffff);
+ for (i = 0; i < ARRAY_SIZE(supported_chipset); i++) {
+ if (chipset == supported_chipset[i]){
+ valid_chipset = 1;
+ break;
+ }
+ }
+ if(!valid_chipset){
+ return PD_ERR_NODEV;
+ }
+
+ /* Special handling for gn4 and beyond chipsets */
+ if (chipset == PCI_DEVICE_ID_VGA_GM965 ||
+ chipset == PCI_DEVICE_ID_VGA_GME965 ||
+ chipset == PCI_DEVICE_ID_VGA_CTG ||
+ chipset == PCI_DEVICE_ID_VGA_TNC ||
+ chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ chipset == PCI_DEVICE_ID_VGA_LNC) {
+ internal_lvds_context.gn4_plus = 1;
+ }
+
+ /* Initialize number of attributes */
+ /* +1 is to include the end attribute */
+ internal_lvds_context.num_attrs = (unsigned char)chipset_attr_index;
+// internal_lvds_context.num_attrs = (unsigned char)chipset_attr_index + 1;
+
+#if 0
+ /* Add chipset specific attrbutes.
+ * This can be expanded into a switch statement in future if required. */
+ if (internal_lvds_context.gn4_plus) {
+ internal_lvds_context.num_attrs += sizeof(internal_lvds_965gm_attrs)/sizeof(pd_attr_t);
+ for (i=0; i < sizeof(internal_lvds_965gm_attrs)/sizeof(pd_attr_t); i++) {
+ internal_lvds_attrs[chipset_attr_index+i] = internal_lvds_965gm_attrs[i];
+ }
+ }
+#endif
+
+ /* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+ /* pwm backlight control needs graphics frequency. we currently implement
+ * pwm backlight control for pouslbo only to limit the vbios lvds size. Each
+ * chipset have a different method of getting this value and chipset has a
+ * different multiplier. */
+ if (chipset == PCI_DEVICE_ID_VGA_PLB ||
+ chipset == PCI_DEVICE_ID_VGA_TNC ||
+ chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ chipset == PCI_DEVICE_ID_VGA_LNC) {
+
+ /* For plb/tnc, graphics frequency is obtained by sending an opcode to
+ * port 5 in the SCH Message Network. We call the read_regs with
+ * PD_REG_BRIDGE_OPCODE specifically for this purpose only.
+ *
+ * The input for this read_reg is the opcode that register data that
+ * we send into the Message control register*/
+ reg_list[1].reg = PD_REG_LIST_END;
+ ret = callback->read_regs(callback->callback_context,
+ reg_list, PD_REG_BRIDGE_OPCODE);
+ if(ret != PD_SUCCESS) {
+ return ret;
+ }
+
+ /*set the graphics frequency*/
+ pd_context->gfx_freq = (unsigned short) reg_list[0].value;
+ }
+#endif
+
+ pd_context->callback = callback; /* Save callback context */
+ pd_context->chipset = chipset; /* save the chipset ID */
+ *context = (void *) pd_context;
+
+ PD_TRACE_EXIT;
+ return PD_SUCCESS;
+} /* internal_lvds_open */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_init_device
+ *
+ * Description:
+ * Initializes the LVDS device, using the device context from the parameter
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if parameter is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_init_device (void *context)
+{ /* internal_lvds_init_device */
+ if (!context) {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ /* Don't need to do much to initialize this device */
+ ((internal_lvds_context_t *)context)->init_done = 1;
+ internal_lvds_driver.num_devices++;
+
+ return (PD_SUCCESS);
+} /* internal_lvds_init_device */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_close
+ *
+ * Description:
+ * Releases resources allocated during internal_lvds_open(). This function
+ * essentially frees a device object.
+ *
+ * Parameters:
+ * [INOUT] device_context: device to be freed
+ *
+ * Return:
+ * PD_SUCCESS: always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_close(void *device_context)
+{
+#ifndef CONFIG_MICRO
+
+ internal_lvds_context_t *pd_context = (internal_lvds_context_t *)device_context;
+
+ /* internal_lvds_close */
+
+ PD_TRACE_ENTER;
+
+ /* Deallocate memory occupied by this device */
+ if (device_context) {
+ if ( NULL != pd_context->timing_table) {
+ pd_free(pd_context->timing_table);
+ }
+
+ /* Free attribute list, if necessary */
+ /* FIXME -- The following test will never call pd_free(), because the
+ * expression "!internal_lvds_driver.num_devices" will yield 0 or 1, and that
+ * will never be greater than 1. This is a potentially small memory
+ * leak, unless some other code frees it.
+ */
+ if (!internal_lvds_driver.num_devices > 1) {
+ pd_free(pd_context->attr_list);
+ }
+ /* This allocated statically no need to free it */
+ /* pd_free(device_context); */
+ internal_lvds_driver.num_devices--;
+ pd_context->init_done = 0;
+ }
+
+ PD_TRACE_EXIT;
+#endif
+ return (PD_SUCCESS);
+} /* internal_lvds_close */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_mode
+ *
+ * Description:
+ * Sets LVDS to a new mode, specified by "mode".
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ * [IN] mode: information about the mode to switch to
+ * [IN] flags: can contain the following value
+ * PD_SET_MODE_FLAG_TEST: only testing to see if mode is supported
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if invalid parameter detected
+ * PD_ERR_MODE_NOTSUPP: if mode specified is not supported
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{
+ internal_lvds_context_t *pd_context = NULL;
+
+ PD_DEBUG("internal_lvds_set_mode)\n");
+ PD_TRACE_ENTER;
+
+ pd_context = (internal_lvds_context_t *)context;
+
+ /* Make sure these parameters are valid */
+ if (!pd_context || !mode) {
+ return (PD_ERR_NULL_PTR);
+ }
+ PD_DEBUG("internal_lvds_set_mode: %ux%u", mode->width, mode->height);
+
+ /* Make sure specified mode is supported */
+ if ((pd_context->fp_width && (mode->width > pd_context->fp_width)) ||
+ (pd_context->fp_height && (mode->height > pd_context->fp_height))) {
+ PD_ERROR("internal_lvds_set_mode: ERROR #1\n");
+ return PD_ERR_MODE_NOTSUPP;
+ }
+
+ /* Do nothing if we are only want to know if a mode is supported */
+ if (flags & PD_SET_MODE_FLAG_TEST) {
+ PD_ERROR("internal_lvds_set_mode: SUPPORTED #2\n");
+ return PD_SUCCESS;
+ }
+
+ pd_context->current_mode = mode;
+ pd_context->pipe = flags;
+ /* Enable panel fitting and return */
+ internal_lvds_panel_fit(pd_context);
+
+ PD_ERROR("internal_lvds_set_mode: EXIT #3\n");
+ PD_TRACE_EXIT;
+
+ return PD_SUCCESS;
+}
+
+int internal_lvds_post_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{ /* internal_lvds_set_mode */
+ internal_lvds_context_t *pd_context = NULL;
+ unsigned long port_control = 0;
+ unsigned long preserve = 0;
+ int ret = 0;
+
+ PD_TRACE_ENTER;
+ pd_context = (internal_lvds_context_t *)context;
+
+ PD_DEBUG("internal_lvds_post_set_mode)\n");
+ /* Make sure these parameters are valide */
+ if (!pd_context || !mode) {
+ PD_DEBUG("internal_lvds_post_set_mode: EXIT #1\n");
+ return (PD_ERR_NULL_PTR);
+ }
+
+ /* Before enabling the LVDS port, make sure that display PLL for this pipe
+ * is enabled and the port is power sequenced on using the panel power
+ * sequencing logic. */
+
+ preserve = 0x3E007803;
+ port_control = preserve & internal_lvds_read_reg(pd_context, 0x61180, PD_REG_MIO);
+ port_control |= BIT(31); /* enable LVDS port */
+ if (flags & PD_SET_MODE_PIPE_B) {
+ port_control |= BIT(30);
+ }
+ port_control |= (BIT(9)|BIT(8)); /* power up */
+ port_control &= ~(BIT(21)|BIT(20)); /* Default sync polarites active high */
+
+ /* For gn4+, dither moved to port_control from panel_fit reg */
+ if (pd_context->gn4_plus) {
+ if (pd_context->panel_depth == 18) {
+ port_control |= BIT(25);
+ }
+
+ if (pd_context->dither != 0xFFFF) {
+ if (pd_context->dither) {
+ port_control |= BIT(25);
+ } else {
+ port_control &= ~BIT(25);
+ }
+ }
+ }
+
+ if((!pd_context->panel_fit) &&
+ ( mode->width < pd_context->fp_width ||
+ mode->height < pd_context->fp_height ) ){
+ port_control |= BIT(15); /* enable border in active for centering */
+ }
+
+ /*
+ * Bit 24 for OpenLDI should be set to a 0 (1x18.0, 2x18.0, 1x24.0, 2x24.0).
+ * From (B-Spec, Ref# 22316, section 1.15.3.8.3)
+ *
+ * Bit 24 for SPWG should be set to a 1 (1x24.1 or 2x24.1).
+ *
+ * This was verified by comparing the timing diagram for 1x24.0 in
+ * OpenLDI spec (5.4.2.2 24-bit Single Pixel Mode, Unbalanced) with the
+ * same diagram in the Display BSpec for Napa or Gen4.
+ * A0 A3 signals match the 1x24.0.
+ *
+ * From the OpenLDI spec (bit mappings are different):
+ *
+ * Table 5-2, Bit Number Mappings
+ * 18 bpp bit# 24 bpp bit# OpenLDI bit#
+ * 5 7 5
+ * 4 6 4
+ * 3 5 3
+ * 2 4 2
+ * 1 3 1
+ * 0 2 0
+ * 1 7
+ * 0 6
+ */
+
+ /* Attribute panel_type description:
+ * Attr ID Attr Value IntLVDS dataformat
+ * ======= =============== ==================
+ * 49 0 (SPWG) 1 (value of Bit 24)
+ * 49 1 (OpenLDI) 0 (value of Bit 24)
+ */
+ if (pd_context->panel_type == 0) {
+ port_control |= BIT(24); /* Dataformat 0 = SPWG, 1 = OpenLDI */
+ }
+
+ /* If the dual-channel is required, then power up second channel
+ * ClkB and B0, B1, B2, (B3) */
+ if (pd_context->dual_channel) {
+ port_control |= (BIT(5)|BIT(4)); /* ClkB */
+ port_control |= (BIT(3)|BIT(2)); /* B0, B1, B2, (B3) */
+ }
+
+ /* Check for 18 or 24 bit panel */
+ if (pd_context->panel_depth == 24) {
+ /* If the panel is 24-bit (8-bpp), enable A3, (B3) pair. */
+ port_control |= (BIT(7)|BIT(6));
+ }
+
+ /* Set the sync polarities correctly if there is a native dtd */
+ if (pd_context->native_dtd) {
+ /* Set bit 20 for hsync active low */
+ if ((pd_context->native_dtd->mode_info_flags & PD_HSYNC_HIGH) == 0) {
+ port_control |= BIT(20);
+ }
+ /* Set bit 21 for vsync active low */
+ if ((pd_context->native_dtd->mode_info_flags & PD_VSYNC_HIGH) == 0) {
+ port_control |= BIT(21);
+ }
+ }
+
+ internal_lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+ internal_lvds_write_reg(pd_context, 0x61180, port_control, 0xFFFFFFFF, PD_REG_MIO);
+ ret = internal_lvds_set_power(pd_context, PD_POWER_MODE_D0);
+ if (ret) {
+ PD_ERROR("PD set_power (D0) returned: 0x%x", ret);
+ return ret;
+ }
+
+ internal_lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+ PD_DEBUG("internal_lvds_post_set_mode: EXIT SUCCESS\n");
+
+ PD_TRACE_EXIT;
+ /* Set the mode as per given timings */
+ return PD_SUCCESS;
+} /* internal_lvds_set_mode */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_attrs
+ *
+ * Description:
+ * Incorporate attributes in "list" into the device context. This function
+ * will override the initial attributes set by init_attrs.
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ * [IN] num: not used, but must not be 0.
+ * [IN] list: list of attributes to incorporate into device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_ERR_ATTR_CANT_CHANGE: attributes cannot be modified
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by Optimization Code. internal_lvds_set_attrs() */
+typedef struct _opt_table_data {
+ unsigned long id;
+ unsigned short block;
+ unsigned short offset;
+} internal_lvds_opt_table_data_t;
+static internal_lvds_opt_table_data_t table_opt_data1[] = {
+
+ /*<--- id ----------> <---block---> <------ offset -------------------> */
+ {PD_ATTR_ID_PANEL_DEPTH, 1, PD_OFFSETOF(internal_lvds_context_t, panel_depth) },
+
+ {PD_ATTR_ID_2_CHANNEL_PANEL, 1, PD_OFFSETOF(internal_lvds_context_t, dual_channel)},
+ {PD_ATTR_ID_LVDS_PANEL_TYPE, 1, PD_OFFSETOF(internal_lvds_context_t, panel_type) },
+ {PD_ATTR_ID_PANEL_FIT, 1, PD_OFFSETOF(internal_lvds_context_t, panel_fit) },
+ {PD_ATTR_ID_DITHER, 1, PD_OFFSETOF(internal_lvds_context_t, dither) },
+ {PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,1,PD_OFFSETOF(internal_lvds_context_t,aspect_ratio)},
+ {PD_ATTR_ID_TEXT_TUNING, 1, PD_OFFSETOF(internal_lvds_context_t, text_tune)},
+ {PD_ATTR_ID_PWM_INTENSITY, 1, PD_OFFSETOF(internal_lvds_context_t, pwm_intensity)},
+ {PD_ATTR_ID_INVERTER_FREQ, 1, PD_OFFSETOF(internal_lvds_context_t, inverter_freq)},
+ {PD_ATTR_ID_BLM_LEGACY_MODE, 1, PD_OFFSETOF(internal_lvds_context_t, blm_legacy_mode)},
+ {LVDS_ATTR_ID_TC_LVDS_CLK, 1, PD_OFFSETOF(internal_lvds_context_t, tc_110MHz_clk)},
+
+ /*<--- id ----------> <---block---> <------ offset -------------------> */
+ {PD_ATTR_ID_FP_PWR_T1, 2, 0 }, /* 6 */
+ {PD_ATTR_ID_FP_PWR_T2, 2, 0 }, /* 7 */
+ {PD_ATTR_ID_FP_PWR_T3, 2, 0 }, /* 8 */
+ {PD_ATTR_ID_FP_PWR_T4, 2, 0 }, /* 9 */
+ {PD_ATTR_ID_FP_PWR_T5, 2, 0 } /* 10 */
+};
+/* End of Tables required by Optimization Code. internal_lvds_set_attrs() */
+
+int internal_lvds_set_attrs (void *context, unsigned long num, pd_attr_t *list)
+{
+ internal_lvds_context_t *pd_context = (internal_lvds_context_t *) context;
+ pd_attr_t *attr = NULL;
+ unsigned short i = 0;
+ unsigned short j = 0;
+ int ret = PD_SUCCESS;
+ /* no of case IDs in the global table */
+ int num_case_ids = sizeof(table_opt_data1)/sizeof(internal_lvds_opt_table_data_t);
+
+ /* basic parameter check */
+ if (!context || !num || !list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ PD_DEBUG("internal_lvds_set_attrs()\n");
+ for (i = 0; i < num; i++, list++) {
+ /* do nothing if the attribute has not been changed */
+ if (!(list->flags & PD_ATTR_FLAG_VALUE_CHANGED)) {
+ continue;
+ }
+
+ //thua- need to reset flag to 'not changed' - 9/19/11
+// list->flags &= ~PD_ATTR_FLAG_VALUE_CHANGED;
+
+ /* attributes can't be changed after init has been completed */
+ if (list->flags & PD_ATTR_FLAG_USER_INVISIBLE &&
+ pd_context->init_done) {
+ return PD_ERR_ATTR_CANT_CHANGE;
+ }
+
+ /* Set the internal attributes' list. Note that although get_attr() can
+ * return NULL theortically, it will not do so here because all the
+ * attribute IDs in this switch statement comes from internal_lvds_attrs[],
+ * a list that is automatically initialized into pd_context. This is
+ * why we are not checking for NULL after calling get_attr().
+ */
+#if 0 /* ORIGINAL SWITCH STATEMENT */
+ switch (list->id) {
+ case PD_ATTR_ID_FP_PWR_T1:
+ case PD_ATTR_ID_FP_PWR_T2:
+ case PD_ATTR_ID_FP_PWR_T3:
+ case PD_ATTR_ID_FP_PWR_T4:
+ case PD_ATTR_ID_FP_PWR_T5:
+ /* current_value should not exceed the predefined max value */
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = LVDS_MIN(
+ ((pd_range_attr_t *)list)->current_value,
+ attr->_pad1);
+ break;
+
+ case PD_ATTR_ID_PANEL_DEPTH:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = list->current_value;
+ pd_context->panel_depth = (unsigned char) attr->current_value;
+ break;
+
+ case PD_ATTR_ID_2_CHANNEL_PANEL:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->dual_channel = (attr->current_value?1:0);
+ break;
+
+ case PD_ATTR_ID_LVDS_PANEL_TYPE:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->panel_type = (attr->current_value?1:0);
+ break;
+
+ case PD_ATTR_ID_PANEL_FIT:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->panel_fit = (attr->current_value?1:0);
+ break;
+
+ default:
+ /* do nothing if we have an unknown ID */
+ break;
+ }
+#endif
+ /* OPTIMIZATION CODE BEGINS FOR THE ABOVE SWITCH
+ *----------------------------------------------
+ * Step 1: First identify the code common to all case blocks.
+ * This we call it "common code block" Since this is to be
+ * executed by all the case blocks.
+ *
+ * Step 2: Group the cases into blocks based on how we can combine them
+ *
+ * Eg: case 0: ptr->x = 1; break; // similar code
+ * case 1: ptr->y = 1; break; // similar code
+ * ------Combined block ----
+ * case 0:
+ * case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+ * This is an important step because we save code space by
+ * mapping many cases to smaller number of blocks. In the above
+ * we use index to get the right offset of the ptr.
+ *
+ * Step 3: Assign block IDs to each block. Put the case ID, block ID
+ * and other information such as offsets of ptr in a global
+ * table.
+ *
+ * Step 4: During run-time , search through the global table, find the
+ * matching case ID, and execute the common code. Next get the
+ * block ID and execute the block specific code. For the index,
+ * retrieve it from the table for the corresponding case ID.
+ *
+ * Step 5: If no matching case ID is found, error it out.
+ *
+ * Let's look at the optimization code for the above switch.
+ * The code below searches for the list->id in a global table where
+ * we store all the case values along with block numbers and other
+ * information. After we find a valid id in the table , we execute the
+ * common code for all cases first and then we retrieve the block id.
+ * The block id is necesary to determine which block does the id belong
+ * to. This is used to execute block specific code. Similar to switch
+ * cases ONLY here we try to minimize the no of blocks.
+ *
+ * In this example , we store the offsets of field names of a ptr in the
+ * global table.This is necessary to combine cases with "similar" but
+ * not "same" codes.
+ *
+ * Eg: case 0: ptr->x = 1; break; // similar code
+ * case 1: ptr->y = 1; break; // similar code
+ * -- Combined block ----
+ * case 0:
+ * case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+ *
+ * By reducing the number of blocks we save on Code space. After we
+ * finish our work , we exit the for loop and check for invalid ID
+ * passed by the upper layer. This is akin to default in the
+ * switch block
+ *
+ * CAUTION: If there is any change in the switch above, this code
+ * along with the tables have to be re-written and changed according
+ * to the new behaviour of the switch. Examples include adding a new
+ * case in the switch. The reason for all this mumbo-jumbo is to
+ * reduce code size in VBIOS, where we are running out of code space.
+ */
+ for(j = 0; j < num_case_ids; j++) {
+ /* Search for the attribute ID in the global table */
+ if(list->id == table_opt_data1[j].id) {
+ /* Run the common code for all the blocks */
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ /* Once we get a valid ID, need to find out which block it
+ * belongs so we can execute block specific code.
+ */
+ if(table_opt_data1[j].block == 1) { /* block 1 */
+ /* Got the block. Need the offset to the struct for that ID
+ * so we can store value at corresponding offset to get the
+ * desired behaviour for that ID.This is the code that makes
+ * the whole optimization work because we are combining the
+ * case IDs into a single block which saves code.
+ */
+ attr->current_value = list->current_value;
+ PTR_OFFSET_USHORT(pd_context, table_opt_data1[j].offset) =
+ (unsigned short) attr->current_value;
+
+ } else { /* block 2. We only have two blocks. */
+ attr->current_value = LVDS_MIN(
+ list->current_value, ((pd_range_attr_t *)attr)->max);
+ }
+ break; /* We found a valid ID, so break inner for loop */
+ }
+ }
+ }
+ /* panel_type 0 (SPWG) isn't available for 18-bit depth */
+ PD_DEBUG("in LVDS_set_attributes()\n");
+ if (pd_context->panel_depth == 18) {
+ pd_context->panel_type = 1;
+ }
+ PD_DEBUG("IntLVDS: dual_channel=%u", pd_context->dual_channel);
+ PD_DEBUG("IntLVDS: panel_type=%u panel_fit=%u panel_dep=%u dither=%u",
+ pd_context->panel_type, pd_context->panel_fit,
+ pd_context->panel_depth, pd_context->dither);
+ PD_DEBUG("IntLVDS: keep_aspect_ratio=%u text_tune=%lu",
+ pd_context->aspect_ratio, pd_context->text_tune);
+ PD_DEBUG("IntLVDS: PWM Intensity=%u Inverter Freq=%u, BLM legacy mode =%u",
+ pd_context->pwm_intensity, pd_context->inverter_freq,
+ pd_context->blm_legacy_mode);
+ PD_DEBUG("IntLVDS: tc_110MHz_clk = %u", pd_context->tc_110MHz_clk);
+
+ if (pd_context->init_done) {
+ /* When emgd_driver_pre_init() pokes new attrs into this port driver,
+ * pd_context->current_mode must be set before calling
+ * internal_lvds_panel_fit(), so set it to the first entry in the timing table:
+ */
+ if (pd_context->current_mode == NULL) {
+ pd_context->current_mode = pd_context->timing_table;
+ }
+ internal_lvds_panel_fit(pd_context);
+ }
+
+ return ret;
+} /* internal_lvds_set_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_attrs
+ *
+ * Description:
+ * Extracts the attribute list and the number of elements in the list
+ * from the device context.
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] num: number of elements in list
+ * [OUT] list: list of attributes from the device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_get_attrs (void *context, unsigned long *num, pd_attr_t **list)
+{ /* internal_lvds_get_attrs */
+ /* basic parameter check */
+ if (!context || !num || !list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ PD_DEBUG("internal_lvds_get_attrs()\n");
+ /* Nothing fancy, just extracting the elements from the list */
+ *list = ((internal_lvds_context_t *)context)->attr_list;
+ *num = ((internal_lvds_context_t *)context)->num_attrs;
+
+ return PD_SUCCESS;
+} /* internal_lvds_get_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_timing_list
+ *
+ * Description:
+ *
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] in_list:
+ * [OUT] list:
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_ERR_NOMEM: if internal memory allocate failed
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_get_timing_list (void *context, pd_timing_t *in_list,
+ pd_timing_t **list)
+{ /* internal_lvds_get_timing_list */
+ internal_lvds_context_t *pd_context = (internal_lvds_context_t *)context;
+ pd_dvo_info_t internal_lvds_info = {0, 0, 1, 0, 0, 0, 0, 0};
+ pd_display_info_t internal_lvds_display_info = {0, 0, 0, 0, NULL};
+ int ret;
+
+ PD_DEBUG("internal_lvds_get_timing_list()\n");
+
+ PD_DEBUG ("NUHAIRI : context = %lu, pd_context = %lu, &internal_lvds_info = %lu\n",context, pd_context, &internal_lvds_info);
+
+ internal_lvds_get_dclk( pd_context, &internal_lvds_info );
+
+ PD_DEBUG("chipset = 0x%x", pd_context->chipset);
+ internal_lvds_display_info.panel_fit = (unsigned char) pd_context->panel_fit;
+ ret = pd_filter_timings(pd_context->callback->callback_context,
+ in_list, &pd_context->timing_table, &internal_lvds_info, &internal_lvds_display_info);
+
+ /* Helper function will return the below values */
+ pd_context->native_dtd = internal_lvds_display_info.native_dtd;
+ pd_context->fp_width = internal_lvds_display_info.width;
+ pd_context->fp_height = internal_lvds_display_info.height;
+
+ *list = pd_context->timing_table;
+ return ret;
+} /* internal_lvds_get_timing_list */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_power
+ *
+ * Description:
+ * Sets LVDS to the specified power state
+ *
+ * Conversion between IEGD timer values to LVDS port timer values
+ *
+ * SEPG(?) IEGD LVDS Port Program bits min max
+ * ---- ------- ------------ ---------------- ------ ---------
+ * T1+T2 T1 ms T1+T2 100us 0x61208 [28:16] 0 ms 819.2 ms
+ * T5 T2 ms T5 100us 0x61208 [12:00] 0 ms 819.2 ms
+ * T6 T3 ms Tx 100us 0x6120C [12:00] 0 ms 819.2 ms
+ * T3 T4 ms T3 100us 0x6120C [28:16] 0 ms 819.2 ms
+ * T4 T5 ms T4 100ms 0x61210 [04:00] 0 ms 3200 ms
+ *
+ * Reg = Value
+ * ------ -------
+ * 0x61208 = [T1 T2]
+ * 0x6120C = [T4 T3]
+ * 0x61210 = [ T5]
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] in_list:
+ * [OUT] list:
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if context is NULL
+ * PD_ERR_INVALID_POWER: if "state" is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by the optimization codes in internal_lvds_set_power() */
+typedef struct {
+ unsigned char id1;
+ unsigned char id2;
+ unsigned char bit;
+ unsigned long reg;
+} opt_set_power_t;
+
+static opt_set_power_t table_set_power[] = {
+ /* id1 id2 bit reg */
+ { PD_ATTR_ID_FP_PWR_T1, PD_ATTR_ID_FP_PWR_T2, 1, 0x61208 }, /* D0 */
+ { PD_ATTR_ID_FP_PWR_T4, PD_ATTR_ID_FP_PWR_T3, 0, 0x6120C }, /* Dx */
+};
+
+int internal_lvds_set_power(void *context, unsigned long state)
+{ /* internal_lvds_set_power */
+ unsigned long i = 0;
+ internal_lvds_context_t *pd_context = (internal_lvds_context_t *)context;
+ pd_attr_t *tattr = NULL; /* holds time delay b/ pwr transition */
+ unsigned long delay = 0, delay1;
+
+ PD_DEBUG("state = %lu", state);
+
+ PD_DEBUG("internal_lvds_set_power() to state = %lu\n",state);
+ /* Basic parameter check */
+ if (!context) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ /* Check for invalid state */
+ if (state > PD_POWER_MODE_D3) {
+ return PD_ERR_INVALID_POWER;
+ }
+
+ /* Get the index into above table */
+ if (state == PD_POWER_MODE_D0) {
+ i = 0;
+ } else {
+ i = 1;
+ }
+
+ internal_lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* Program panel power up/down delays: Either T1/T2 or T3/T4*/
+ tattr = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, table_set_power[i].id1, 0);
+ /* Convert ms to 100us */
+ delay1 = tattr->current_value;
+ delay = (tattr->current_value * 10) << 16;
+ tattr = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, table_set_power[i].id2, 0);
+ delay1 += tattr->current_value;
+ delay |= tattr->current_value * 10;
+
+ internal_lvds_write_reg(pd_context, table_set_power[i].reg, delay, 0x1FFF1FFF, PD_REG_MIO);
+
+ /* Program power cycle delay: convert ms to 100ms */
+ delay = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, PD_ATTR_ID_FP_PWR_T5, 0)->current_value;
+ delay1 += delay;
+ /* TODO: Write reference divider [31:8] */
+ delay = ((delay/100+1) & 0xFF) | ((pd_context->gfx_freq*100/2-1)<<8);
+ internal_lvds_write_reg(pd_context, 0x61210, delay, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* Power state target */
+ internal_lvds_write_reg(pd_context, 0x61204, table_set_power[i].bit, BIT(0), PD_REG_MIO);
+
+ /* Power down on reset available on crestline onwards */
+ internal_lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+ /* PWM is a method of controlling the backlight intensity.
+ * It is not method to turn on baclkight.
+ * We still need the PD method to turn on the backlight.
+ *
+ * This feature is for Pouslbo Only. We check that the user has set the
+ * inverter frequency. Default intensity, if not set, is 100%
+ *
+ * Due to the high amount of calculation, we want to only set this register
+ * if it has not been ser previously. The register could be
+ * "brought forward" from VBIOS.
+ */
+ if(pd_context->inverter_freq != 0xFFFF && /* Overwritten by set_attr */
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_PLB ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) &&
+ !pd_context->pwm_done) {
+ unsigned long reg_value = 0;
+ unsigned long percentage = 0;
+ unsigned long calculation = 0;
+ unsigned long blc_pwm_ctl2 = 0;
+
+ /* We first need to get the graphics frequency, which will be used to
+ * calculate Backlight Modulation Frequency[BMF]. BMF will be used to
+ * fill up the 15 MSB in the 0x61254 register
+ *
+ * The calculation for the Modulation Frequency field in the
+ * BLC_PWM_CTL Register is:
+ *
+ * Reference Clock Freq 1
+ * ----------------------- x ------------------
+ * Divider PWM Freq in Hz
+ *
+ */
+#if 0
+ /* GMA accurate calculation that requires "calculation" to be an
+ * unsigned long long typedef */
+ calculation = pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2;
+ calculation = calculation / 0x20; /*pouslbo specific divider*/
+ calculation = calculation * PWM_FREQ_CALC_CONSTANT_1;
+ calculation = calculation / pd_context->inverter_freq;
+ calculation = calculation / PWM_FREQ_CALC_CONSTANT_1;
+#endif
+ /* Some system bios cannot take 64 bit data type. Using a more
+ * simplified calculation that is not too accurate if the inputs
+ * are not round numbers */
+ calculation = pd_context->inverter_freq * 0x20; /* plb/tnc divider */
+ calculation = (pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2) /
+ calculation;
+
+ /* Writing the register: 15 MSB is the max lvds clock / 32.
+ * Bit 16 can either be legacy or non legacy depending upon Attr #72. */
+ if (pd_context->gn4_plus) {
+ blc_pwm_ctl2 = (1L << 31) |
+ (pd_context->blm_legacy_mode << 30) |
+ ((pd_context->pipe == PD_SET_MODE_PIPE_B)?1L:0L << 29);
+ internal_lvds_write_reg(pd_context, 0x61250, blc_pwm_ctl2, 0xFFFFFFFF, PD_REG_MIO);
+ reg_value = (calculation & 0xFFFF)<<16;
+ } else {
+ reg_value = ((calculation & 0xFFFE) |
+ pd_context->blm_legacy_mode)<<16;
+ }
+
+ /* The 16 LSB is a value that the user sets in configuration.
+ * user sets the value in percentage.
+ * We convert it into the clock speed */
+ percentage = ( pd_context->pwm_intensity * (unsigned long)calculation);
+ reg_value |= (unsigned long)( percentage / (int)100 ) & 0xFFFE;
+ internal_lvds_write_reg(pd_context, 0x61254, reg_value, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* set the flag so that we only do this function once */
+ pd_context->pwm_done = 1;
+ }
+#endif
+
+ if (state != PD_POWER_MODE_D0) {
+ /* Wait until the current power up/down sequence is complete */
+ i = 0;
+ while(internal_lvds_read_reg(pd_context, 0x61200, PD_REG_MIO) & 0x80000000L) {
+ i++;
+ if(i > 0x100000L) {
+ break;
+ }
+ }
+ internal_lvds_write_reg(pd_context, 0x61180, 0, BIT(31), PD_REG_MIO);
+ //pd_usleep(delay1*1000);
+ }
+
+#ifdef CONFIG_TNC
+#if 0
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS BKLT control. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN 0x20
+#define RGIO 0x24
+#define RGLVL 0x28
+#define TNC_LVDS_VDDEN BIT(0)
+#define TNC_LVDS_BKLTEN BIT(1)
+#define TNC_LVDS_BKLTCTL BIT(2)
+
+ if (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) {
+ unsigned long value;
+
+ /* Enable backlight for LVDS: based on observed si behavior:
+ * Subject to change based on si DE feedback */
+ if (state == PD_POWER_MODE_D0) {
+ value = TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL;
+ } else {
+ value = 0;
+ }
+ internal_lvds_write_reg(pd_context, RGEN, value,
+ TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+ internal_lvds_write_reg(pd_context, RGIO, value,
+ TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+ }
+#endif
+#endif
+
+ /* update power state */
+ pd_context->power_state = state;
+ return PD_SUCCESS;
+} /* internal_lvds_set_power */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_power
+ *
+ * Description:
+ * Returns the current LVDS power state back to the caller.
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] state: current power state
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_get_power (void *context, unsigned long *state)
+{ /* internal_lvds_get_power */
+ if ((NULL == context) || (NULL == state)) {
+ return PD_ERR_NULL_PTR;
+ }
+ PD_DEBUG("internal_lvds_get_power()\n");
+ /* The caller should be able to do this himself, but whatever */
+ *state = ((internal_lvds_context_t *) context)->power_state;
+ return PD_SUCCESS;
+} /* internal_lvds_get_power */
+
+int internal_lvds_save(void *context, void **state, unsigned long flags)
+{
+ *state = NULL;
+ return PD_SUCCESS;
+}
+
+int internal_lvds_restore(void *context, void *state, unsigned long flags)
+{
+ int ret = PD_SUCCESS;
+ return ret;
+}
+
+/*----------------------------------------------------------------------
+ * Function: internal_lvds_get_port_status()
+ *
+ * Description: It is called to get the information about the display
+ *
+ * Parameters: context - Port driver's context
+ * port_status - Returns the display type and connection state
+ *
+ * Return: PD_SUCCESS(0) success
+ * PD_ERR_XXXXXX otherwise
+ *----------------------------------------------------------------------*/
+int internal_lvds_get_port_status(void *context, pd_port_status_t *port_status)
+{
+ /* Display connection cannot be determined */
+ port_status->display_type = PD_DISPLAY_LVDS_INT;
+ port_status->connected = PD_DISP_STATUS_UNKNOWN;
+ return PD_SUCCESS;
+}
+
+static unsigned long internal_lvds_read_reg(internal_lvds_context_t *pd_context,unsigned long reg,
+ unsigned long reg_type)
+{
+ pd_reg_t list[2];
+ int ret;
+
+ list[0].reg = reg;
+ list[0].value = 0;
+ list[1].reg = PD_REG_LIST_END;
+ ret = pd_context->callback->read_regs(
+ pd_context->callback->callback_context, list, reg_type);
+ if (ret) {
+ PD_ERROR("LVDS read regs: Failed.");
+ }
+ return list[0].value;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_write_reg
+ *
+ * Description:
+ * Writes bits in "value" into a register. Bits written are dictated by
+ * the "change_bits" mask.
+ *
+ * Parameters:
+ * [IN] pd_context: device context, dispatcher to the actual write_reg
+ * function
+ * [IN] reg: register to write value to
+ * [IN] value: value to change the register to
+ * [IN] change_bits: bit mask, the bits set to "1" will be modified by
+ * the corresponding bits in "value"
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_write_reg(internal_lvds_context_t *pd_context, unsigned long reg,
+ unsigned long value,
+ unsigned long change_bits,
+ unsigned long reg_type)
+{ /* internal_lvds_write_reg */
+ pd_reg_t list[2];
+ int ret;
+
+ list[0].reg = reg;
+ list[0].value = (internal_lvds_read_reg(pd_context, reg, PD_REG_MIO) & ~change_bits) | value;
+ list[1].reg = PD_REG_LIST_END;
+ ret = pd_context->callback->write_regs(
+ pd_context->callback->callback_context, list, reg_type);
+ if (ret) {
+ PD_ERROR("LVDS write regs: Failed.");
+ }
+ return;
+} /* internal_lvds_write_reg */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_panel_fit
+ *
+ * Description:
+ * Enables panel fitting
+ *
+ * Parameters:
+ * [IN] pd_context: device context
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_panel_fit(internal_lvds_context_t *pd_context)
+{
+ /* enable auto vertical ratio */
+ /* enable auto horizantal ratio */
+ /* no dither */
+ unsigned long panel_fit_reg = 0x00000220;
+ PD_DEBUG("internal_lvds_panel_fit() \n");
+
+ PD_TRACE_ENTER;
+
+ if (pd_context->current_mode->width != pd_context->fp_width ||
+ pd_context->current_mode->height != pd_context->fp_height) {
+ /* Enable panel fitting */
+ /* vertical interpolation = bilinear */
+ /* horizontal interpolation = bilinear */
+ panel_fit_reg |= 0x80000440;
+ }
+ /* Enable dither based on default/user-set value:
+ * By default
+ * dither = 1 for 18-bit panels
+ * = 0 for 24-bit panels.
+ * But this behavior can be changed by setting the DITHER attribute.
+ * When user sets the attribute, dither will be updated
+ * as part of attribute processing in set attributes. */
+ /* For gn4 based chipsets dither is controlled in port_control register */
+ if (!pd_context->gn4_plus) {
+ /* Default behavior */
+ if (pd_context->panel_depth == 18) {
+ panel_fit_reg |= BIT(3);
+ }
+
+ /* Overwritten by set attribute */
+ if (pd_context->dither != 0xFFFF) {
+ if (pd_context->dither) {
+ panel_fit_reg |= BIT(3);
+ } else {
+ panel_fit_reg &= ~BIT(3);
+ }
+ }
+ }
+
+ if (pd_context->gn4_plus) {
+ unsigned long src_ratio, dest_ratio;
+ panel_fit_reg = 0;
+ if (pd_context->native_dtd &&
+ (pd_context->current_mode->width != pd_context->native_dtd->width ||
+ pd_context->current_mode->height !=
+ pd_context->native_dtd->height)) {
+ /* Enable panel fitter */
+ panel_fit_reg = 0x80000000;
+
+ /* Select the pipe */
+ if (pd_context->pipe & PD_SET_MODE_PIPE_B) {
+ panel_fit_reg |= BIT(29); /* bits[30:29] = 01 for pipe B */
+ }
+
+ /* Scaling mode:
+ * Default - Auto scaling src_ratio == dest_ratio
+ * Piller box scaling - src_ratio < dest_ratio
+ * Letter box scaling - src_ratio > dest_ratio */
+
+ /* To make this work correctly, port driver shall know the
+ * size of the framebuffer, not the src mode. Most of the
+ * times the src mode is fb, but not all the cases.
+ * User has an attribute to change
+ * 1. Between Pillerbox and auto, and vice versa
+ * and
+ * 2. Between Letterbox and auto, and vice versa.
+ */
+ if (pd_context->aspect_ratio) {
+ src_ratio = (pd_context->current_mode->width << 10)/
+ (pd_context->current_mode->height);
+ dest_ratio = (pd_context->native_dtd->width << 10)/
+ (pd_context->native_dtd->height);
+
+ if (dest_ratio > src_ratio) {
+ /* Pillarbox scaling */
+ panel_fit_reg |= BIT(27);
+ } else if (dest_ratio < src_ratio) {
+ /* Letterbox scaling */
+ panel_fit_reg |= BIT(27) | BIT(26);
+ }
+ }
+
+ /* Filter coefficient select: pd_context->text_tune = 0,1,2 */
+ panel_fit_reg |= (pd_context->text_tune << 24);
+ }
+ }
+
+ internal_lvds_write_reg(pd_context, 0x61230, panel_fit_reg, 0xFFFFFFFF, PD_REG_MIO);
+ PD_DEBUG("panel_fit_reg 0x61230 = 0x%lx", panel_fit_reg);
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_dclk
+ *
+ * Description:
+ * Gets the Dclk for LVDS
+ *
+ * Parameters:
+ * [IN] pd_context: device context
+ * [OUT]internal_lvds_info: Structure that contains the min and max dclk
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_get_dclk(internal_lvds_context_t *pd_context, pd_dvo_info_t *internal_lvds_info )
+{
+ PD_DEBUG("internal_lvds_get_dclk()\n");
+ /* Get the min and max dclks for lvds */
+ if (pd_context->dual_channel) {
+ internal_lvds_info->min_dclk = LVDS_MIN_DCLK * 2 ;
+ internal_lvds_info->max_dclk = LVDS_MAX_DCLK * 2;
+ } else {
+ internal_lvds_info->min_dclk = LVDS_MIN_DCLK;
+ internal_lvds_info->max_dclk = LVDS_MAX_DCLK;
+ }
+ PD_DEBUG("internal_lvds_dclk: #1\n");
+/* This #define is the result of code size reduction effort. */
+#ifdef CONFIG_CTG
+ /* Set dclk for GM965 */
+ if(pd_context->chipset==PCI_DEVICE_ID_VGA_CTG){
+ /* Set dclk for GM965/CTG */
+ if (pd_context->dual_channel) {
+ internal_lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+ internal_lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+ } else {
+ internal_lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+ internal_lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+ }
+ }
+#else
+
+ /* Set dclk for 915GM */
+ if(pd_context->chipset==PCI_DEVICE_ID_VGA_915AL){
+ if (pd_context->dual_channel) {
+ internal_lvds_info->min_dclk = LVDS_915GM_DUAL_MIN_DCLK ;
+ internal_lvds_info->max_dclk = LVDS_915GM_DUAL_MAX_DCLK;
+ } else {
+ internal_lvds_info->min_dclk = LVDS_915GM_SINGLE_MIN_DCLK;
+ internal_lvds_info->max_dclk = LVDS_915GM_SINGLE_MAX_DCLK;
+ }
+ } else if(pd_context->chipset==PCI_DEVICE_ID_VGA_945GM ||
+ pd_context->chipset==PCI_DEVICE_ID_VGA_945GME){
+ /* Set dclk for 945GM */
+ if (pd_context->dual_channel) {
+ internal_lvds_info->min_dclk = LVDS_945GM_DUAL_MIN_DCLK ;
+ internal_lvds_info->max_dclk = LVDS_945GM_DUAL_MAX_DCLK;
+ } else {
+ internal_lvds_info->min_dclk = LVDS_945GM_SINGLE_MIN_DCLK;
+ internal_lvds_info->max_dclk = LVDS_945GM_SINGLE_MAX_DCLK;
+ }
+ } else if(pd_context->chipset==PCI_DEVICE_ID_VGA_GM965 ||
+ pd_context->chipset==PCI_DEVICE_ID_VGA_GME965){
+ /* Set dclk for GM965 */
+ if (pd_context->dual_channel) {
+ internal_lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+ internal_lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+ } else {
+ internal_lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+ internal_lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+ }
+ }
+#endif
+
+#ifdef CONFIG_TNC
+ /* Get the min and max dclks for Atom E6xx lvds */
+ if ((pd_context->chipset == PCI_DEVICE_ID_VGA_TNC) ||
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0) ||
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_LNC)) {
+ internal_lvds_info->min_dclk = LVDS_TNC_SINGLE_MIN_DCLK;
+ /* Experimental feature to raise TC LVDS clk to 110MHz. */
+ if (pd_context->tc_110MHz_clk) {
+ internal_lvds_info->max_dclk = 110000L;
+ } else {
+ internal_lvds_info->max_dclk = LVDS_TNC_SINGLE_MAX_DCLK;
+ }
+ PD_DEBUG("internal_lvds_dclk: #2\n");
+ }
+#endif
+ PD_DEBUG("internal_lvds_dclk: at the end\n");
+}
+
+#pragma optimize ("",on)
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
new file mode 100644
index 0000000..f691d1a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
@@ -0,0 +1,170 @@
+/* -*- pse-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.h
+ * $Revision: 1.3 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is header file for Internal LVDS PORT DRIVER.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_LVDS_H
+#define _PD_LVDS_H
+
+#include <pd.h>
+
+#ifdef T_LINUX
+#include <pci.h>
+#endif
+
+/* Values received from DPG hardware engineer. These are for single channel. */
+
+#ifndef PCI_DEVICE_ID_VGA_855
+#define PCI_DEVICE_ID_VGA_855 0x3582
+#endif
+#ifndef PCI_DEVICE_ID_VGA_915AL
+#define PCI_DEVICE_ID_VGA_915AL 0x2592
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GM
+#define PCI_DEVICE_ID_VGA_945GM 0x27A2
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GME
+#define PCI_DEVICE_ID_VGA_945GME 0x27AE
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GM965
+#define PCI_DEVICE_ID_VGA_GM965 0x2A02
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GME965
+#define PCI_DEVICE_ID_VGA_GME965 0x2A12
+#endif
+#ifndef PCI_DEVICE_ID_VGA_CTG
+#define PCI_DEVICE_ID_VGA_CTG 0x2A42
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PLB
+#define PCI_DEVICE_ID_VGA_PLB 0x8108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PNVM
+#define PCI_DEVICE_ID_VGA_PNVM 0xA011
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC
+#define PCI_DEVICE_ID_VGA_TNC 0x4108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC_A0
+#define PCI_DEVICE_ID_VGA_TNC_A0 0x4100
+#endif
+#ifndef PCI_DEVICE_ID_VGA_LNC
+#define PCI_DEVICE_ID_VGA_LNC 0x4102
+#endif
+
+
+#define LVDS_MIN_DCLK 12000L /* in KHz */
+#define LVDS_MAX_DCLK 112000L /* in KHz */
+/* definition for 915GM */
+#define LVDS_915GM_SINGLE_MIN_DCLK 20000L
+#define LVDS_915GM_SINGLE_MAX_DCLK 112000L
+#define LVDS_915GM_DUAL_MIN_DCLK 25000L
+#define LVDS_915GM_DUAL_MAX_DCLK 224000L
+
+/* definition for 945GM */
+#define LVDS_945GM_SINGLE_MIN_DCLK 25000L
+#define LVDS_945GM_SINGLE_MAX_DCLK 112000L
+#define LVDS_945GM_DUAL_MIN_DCLK 25000L
+#define LVDS_945GM_DUAL_MAX_DCLK 224000L
+
+/* definition for GM965 */
+#define LVDS_GM965_SINGLE_MIN_DCLK 25000L
+#define LVDS_GM965_SINGLE_MAX_DCLK 112000L
+#define LVDS_GM965_DUAL_MIN_DCLK 25000L
+#define LVDS_GM965_DUAL_MAX_DCLK 224000L
+
+/* definition for Atom E6xx */
+#define LVDS_TNC_SINGLE_MIN_DCLK 19750L
+#define LVDS_TNC_SINGLE_MAX_DCLK 79500L
+
+#define LVDS_MIN(a, b) ((a)<(b)?(a):(b))
+
+/* Local attributes
+ * BIT15 of attribute Id specifies that it is a local attribute */
+#define LVDS_ATTR_ID_DATA_FORMAT (BIT(15)|1)
+#define LVDS_ATTR_ID_TC_LVDS_CLK (BIT(15)|2)
+
+/* Default values */
+#define LVDS_DEF_PANEL_DEPTH 18 /* Default panel depth */
+#define LVDS_DEF_DITHER 1 /* default=1 as default panel depth=18*/
+#define LVDS_DEF_SCALE_ON 1 /* Default scaling is on */
+#define LVDS_DEF_PANEL_FIT 1 /* Default panel fit in on */
+
+typedef struct _internal_lvds_context {
+ unsigned short fp_width;
+ unsigned short fp_height;
+ unsigned short dual_channel;
+ unsigned short panel_type;
+ unsigned short panel_fit;
+ unsigned short panel_depth;
+ unsigned short dither;
+ unsigned short aspect_ratio;
+ unsigned long text_tune;
+ unsigned long pwm_intensity;
+ unsigned long inverter_freq;
+ unsigned long blm_legacy_mode;
+
+ unsigned long power_state;
+ unsigned short chipset;
+ unsigned char init_done;
+ unsigned char num_attrs;
+ unsigned long pipe;
+ unsigned short gfx_freq;
+ unsigned char gn4_plus;
+ unsigned char pwm_done;
+ unsigned char tc_110MHz_clk;
+
+ pd_callback_t *callback;
+ pd_timing_t *timing_table;
+ pd_attr_t *attr_list;
+ pd_timing_t *native_dtd;
+ pd_timing_t *current_mode;
+} internal_lvds_context_t;
+
+extern int PD_MODULE_INIT(internal_lvds_init, (void *handle));
+extern int PD_MODULE_EXIT(internal_lvds_exit, (void));
+extern unsigned long internal_lvds_validate(unsigned long cookie);
+extern int internal_lvds_open(pd_callback_t *callback, void **context);
+extern int internal_lvds_init_device(void *context);
+extern int internal_lvds_close(void *context);
+extern int internal_lvds_set_mode(void *context, pd_timing_t *mode,
+ unsigned long flags);
+extern int internal_lvds_post_set_mode(void *context, pd_timing_t *mode,
+ unsigned long flags);
+extern int internal_lvds_set_attrs(void *context, unsigned long num, pd_attr_t *list);
+extern int internal_lvds_get_attrs(void *context, unsigned long*num, pd_attr_t **list);
+extern int internal_lvds_get_timing_list(void *context, pd_timing_t *in_list,
+ pd_timing_t **list);
+extern int internal_lvds_set_power(void *context, unsigned long state);
+extern int internal_lvds_get_power(void *context, unsigned long *state);
+extern int internal_lvds_save(void *context, void **state, unsigned long flags);
+extern int internal_lvds_restore(void *context, void *state, unsigned long flags);
+extern int internal_lvds_get_port_status(void *context, pd_port_status_t *port_status);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c b/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
new file mode 100644
index 0000000..a180772
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
@@ -0,0 +1,114 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: lpd.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Functions necessary to allow debug printing from the port drivers.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <igd_pd.h>
+#include <igd_pi.h>
+#include "pd_print.h"
+#include <memory.h>
+
+
+/*
+ * This file implements the pd debug printing functions using the OAL.
+ * In order to keep the OAL debug printing macro definitions in the OAL
+ * the DEBUG_BUILD_TYPE option must be set, even in a production build. The
+ * port drivers themselves must not call the pd debug printing functions
+ * in a release build. This enables the PD SDK to have debug printing from
+ * port drivers, even when using a release driver.
+ */
+#ifndef DEBUG_BUILD_TYPE
+#define DEBUG_BUILD_TYPE
+#endif
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <igd_debug.h>
+
+unsigned long *dropped_debug_messages;
+
+int pd_set_funcname( const char *name )
+{
+ os_set_funcname(name);
+ return 1;
+}
+
+int pd_print(const char *funcname, const int error,
+ const int error_exit, const char *format, ...)
+{
+#ifdef DEBUG_BUILD_TYPE
+ va_list ap;
+ unsigned int *blah;
+ char *priority = error ? KERN_ERR : EMGD_DEBUG_MSG_PRIORITY;
+ char *fmt = NULL;
+
+ /* Can't directly use the EMGD_DEBUG_S macro (because "format" is a string
+ * variable), so duplicate some of it here:
+ */
+ if (!(emgd_debug && emgd_debug-> MODULE_NAME)) {
+ return 0;
+ }
+
+ va_start(ap, format);
+ blah = (unsigned int *)ap;
+
+ if (error_exit) {
+ EMGD_DEBUG("EXIT With Error...");
+ }
+
+ /* Create a new format string, with all of the correct parts: */
+ fmt = OS_ALLOC(strlen(priority) + strlen(funcname) +
+ strlen(format) + 2);
+ if (fmt == NULL) {
+ printk(format, blah[0], blah[1], blah[2], blah[3], blah[4], blah[5],
+ blah[6], blah[7], blah[8], blah[9]);
+ } else {
+ sprintf(fmt, "%s%s %s", priority, funcname, format);
+ printk(fmt, blah[0], blah[1], blah[2], blah[3], blah[4], blah[5],
+ blah[6], blah[7], blah[8], blah[9]);
+ OS_FREE(fmt);
+ }
+ printk("\n");
+ va_end(ap);
+
+ return 0;
+#endif
+}
+
+void pd_trace_enter(const char *funcname)
+{
+ EMGD_DEBUG_S("%s ENTER", funcname);
+}
+
+void pd_trace_exit(const char *funcname)
+{
+ EMGD_DEBUG_S("%s EXIT", funcname);
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h b/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
new file mode 100644
index 0000000..8893e1b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_print.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Header file to get printing macros for port drivers
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_PRINT_H
+#define _PD_PRINT_H
+
+#include <config.h>
+
+extern int pd_print(const char *funcname, const int error,
+ const int error_exit, const char *format, ...);
+extern void pd_trace_enter(const char *funcname);
+extern void pd_trace_exit(const char *funcname);
+
+#ifdef DEBUG_BUILD_TYPE
+#define PD_DEBUG(arg...) pd_print(__FUNCTION__, 0, 0, arg)
+#define PD_ERROR(arg...) pd_print(__FUNCTION__, 1, 0, arg)
+#define PD_TRACE_ENTER pd_trace_enter(__FUNCTION__)
+#define PD_TRACE_EXIT pd_trace_exit(__FUNCTION__)
+#define PD_ERROR_EXIT(arg...) pd_print(__FUNCTION__, 1, 1, arg)
+#else
+#define PD_DEBUG(arg...)
+#define PD_ERROR(arg...)
+#define PD_TRACE_ENTER
+#define PD_TRACE_EXIT
+#define PD_ERROR_EXIT(arg...)
+#endif
+
+#define PD_OFFSETOF(t,m) ((unsigned long)&(((t *)0)->m))
+#if 0
+#define PD_OFFSETOF(t,m) offsetof(t,m)
+#endif
+
+#define PD_MODULE_INIT(func, params) func params
+#define PD_MODULE_EXIT(func, params) func params
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
new file mode 100644
index 0000000..fff6756
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
@@ -0,0 +1,1559 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.c
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file is contains all necessary functions for Internal
+ * LVDS PORT DRIVER.
+ * This is written according to the port interface defined in pd.h.
+ *-----------------------------------------------------------------------------
+ */
+#include <linux/kernel.h>
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+#include <linux/bug.h>
+#endif
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+#include "lvds.h"
+
+/* One space between the #define and the backslash,else compilers complain */
+#define PTR_OFFSET_UCHAR(ptr,offset) (*((unsigned char *)ptr + offset))
+#define PTR_OFFSET_USHORT(ptr, offset) (*(unsigned short *)((unsigned char *)ptr + offset))
+
+#define PTR_OFFSET_ULONG(ptr, offset) (*(unsigned long *)((unsigned char *)ptr + offset))
+/* END OF OPTIMIZATION MACROS */
+
+/* This constant = 10,000,000. The value is used to
+ * get effective results from the integer math, and
+ * to not divide by 0. */
+#define PWM_FREQ_CALC_CONSTANT_1 0x00989680
+/* This constant is 1,000,000 - to multiply to get
+ * the Display Clock Frequency to the order of Mhz */
+#define PWM_FREQ_CALC_CONSTANT_2 0x000F4240
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+static pd_version_t lvds_version = {11, 0, 0, 0}; /* driver version */
+static unsigned long lvds_dab_list[] = {
+ PD_DAB_LIST_END
+}; /* dab list */
+
+static unsigned long supported_chipset[] =
+{
+#ifdef CONFIG_855
+ PCI_DEVICE_ID_VGA_855,
+#endif
+#ifdef CONFIG_915AL
+ PCI_DEVICE_ID_VGA_915AL,
+#endif
+#ifdef CONFIG_945GM
+ PCI_DEVICE_ID_VGA_945GM,
+ PCI_DEVICE_ID_VGA_945GME,
+#endif
+#ifdef CONFIG_965GM
+ PCI_DEVICE_ID_VGA_GM965,
+ PCI_DEVICE_ID_VGA_GME965,
+#endif
+#ifdef CONFIG_CTG
+ PCI_DEVICE_ID_VGA_CTG,
+#endif
+#ifdef CONFIG_PLB
+ PCI_DEVICE_ID_VGA_PLB,
+#endif
+#ifdef CONFIG_TNC
+ PCI_DEVICE_ID_VGA_TNC,
+ PCI_DEVICE_ID_VGA_TNC_A0,
+ PCI_DEVICE_ID_VGA_LNC,
+#endif
+};
+
+static pd_driver_t lvds_driver = {
+ PD_SDK_VERSION,
+ "Internal LVDS Port Driver",
+ 0,
+ &lvds_version,
+ PD_DISPLAY_LVDS_INT,
+ PD_FLAG_UP_SCALING,
+ lvds_dab_list,
+ 100,
+ lvds_validate,
+ lvds_open,
+ lvds_init_device,
+ lvds_close,
+ lvds_set_mode,
+ lvds_post_set_mode,
+ lvds_set_attrs,
+ lvds_get_attrs,
+ lvds_get_timing_list,
+ lvds_set_power,
+ lvds_get_power,
+ lvds_save,
+ lvds_restore,
+ lvds_get_port_status
+};
+
+/* This is a common attribute table for all chipsets. At the end of the table
+ * there are multiple end entries to add chipset specific attributes.
+ * Chipset specific attributes:
+ * 965GM/GM45- Maintain aspect ratio
+ * Note:
+ * 1. Make sure to update the chipset_attr_index whenever adding a
+ * chipset specific new attr.
+ */
+static pd_attr_t lvds_attrs[] =
+{
+ /* Range attributes */
+
+ /*<-------ID-----------> <----TYPE--------> <---NAME-----> <----flag----> <---DEF_VAL----> <--CURR_VALUE--> min max st */
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T1, PD_ATTR_TYPE_RANGE, "FP Power T1", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T2, PD_ATTR_TYPE_RANGE, "FP Power T2", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T3, PD_ATTR_TYPE_RANGE, "FP Power T3", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T4, PD_ATTR_TYPE_RANGE, "FP Power T4", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 819, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T5, PD_ATTR_TYPE_RANGE, "FP Power T5", PD_ATTR_FLAG_USER_INVISIBLE, 400, 400, 0, 3000, 1),
+ PD_MAKE_ATTR (PD_ATTR_ID_PANEL_DEPTH, PD_ATTR_TYPE_RANGE, "Panel Depth", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_DEPTH, LVDS_DEF_PANEL_DEPTH, 18, 24, 6),
+
+ PD_MAKE_ATTR (PD_ATTR_ID_PWM_INTENSITY, PD_ATTR_TYPE_RANGE, "PWM cycle", PD_ATTR_FLAG_USER_INVISIBLE, 100, 0, 0, 100, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_INVERTER_FREQ, PD_ATTR_TYPE_RANGE, "Inverter Frequency", PD_ATTR_FLAG_USER_INVISIBLE, 100, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_BLM_LEGACY_MODE, PD_ATTR_TYPE_BOOL, "Backlight Legacy mode", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+ /*<-------ID------------> <----TYPE--------> <---NAME-----> <------flag---------------> <---DEF_VAL----> <--CURR_VALUE--> <---pad--> */
+ PD_MAKE_ATTR (PD_ATTR_ID_2_CHANNEL_PANEL, PD_ATTR_TYPE_BOOL, "Dual-channel panel", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_LVDS_PANEL_TYPE, PD_ATTR_TYPE_BOOL, "Panel Type", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_PANEL_FIT, PD_ATTR_TYPE_BOOL, "Panel Upscale", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_FIT,LVDS_DEF_PANEL_FIT,0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_DITHER, PD_ATTR_TYPE_BOOL, "Dither", PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_DITHER, LVDS_DEF_DITHER, 0, 0, 0),
+ PD_MAKE_ATTR (LVDS_ATTR_ID_TC_LVDS_CLK, PD_ATTR_TYPE_BOOL, "TC LVDS CLK 110MHz", PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+ /* Start of chipset specific attributes */
+ /* Maintain aspect ratio */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0),
+ /* Text tuning */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0),
+
+ /* Attribute list end */
+ PD_MAKE_ATTR (PD_ATTR_LIST_END, 0, "", 0, 0, 0, 0, 0, 0)
+};
+
+/* Rightnow it is -3 to reach starting of chipset specific attributes */
+static unsigned short chipset_attr_index = (unsigned short)
+ sizeof(lvds_attrs)/sizeof(pd_attr_t) - 3;
+
+static pd_attr_t lvds_965gm_attrs[] = {
+ PD_MAKE_ATTR (PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,PD_ATTR_TYPE_BOOL, "Maintain Aspect Ratio",0, 0, 0, 0, 0, 0),
+ PD_MAKE_ATTR (PD_ATTR_ID_TEXT_TUNING, PD_ATTR_TYPE_RANGE, "Text Enhancement", 0, 0, 0, 0, 2, 1),
+};
+
+static void lvds_write_reg(lvds_context_t *pd_context, unsigned long reg,
+ unsigned long value, unsigned long change_bits, unsigned long reg_type);
+
+static unsigned long lvds_read_reg(lvds_context_t *pd_context,
+ unsigned long reg, unsigned long reg_type);
+static void lvds_panel_fit(lvds_context_t *pd_context);
+
+static void lvds_get_dclk(lvds_context_t *pd_context, pd_dvo_info_t *lvds_info);
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_INIT(lvds_init)
+ *
+ * Description:
+ * This is the entry function into LVDS port driver when
+ * it first loads. This will call pd_register() to register
+ * with Display driver. Only the driver object is initialized in this
+ * function, similar to DrverEntry() in a WDM driver.
+ *
+ * Parameters:
+ * [OUT] *handle: Not used. Place holder for supporting dynamic pd
+ *
+ * Return:
+ * PD_SUCCESS(0) success
+ * PD_ERR_XXXXXX otherwise
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int PD_MODULE_INIT(lvds_init, (void *handle))
+{
+ /* register the LVDS driver */
+ return pd_register(handle, &lvds_driver);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_EXIT(lvds_exit, (void))
+ *
+ * Description:
+ * This function cleans up resources used by the LVDS driver
+ *
+ * Parameters:
+ * None
+ *
+ * Return:
+ * PD_SUCCESS(0): always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int PD_MODULE_EXIT(lvds_exit, (void))
+{
+ return PD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_validate
+ *
+ * Description:
+ * Place holder for a future function
+ *
+ * Parameters:
+ * TBD
+ *
+ * Return:
+ * TBD
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned long lvds_validate (unsigned long cookie)
+{ /* lvds_validate */
+ /* Validate magic cookie */
+ /* TODO: Implement the magic cookie algorithm */
+ return cookie;
+} /* lvds_validate */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_open
+ *
+ * Description:
+ * This function creates an LVDS context and intialize it with LVDS
+ * attributes.
+ *
+ * Internal LVDS port is available only on MGM platform, this port driver
+ * reads the GMCH device ID with pd_read_regs(PD_REG_PCI) to verify that
+ * it is supported on the current platform.
+ *
+ * Parameters:
+ * [IN] callback: callback context
+ * [INOUT] context: Device context. This function will set the attributes
+ * for this context, provided it is already allocated,
+ * i.e. not NULL.
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if either of the parameters is NULL
+ * PD_ERR_NODEV: if an LVDS device is already up and running
+ * PD_ERR_NOMEM: if a memory allocation failed
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* lvds context structure being declared and initialized */
+
+static lvds_context_t lvds_context = { /* lvds context structure */
+ 0, /* fp_width */
+ 0, /* fp_height */
+ 0, /* dual_channel: Default single channel */
+ 0, /* panel_type : 0-SPWG 1-OpenLDI*/
+ LVDS_DEF_PANEL_FIT, /* panel_fit */
+ LVDS_DEF_PANEL_DEPTH,/* panel_depth */
+ 0xFFFF, /* dither */
+ 0, /* Main aspect ratio, default no */
+ 0, /* panel filter: Default fuzzy filtering */
+ 100, /* PWM Intensity */
+ 0xFFFF, /* Inverter Frequency*/
+ 0, /* BLM Legacy Mode */
+
+ PD_POWER_MODE_D0, /* power_state */
+ 0, /* chipset */
+ 0, /* init_done */
+ 0, /* num_attrs */
+ 0, /* PIPE flags */
+ 0, /* Graphics Frequency */
+ 0, /* is gn4 based LVDS controller? */
+ 0, /* is pwm_done? */
+ 0, /* is tc_110MHz_clk? i.e., TC max LVDS to 110MHz*/
+
+ NULL, /* ptr to callback */
+ NULL, /* ptr to timing table */
+ lvds_attrs, /* ptr to attribute list */
+ NULL, /* ptr to native timing */
+ NULL, /* current mode */
+};
+
+int lvds_open(pd_callback_t *callback, void **context)
+{ /* lvds_open */
+ lvds_context_t *pd_context = (lvds_context_t*) &(lvds_context); /* static Global */
+ pd_reg_t reg_list[2];
+ int ret, i, valid_chipset = 0;
+ unsigned short chipset;
+
+ PD_TRACE_ENTER;
+
+
+
+ /* make sure parameters are valid */
+ if (!callback || !context) {
+ PD_ERROR("invalid parameter");
+ return (PD_ERR_NULL_PTR);
+ }
+ /* GMCH cannot support more than one device */
+ if (lvds_driver.num_devices > 0) {
+ return (PD_ERR_NODEV);
+ }
+ /* Verify that this is an GMCH with Internal LVDS available */
+ reg_list[0].reg = 2;
+ reg_list[1].reg = PD_REG_LIST_END;
+ ret = callback->read_regs(callback->callback_context, reg_list, PD_REG_PCI);
+ if(ret != PD_SUCCESS) {
+ return ret;
+ }
+ chipset = (unsigned short)(reg_list[0].value & 0xffff);
+ for (i = 0; i < ARRAY_SIZE(supported_chipset); i++) {
+ if (chipset == supported_chipset[i]){
+ valid_chipset = 1;
+ break;
+ }
+ }
+ if(!valid_chipset){
+ return PD_ERR_NODEV;
+ }
+
+ /* Special handling for gn4 and beyond chipsets */
+ if (chipset == PCI_DEVICE_ID_VGA_GM965 ||
+ chipset == PCI_DEVICE_ID_VGA_GME965 ||
+ chipset == PCI_DEVICE_ID_VGA_CTG ||
+ chipset == PCI_DEVICE_ID_VGA_TNC ||
+ chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ chipset == PCI_DEVICE_ID_VGA_LNC) {
+ lvds_context.gn4_plus = 1;
+ }
+
+ /* Initialize number of attributes */
+ /* +1 is to include the end attribute */
+ lvds_context.num_attrs = (unsigned char)chipset_attr_index + 1;
+
+ /* Add chipset specific attrbutes.
+ * This can be expanded into a switch statement in future if required. */
+ if (lvds_context.gn4_plus) {
+ lvds_context.num_attrs += sizeof(lvds_965gm_attrs)/sizeof(pd_attr_t);
+ for (i=0; i < sizeof(lvds_965gm_attrs)/sizeof(pd_attr_t); i++) {
+ lvds_attrs[chipset_attr_index+i] = lvds_965gm_attrs[i];
+ }
+ }
+ /* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+ /* pwm backlight control needs graphics frequency. we currently implement
+ * pwm backlight control for pouslbo only to limit the vbios lvds size. Each
+ * chipset have a different method of getting this value and chipset has a
+ * different multiplier. */
+ if (chipset == PCI_DEVICE_ID_VGA_PLB ||
+ chipset == PCI_DEVICE_ID_VGA_TNC ||
+ chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ chipset == PCI_DEVICE_ID_VGA_LNC) {
+
+ /* For plb/tnc, graphics frequency is obtained by sending an opcode to
+ * port 5 in the SCH Message Network. We call the read_regs with
+ * PD_REG_BRIDGE_OPCODE specifically for this purpose only.
+ *
+ * The input for this read_reg is the opcode that register data that
+ * we send into the Message control register*/
+ reg_list[1].reg = PD_REG_LIST_END;
+ ret = callback->read_regs(callback->callback_context,
+ reg_list, PD_REG_BRIDGE_OPCODE);
+ if(ret != PD_SUCCESS) {
+ return ret;
+ }
+
+ /*set the graphics frequency*/
+ pd_context->gfx_freq = (unsigned short) reg_list[0].value;
+ }
+#endif
+
+ pd_context->callback = callback; /* Save callback context */
+ pd_context->chipset = chipset; /* save the chipset ID */
+ *context = (void *) pd_context;
+
+ PD_TRACE_EXIT;
+ return PD_SUCCESS;
+} /* lvds_open */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_init_device
+ *
+ * Description:
+ * Initializes the LVDS device, using the device context from the parameter
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if parameter is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_init_device (void *context)
+{ /* lvds_init_device */
+ if (!context) {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ /* Don't need to do much to initialize this device */
+ ((lvds_context_t *)context)->init_done = 1;
+ lvds_driver.num_devices++;
+
+ return (PD_SUCCESS);
+} /* lvds_init_device */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_close
+ *
+ * Description:
+ * Releases resources allocated during lvds_open(). This function
+ * essentially frees a device object.
+ *
+ * Parameters:
+ * [INOUT] device_context: device to be freed
+ *
+ * Return:
+ * PD_SUCCESS: always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_close(void *device_context)
+{
+#ifndef CONFIG_MICRO
+
+ lvds_context_t *pd_context = (lvds_context_t *)device_context;
+
+ /* lvds_close */
+
+ PD_TRACE_ENTER;
+
+ /* Deallocate memory occupied by this device */
+ if (device_context) {
+ if ( NULL != pd_context->timing_table) {
+ pd_free(pd_context->timing_table);
+ pd_context->timing_table = NULL;
+ }
+
+ /* Free attribute list, if necessary */
+ /* FIXME -- The following test will never call pd_free(), because the
+ * expression "!lvds_driver.num_devices" will yield 0 or 1, and that
+ * will never be greater than 1. This is a potentially small memory
+ * leak, unless some other code frees it.
+ */
+ if (!lvds_driver.num_devices > 1) {
+ pd_free(pd_context->attr_list);
+ }
+ /* This allocated statically no need to free it */
+ /* pd_free(device_context); */
+ lvds_driver.num_devices--;
+ pd_context->init_done = 0;
+ }
+
+ PD_TRACE_EXIT;
+#endif
+ return (PD_SUCCESS);
+} /* lvds_close */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_mode
+ *
+ * Description:
+ * Sets LVDS to a new mode, specified by "mode".
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ * [IN] mode: information about the mode to switch to
+ * [IN] flags: can contain the following value
+ * PD_SET_MODE_FLAG_TEST: only testing to see if mode is supported
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if invalid parameter detected
+ * PD_ERR_MODE_NOTSUPP: if mode specified is not supported
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{
+ lvds_context_t *pd_context = NULL;
+
+ PD_DEBUG("lvds_set_mode)\n");
+ PD_TRACE_ENTER;
+
+ pd_context = (lvds_context_t *)context;
+
+ /* Make sure these parameters are valid */
+ if (!pd_context || !mode) {
+ return (PD_ERR_NULL_PTR);
+ }
+ PD_DEBUG("lvds_set_mode: %ux%u", mode->width, mode->height);
+
+ /* Make sure specified mode is supported */
+ if ((pd_context->fp_width && (mode->width > pd_context->fp_width)) ||
+ (pd_context->fp_height && (mode->height > pd_context->fp_height))) {
+ return PD_ERR_MODE_NOTSUPP;
+ }
+
+ /* Do nothing if we are only want to know if a mode is supported */
+ if (flags & PD_SET_MODE_FLAG_TEST) {
+ return PD_SUCCESS;
+ }
+
+ pd_context->current_mode = mode;
+ pd_context->pipe = flags;
+ /* Enable panel fitting and return */
+ lvds_panel_fit(pd_context);
+
+ PD_TRACE_EXIT;
+
+ return PD_SUCCESS;
+}
+
+int lvds_post_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{ /* lvds_set_mode */
+ lvds_context_t *pd_context = NULL;
+ unsigned long port_control = 0;
+ unsigned long preserve = 0;
+ int ret = 0;
+
+ PD_TRACE_ENTER;
+ pd_context = (lvds_context_t *)context;
+
+ PD_DEBUG("lvds_post_set_mode)\n");
+ /* Make sure these parameters are valide */
+ if (!pd_context || !mode) {
+ return (PD_ERR_NULL_PTR);
+ }
+
+ /* Before enabling the LVDS port, make sure that display PLL for this pipe
+ * is enabled and the port is power sequenced on using the panel power
+ * sequencing logic. */
+
+ preserve = 0x3E007803;
+ port_control = preserve & lvds_read_reg(pd_context, 0x61180, PD_REG_MIO);
+ port_control |= BIT(31); /* enable LVDS port */
+ if (flags & PD_SET_MODE_PIPE_B) {
+ port_control |= BIT(30);
+ }
+ port_control |= (BIT(9)|BIT(8)); /* power up */
+ port_control &= ~(BIT(21)|BIT(20)); /* Default sync polarites active high */
+
+ /* For gn4+, dither moved to port_control from panel_fit reg */
+ if (pd_context->gn4_plus) {
+ if (pd_context->panel_depth == 18) {
+ port_control |= BIT(25);
+ }
+
+ if (pd_context->dither != 0xFFFF) {
+ if (pd_context->dither) {
+ port_control |= BIT(25);
+ } else {
+ port_control &= ~BIT(25);
+ }
+ }
+ }
+
+ if((!pd_context->panel_fit) &&
+ ( mode->width < pd_context->fp_width ||
+ mode->height < pd_context->fp_height ) ){
+ port_control |= BIT(15); /* enable border in active for centering */
+ }
+
+ /*
+ * Bit 24 for OpenLDI should be set to a 0 (1x18.0, 2x18.0, 1x24.0, 2x24.0).
+ * From (B-Spec, Ref# 22316, section 1.15.3.8.3)
+ *
+ * Bit 24 for SPWG should be set to a 1 (1x24.1 or 2x24.1).
+ *
+ * This was verified by comparing the timing diagram for 1x24.0 in
+ * OpenLDI spec (5.4.2.2 24-bit Single Pixel Mode, Unbalanced) with the
+ * same diagram in the Display BSpec for Napa or Gen4.
+ * A0 A3 signals match the 1x24.0.
+ *
+ * From the OpenLDI spec (bit mappings are different):
+ *
+ * Table 5-2, Bit Number Mappings
+ * 18 bpp bit# 24 bpp bit# OpenLDI bit#
+ * 5 7 5
+ * 4 6 4
+ * 3 5 3
+ * 2 4 2
+ * 1 3 1
+ * 0 2 0
+ * 1 7
+ * 0 6
+ */
+
+ /* Attribute panel_type description:
+ * Attr ID Attr Value IntLVDS dataformat
+ * ======= =============== ==================
+ * 49 0 (SPWG) 1 (value of Bit 24)
+ * 49 1 (OpenLDI) 0 (value of Bit 24)
+ */
+ if (pd_context->panel_type == 0) {
+ port_control |= BIT(24); /* Dataformat 0 = SPWG, 1 = OpenLDI */
+ }
+
+ /* If the dual-channel is required, then power up second channel
+ * ClkB and B0, B1, B2, (B3) */
+ if (pd_context->dual_channel) {
+ port_control |= (BIT(5)|BIT(4)); /* ClkB */
+ port_control |= (BIT(3)|BIT(2)); /* B0, B1, B2, (B3) */
+ }
+
+ /* Check for 18 or 24 bit panel */
+ if (pd_context->panel_depth == 24) {
+ /* If the panel is 24-bit (8-bpp), enable A3, (B3) pair. */
+ port_control |= (BIT(7)|BIT(6));
+ }
+
+ /* Set the sync polarities correctly if there is a native dtd */
+ if (pd_context->native_dtd) {
+ /* Set bit 20 for hsync active low */
+ if ((pd_context->native_dtd->mode_info_flags & PD_HSYNC_HIGH) == 0) {
+ port_control |= BIT(20);
+ }
+ /* Set bit 21 for vsync active low */
+ if ((pd_context->native_dtd->mode_info_flags & PD_VSYNC_HIGH) == 0) {
+ port_control |= BIT(21);
+ }
+ }
+
+ lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+ lvds_write_reg(pd_context, 0x61180, port_control, 0xFFFFFFFF, PD_REG_MIO);
+ ret = lvds_set_power(pd_context, PD_POWER_MODE_D0);
+ if (ret) {
+ PD_ERROR("PD set_power (D0) returned: 0x%x", ret);
+ return ret;
+ }
+
+ lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+
+ PD_TRACE_EXIT;
+ /* Set the mode as per given timings */
+ return PD_SUCCESS;
+} /* lvds_set_mode */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_attrs
+ *
+ * Description:
+ * Incorporate attributes in "list" into the device context. This function
+ * will override the initial attributes set by init_attrs.
+ *
+ * Parameters:
+ * [INOUT] context: device context
+ * [IN] num: not used, but must not be 0.
+ * [IN] list: list of attributes to incorporate into device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_ERR_ATTR_CANT_CHANGE: attributes cannot be modified
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by Optimization Code. lvds_set_attrs() */
+typedef struct _opt_table_data {
+ unsigned long id;
+ unsigned short block;
+ unsigned short offset;
+} lvds_opt_table_data_t;
+static lvds_opt_table_data_t table_opt_data1[] = {
+
+ /*<--- id ----------> <---block---> <------ offset -------------------> */
+ {PD_ATTR_ID_PANEL_DEPTH, 1, PD_OFFSETOF(lvds_context_t, panel_depth) },
+
+ {PD_ATTR_ID_2_CHANNEL_PANEL, 1, PD_OFFSETOF(lvds_context_t, dual_channel)},
+ {PD_ATTR_ID_LVDS_PANEL_TYPE, 1, PD_OFFSETOF(lvds_context_t, panel_type) },
+ {PD_ATTR_ID_PANEL_FIT, 1, PD_OFFSETOF(lvds_context_t, panel_fit) },
+ {PD_ATTR_ID_DITHER, 1, PD_OFFSETOF(lvds_context_t, dither) },
+ {PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,1,PD_OFFSETOF(lvds_context_t,aspect_ratio)},
+ {PD_ATTR_ID_TEXT_TUNING, 1, PD_OFFSETOF(lvds_context_t, text_tune)},
+ {PD_ATTR_ID_PWM_INTENSITY, 1, PD_OFFSETOF(lvds_context_t, pwm_intensity)},
+ {PD_ATTR_ID_INVERTER_FREQ, 1, PD_OFFSETOF(lvds_context_t, inverter_freq)},
+ {PD_ATTR_ID_BLM_LEGACY_MODE, 1, PD_OFFSETOF(lvds_context_t, blm_legacy_mode)},
+ {LVDS_ATTR_ID_TC_LVDS_CLK, 1, PD_OFFSETOF(lvds_context_t, tc_110MHz_clk)},
+
+ /*<--- id ----------> <---block---> <------ offset -------------------> */
+ {PD_ATTR_ID_FP_PWR_T1, 2, 0 }, /* 6 */
+ {PD_ATTR_ID_FP_PWR_T2, 2, 0 }, /* 7 */
+ {PD_ATTR_ID_FP_PWR_T3, 2, 0 }, /* 8 */
+ {PD_ATTR_ID_FP_PWR_T4, 2, 0 }, /* 9 */
+ {PD_ATTR_ID_FP_PWR_T5, 2, 0 } /* 10 */
+};
+/* End of Tables required by Optimization Code. lvds_set_attrs() */
+
+int lvds_set_attrs (void *context, unsigned long num, pd_attr_t *list)
+{
+ lvds_context_t *pd_context = (lvds_context_t *) context;
+ pd_attr_t *attr = NULL;
+ unsigned short i = 0;
+ unsigned short j = 0;
+ int ret = PD_SUCCESS;
+ /* no of case IDs in the global table */
+ int num_case_ids = sizeof(table_opt_data1)/sizeof(lvds_opt_table_data_t);
+
+ /* basic parameter check */
+ if (!context || !num || !list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ PD_DEBUG("lvds_set_attrs()\n");
+ for (i = 0; i < num; i++, list++) {
+ /* do nothing if the attribute has not been changed */
+ if (!(list->flags & PD_ATTR_FLAG_VALUE_CHANGED)) {
+ continue;
+ }
+
+ /* attributes can't be changed after init has been completed */
+ if (list->flags & PD_ATTR_FLAG_USER_INVISIBLE &&
+ pd_context->init_done) {
+ return PD_ERR_ATTR_CANT_CHANGE;
+ }
+
+ /* Set the internal attributes' list. Note that although get_attr() can
+ * return NULL theortically, it will not do so here because all the
+ * attribute IDs in this switch statement comes from lvds_attrs[],
+ * a list that is automatically initialized into pd_context. This is
+ * why we are not checking for NULL after calling get_attr().
+ */
+#if 0 /* ORIGINAL SWITCH STATEMENT */
+ switch (list->id) {
+ case PD_ATTR_ID_FP_PWR_T1:
+ case PD_ATTR_ID_FP_PWR_T2:
+ case PD_ATTR_ID_FP_PWR_T3:
+ case PD_ATTR_ID_FP_PWR_T4:
+ case PD_ATTR_ID_FP_PWR_T5:
+ /* current_value should not exceed the predefined max value */
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = LVDS_MIN(
+ ((pd_range_attr_t *)list)->current_value,
+ attr->_pad1);
+ break;
+
+ case PD_ATTR_ID_PANEL_DEPTH:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = list->current_value;
+ pd_context->panel_depth = (unsigned char) attr->current_value;
+ break;
+
+ case PD_ATTR_ID_2_CHANNEL_PANEL:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->dual_channel = (attr->current_value?1:0);
+ break;
+
+ case PD_ATTR_ID_LVDS_PANEL_TYPE:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->panel_type = (attr->current_value?1:0);
+ break;
+
+ case PD_ATTR_ID_PANEL_FIT:
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+ pd_context->panel_fit = (attr->current_value?1:0);
+ break;
+
+ default:
+ /* do nothing if we have an unknown ID */
+ break;
+ }
+#endif
+ /* OPTIMIZATION CODE BEGINS FOR THE ABOVE SWITCH
+ *----------------------------------------------
+ * Step 1: First identify the code common to all case blocks.
+ * This we call it "common code block" Since this is to be
+ * executed by all the case blocks.
+ *
+ * Step 2: Group the cases into blocks based on how we can combine them
+ *
+ * Eg: case 0: ptr->x = 1; break; // similar code
+ * case 1: ptr->y = 1; break; // similar code
+ * ------Combined block ----
+ * case 0:
+ * case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+ * This is an important step because we save code space by
+ * mapping many cases to smaller number of blocks. In the above
+ * we use index to get the right offset of the ptr.
+ *
+ * Step 3: Assign block IDs to each block. Put the case ID, block ID
+ * and other information such as offsets of ptr in a global
+ * table.
+ *
+ * Step 4: During run-time , search through the global table, find the
+ * matching case ID, and execute the common code. Next get the
+ * block ID and execute the block specific code. For the index,
+ * retrieve it from the table for the corresponding case ID.
+ *
+ * Step 5: If no matching case ID is found, error it out.
+ *
+ * Let's look at the optimization code for the above switch.
+ * The code below searches for the list->id in a global table where
+ * we store all the case values along with block numbers and other
+ * information. After we find a valid id in the table , we execute the
+ * common code for all cases first and then we retrieve the block id.
+ * The block id is necesary to determine which block does the id belong
+ * to. This is used to execute block specific code. Similar to switch
+ * cases ONLY here we try to minimize the no of blocks.
+ *
+ * In this example , we store the offsets of field names of a ptr in the
+ * global table.This is necessary to combine cases with "similar" but
+ * not "same" codes.
+ *
+ * Eg: case 0: ptr->x = 1; break; // similar code
+ * case 1: ptr->y = 1; break; // similar code
+ * -- Combined block ----
+ * case 0:
+ * case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+ *
+ * By reducing the number of blocks we save on Code space. After we
+ * finish our work , we exit the for loop and check for invalid ID
+ * passed by the upper layer. This is akin to default in the
+ * switch block
+ *
+ * CAUTION: If there is any change in the switch above, this code
+ * along with the tables have to be re-written and changed according
+ * to the new behaviour of the switch. Examples include adding a new
+ * case in the switch. The reason for all this mumbo-jumbo is to
+ * reduce code size in VBIOS, where we are running out of code space.
+ */
+ for(j = 0; j < num_case_ids; j++) {
+ /* Search for the attribute ID in the global table */
+ if(list->id == table_opt_data1[j].id) {
+ /* Run the common code for all the blocks */
+ attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+ list->id, 0);
+ /* Once we get a valid ID, need to find out which block it
+ * belongs so we can execute block specific code.
+ */
+ if(table_opt_data1[j].block == 1) { /* block 1 */
+ /* Got the block. Need the offset to the struct for that ID
+ * so we can store value at corresponding offset to get the
+ * desired behaviour for that ID.This is the code that makes
+ * the whole optimization work because we are combining the
+ * case IDs into a single block which saves code.
+ */
+ attr->current_value = list->current_value;
+ PTR_OFFSET_USHORT(pd_context, table_opt_data1[j].offset) =
+ (unsigned short) attr->current_value;
+
+ } else { /* block 2. We only have two blocks. */
+ attr->current_value = LVDS_MIN(
+ list->current_value, ((pd_range_attr_t *)attr)->max);
+ }
+ break; /* We found a valid ID, so break inner for loop */
+ }
+ }
+ }
+ /* panel_type 0 (SPWG) isn't available for 18-bit depth */
+ PD_DEBUG("in LVDS_set_attributes()\n");
+ if (pd_context->panel_depth == 18) {
+ pd_context->panel_type = 1;
+ }
+ PD_DEBUG("IntLVDS: dual_channel=%u", pd_context->dual_channel);
+ PD_DEBUG("IntLVDS: panel_type=%u panel_fit=%u panel_dep=%u dither=%u",
+ pd_context->panel_type, pd_context->panel_fit,
+ pd_context->panel_depth, pd_context->dither);
+ PD_DEBUG("IntLVDS: keep_aspect_ratio=%u text_tune=%lu",
+ pd_context->aspect_ratio, pd_context->text_tune);
+ PD_DEBUG("IntLVDS: PWM Intensity=%u Inverter Freq=%u, BLM legacy mode =%u",
+ pd_context->pwm_intensity, pd_context->inverter_freq,
+ pd_context->blm_legacy_mode);
+ PD_DEBUG("IntLVDS: tc_110MHz_clk = %u", pd_context->tc_110MHz_clk);
+
+ if (pd_context->init_done) {
+ /* When emgd_driver_pre_init() pokes new attrs into this port driver,
+ * pd_context->current_mode must be set before calling
+ * lvds_panel_fit(), so set it to the first entry in the timing table:
+ */
+ if (pd_context->current_mode == NULL) {
+ pd_context->current_mode = pd_context->timing_table;
+ }
+ lvds_panel_fit(pd_context);
+ }
+
+ return ret;
+} /* lvds_set_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_attrs
+ *
+ * Description:
+ * Extracts the attribute list and the number of elements in the list
+ * from the device context.
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] num: number of elements in list
+ * [OUT] list: list of attributes from the device context
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_get_attrs (void *context, unsigned long *num, pd_attr_t **list)
+{ /* lvds_get_attrs */
+ /* basic parameter check */
+ if (!context || !num || !list) {
+ return PD_ERR_NULL_PTR;
+ }
+
+ PD_DEBUG("lvds_get_attrs()\n");
+ /* Nothing fancy, just extracting the elements from the list */
+ *list = ((lvds_context_t *)context)->attr_list;
+ *num = ((lvds_context_t *)context)->num_attrs;
+
+ return PD_SUCCESS;
+} /* lvds_get_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_timing_list
+ *
+ * Description:
+ *
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] in_list:
+ * [OUT] list:
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_ERR_NOMEM: if internal memory allocate failed
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_get_timing_list (void *context, pd_timing_t *in_list,
+ pd_timing_t **list)
+{ /* lvds_get_timing_list */
+ lvds_context_t *pd_context = (lvds_context_t *)context;
+ pd_dvo_info_t lvds_info = {0, 0, 1, 0, 0, 0, 0, 0};
+ pd_display_info_t lvds_display_info = {0, 0, 0, 0, NULL};
+ int ret;
+
+ PD_DEBUG("lvds_get_timing_list()\n");
+ lvds_get_dclk( pd_context, &lvds_info );
+
+ PD_DEBUG("chipset = 0x%x", pd_context->chipset);
+ lvds_display_info.panel_fit = (unsigned char) pd_context->panel_fit;
+ ret = pd_filter_timings(pd_context->callback->callback_context,
+ in_list, &pd_context->timing_table, &lvds_info, &lvds_display_info);
+
+ /* Helper function will return the below values */
+ pd_context->native_dtd = lvds_display_info.native_dtd;
+ pd_context->fp_width = lvds_display_info.width;
+ pd_context->fp_height = lvds_display_info.height;
+
+ *list = pd_context->timing_table;
+ return ret;
+} /* lvds_get_timing_list */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_power
+ *
+ * Description:
+ * Sets LVDS to the specified power state
+ *
+ * Conversion between IEGD timer values to LVDS port timer values
+ *
+ * SEPG(?) IEGD LVDS Port Program bits min max
+ * ---- ------- ------------ ---------------- ------ ---------
+ * T1+T2 T1 ms T1+T2 100us 0x61208 [28:16] 0 ms 819.2 ms
+ * T5 T2 ms T5 100us 0x61208 [12:00] 0 ms 819.2 ms
+ * T6 T3 ms Tx 100us 0x6120C [12:00] 0 ms 819.2 ms
+ * T3 T4 ms T3 100us 0x6120C [28:16] 0 ms 819.2 ms
+ * T4 T5 ms T4 100ms 0x61210 [04:00] 0 ms 3200 ms
+ *
+ * Reg = Value
+ * ------ -------
+ * 0x61208 = [T1 T2]
+ * 0x6120C = [T4 T3]
+ * 0x61210 = [ T5]
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] in_list:
+ * [OUT] list:
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if context is NULL
+ * PD_ERR_INVALID_POWER: if "state" is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by the optimization codes in lvds_set_power() */
+typedef struct {
+ unsigned char id1;
+ unsigned char id2;
+ unsigned char bit;
+ unsigned long reg;
+} opt_set_power_t;
+
+static opt_set_power_t table_set_power[] = {
+ /* id1 id2 bit reg */
+ { PD_ATTR_ID_FP_PWR_T1, PD_ATTR_ID_FP_PWR_T2, 1, 0x61208 }, /* D0 */
+ { PD_ATTR_ID_FP_PWR_T4, PD_ATTR_ID_FP_PWR_T3, 0, 0x6120C }, /* Dx */
+};
+
+int lvds_set_power(void *context, unsigned long state)
+{ /* lvds_set_power */
+ unsigned long i = 0;
+ lvds_context_t *pd_context = (lvds_context_t *)context;
+ pd_attr_t *tattr = NULL; /* holds time delay b/ pwr transition */
+ unsigned long delay = 0, delay1;
+
+ PD_DEBUG("state = %lu", state);
+
+ PD_DEBUG("lvds_set_power() to state = %lu\n",state);
+ /* Basic parameter check */
+ if (!context) {
+ PD_DEBUG("No context");
+ return PD_ERR_NULL_PTR;
+ }
+ PD_DEBUG("pd_context=0x%lx", (unsigned long)pd_context);
+
+ /* Check for invalid state */
+ if (state > PD_POWER_MODE_D3) {
+ PD_DEBUG("Invalid power state");
+ return PD_ERR_INVALID_POWER;
+ }
+
+ /* Get the index into above table */
+ if (state == PD_POWER_MODE_D0) {
+ i = 0;
+ } else {
+ i = 1;
+ }
+
+ lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* Program panel power up/down delays: Either T1/T2 or T3/T4*/
+ tattr = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, table_set_power[i].id1, 0);
+ /* Convert ms to 100us */
+ delay1 = tattr->current_value;
+ delay = (tattr->current_value * 10) << 16;
+ tattr = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, table_set_power[i].id2, 0);
+ delay1 += tattr->current_value;
+ delay |= tattr->current_value * 10;
+
+ lvds_write_reg(pd_context, table_set_power[i].reg, delay, 0x1FFF1FFF, PD_REG_MIO);
+
+ /* Program power cycle delay: convert ms to 100ms */
+ delay = pd_get_attr(pd_context->attr_list,
+ pd_context->num_attrs, PD_ATTR_ID_FP_PWR_T5, 0)->current_value;
+ delay1 += delay;
+ /* TODO: Write reference divider [31:8] */
+ delay = ((delay/100+1) & 0xFF) | ((pd_context->gfx_freq*100/2-1)<<8);
+ lvds_write_reg(pd_context, 0x61210, delay, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* Power state target */
+ lvds_write_reg(pd_context, 0x61204, table_set_power[i].bit, BIT(0), PD_REG_MIO);
+
+ /* Power down on reset available on crestline onwards */
+ lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+ /* PWM is a method of controlling the backlight intensity.
+ * It is not method to turn on baclkight.
+ * We still need the PD method to turn on the backlight.
+ *
+ * This feature is for Pouslbo Only. We check that the user has set the
+ * inverter frequency. Default intensity, if not set, is 100%
+ *
+ * Due to the high amount of calculation, we want to only set this register
+ * if it has not been ser previously. The register could be
+ * "brought forward" from VBIOS.
+ */
+ if(pd_context->inverter_freq != 0xFFFF && /* Overwritten by set_attr */
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_PLB ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) &&
+ !pd_context->pwm_done) {
+ unsigned long reg_value = 0;
+ unsigned long percentage = 0;
+ unsigned long calculation = 0;
+ unsigned long blc_pwm_ctl2 = 0;
+
+ /* We first need to get the graphics frequency, which will be used to
+ * calculate Backlight Modulation Frequency[BMF]. BMF will be used to
+ * fill up the 15 MSB in the 0x61254 register
+ *
+ * The calculation for the Modulation Frequency field in the
+ * BLC_PWM_CTL Register is:
+ *
+ * Reference Clock Freq 1
+ * ----------------------- x ------------------
+ * Divider PWM Freq in Hz
+ *
+ */
+#if 0
+ /* GMA accurate calculation that requires "calculation" to be an
+ * unsigned long long typedef */
+ calculation = pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2;
+ calculation = calculation / 0x20; /*pouslbo specific divider*/
+ calculation = calculation * PWM_FREQ_CALC_CONSTANT_1;
+ calculation = calculation / pd_context->inverter_freq;
+ calculation = calculation / PWM_FREQ_CALC_CONSTANT_1;
+#endif
+ /* Some system bios cannot take 64 bit data type. Using a more
+ * simplified calculation that is not too accurate if the inputs
+ * are not round numbers */
+ calculation = pd_context->inverter_freq * 0x20; /* plb/tnc divider */
+ calculation = (pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2) /
+ calculation;
+
+ /* Writing the register: 15 MSB is the max lvds clock / 32.
+ * Bit 16 can either be legacy or non legacy depending upon Attr #72. */
+ if (pd_context->gn4_plus) {
+ blc_pwm_ctl2 = (1L << 31) |
+ (pd_context->blm_legacy_mode << 30) |
+ ((pd_context->pipe == PD_SET_MODE_PIPE_B)?1L:0L << 29);
+ lvds_write_reg(pd_context, 0x61250, blc_pwm_ctl2, 0xFFFFFFFF, PD_REG_MIO);
+ reg_value = (calculation & 0xFFFF)<<16;
+ } else {
+ reg_value = ((calculation & 0xFFFE) |
+ pd_context->blm_legacy_mode)<<16;
+ }
+
+ /* The 16 LSB is a value that the user sets in configuration.
+ * user sets the value in percentage.
+ * We convert it into the clock speed */
+ percentage = ( pd_context->pwm_intensity * (unsigned long)calculation);
+ reg_value |= (unsigned long)( percentage / (int)100 ) & 0xFFFE;
+ lvds_write_reg(pd_context, 0x61254, reg_value, 0xFFFFFFFF, PD_REG_MIO);
+
+ /* set the flag so that we only do this function once */
+ pd_context->pwm_done = 1;
+ }
+#endif
+
+ if (state != PD_POWER_MODE_D0) {
+ /* Wait until the current power up/down sequence is complete */
+ i = 0;
+ while(lvds_read_reg(pd_context, 0x61200, PD_REG_MIO) & 0x80000000L) {
+ i++;
+ if(i > 0x100000L) {
+ break;
+ }
+ }
+ lvds_write_reg(pd_context, 0x61180, 0, BIT(31), PD_REG_MIO);
+ }
+
+#ifdef CONFIG_TNC
+#if 0
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS BKLT control. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN 0x20
+#define RGIO 0x24
+#define RGLVL 0x28
+#define TNC_LVDS_VDDEN BIT(0)
+#define TNC_LVDS_BKLTEN BIT(1)
+#define TNC_LVDS_BKLTCTL BIT(2)
+
+ if (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+ pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) {
+ unsigned long value;
+
+ /* Enable backlight for LVDS: based on observed si behavior:
+ * Subject to change based on si DE feedback */
+ if (state == PD_POWER_MODE_D0) {
+ value = TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL;
+ } else {
+ value = 0;
+ }
+ lvds_write_reg(pd_context, RGEN, value,
+ TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+ lvds_write_reg(pd_context, RGIO, value,
+ TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+ }
+#endif
+#endif
+
+ /* update power state */
+ pd_context->power_state = state;
+ return PD_SUCCESS;
+} /* lvds_set_power */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_power
+ *
+ * Description:
+ * Returns the current LVDS power state back to the caller.
+ *
+ * Parameters:
+ * [IN] context: device context to extract information from
+ * [OUT] state: current power state
+ *
+ * Return:
+ * PD_ERR_NULL_PTR: if one of the parameters is invalid
+ * PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_get_power (void *context, unsigned long *state)
+{ /* lvds_get_power */
+ if ((NULL == context) || (NULL == state)) {
+ return PD_ERR_NULL_PTR;
+ }
+ PD_DEBUG("lvds_get_power()\n");
+ /* The caller should be able to do this himself, but whatever */
+ *state = ((lvds_context_t *) context)->power_state;
+ return PD_SUCCESS;
+} /* lvds_get_power */
+
+int lvds_save(void *context, void **state, unsigned long flags)
+{
+ *state = NULL;
+ return PD_SUCCESS;
+}
+
+int lvds_restore(void *context, void *state, unsigned long flags)
+{
+ int ret = PD_SUCCESS;
+ return ret;
+}
+
+/*----------------------------------------------------------------------
+ * Function: lvds_get_port_status()
+ *
+ * Description: It is called to get the information about the display
+ *
+ * Parameters: context - Port driver's context
+ * port_status - Returns the display type and connection state
+ *
+ * Return: PD_SUCCESS(0) success
+ * PD_ERR_XXXXXX otherwise
+ *----------------------------------------------------------------------*/
+int lvds_get_port_status(void *context, pd_port_status_t *port_status)
+{
+ /* Display connection cannot be determined */
+ port_status->display_type = PD_DISPLAY_LVDS_INT;
+ port_status->connected = PD_DISP_STATUS_UNKNOWN;
+ return PD_SUCCESS;
+}
+
+static unsigned long lvds_read_reg(lvds_context_t *pd_context,unsigned long reg,
+ unsigned long reg_type)
+{
+ pd_reg_t list[2];
+ int ret;
+
+ list[0].reg = reg;
+ list[0].value = 0;
+ list[1].reg = PD_REG_LIST_END;
+ ret = pd_context->callback->read_regs(
+ pd_context->callback->callback_context, list, reg_type);
+ if (ret) {
+ PD_ERROR("LVDS read regs: Failed.");
+ }
+ return list[0].value;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_write_reg
+ *
+ * Description:
+ * Writes bits in "value" into a register. Bits written are dictated by
+ * the "change_bits" mask.
+ *
+ * Parameters:
+ * [IN] pd_context: device context, dispatcher to the actual write_reg
+ * function
+ * [IN] reg: register to write value to
+ * [IN] value: value to change the register to
+ * [IN] change_bits: bit mask, the bits set to "1" will be modified by
+ * the corresponding bits in "value"
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_write_reg(lvds_context_t *pd_context, unsigned long reg,
+ unsigned long value,
+ unsigned long change_bits,
+ unsigned long reg_type)
+{ /* lvds_write_reg */
+ pd_reg_t list[2];
+ int ret;
+
+ PD_DEBUG("ENTER");
+
+ list[0].reg = reg;
+ list[0].value = (lvds_read_reg(pd_context, reg, PD_REG_MIO) & ~change_bits) | value;
+ list[1].reg = PD_REG_LIST_END;
+ ret = pd_context->callback->write_regs(
+ pd_context->callback->callback_context, list, reg_type);
+ if (ret) {
+ PD_ERROR("LVDS write regs: Failed.");
+ }
+ PD_DEBUG("EXIT");
+ return;
+} /* lvds_write_reg */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_panel_fit
+ *
+ * Description:
+ * Enables panel fitting
+ *
+ * Parameters:
+ * [IN] pd_context: device context
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_panel_fit(lvds_context_t *pd_context)
+{
+ /* enable auto vertical ratio */
+ /* enable auto horizantal ratio */
+ /* no dither */
+ unsigned long panel_fit_reg = 0x00000220;
+ PD_DEBUG("lvds_panel_fit() \n");
+
+ PD_TRACE_ENTER;
+
+ if (pd_context->current_mode->width != pd_context->fp_width ||
+ pd_context->current_mode->height != pd_context->fp_height) {
+ /* Enable panel fitting */
+ /* vertical interpolation = bilinear */
+ /* horizontal interpolation = bilinear */
+ panel_fit_reg |= 0x80000440;
+ }
+ /* Enable dither based on default/user-set value:
+ * By default
+ * dither = 1 for 18-bit panels
+ * = 0 for 24-bit panels.
+ * But this behavior can be changed by setting the DITHER attribute.
+ * When user sets the attribute, dither will be updated
+ * as part of attribute processing in set attributes. */
+ /* For gn4 based chipsets dither is controlled in port_control register */
+ if (!pd_context->gn4_plus) {
+ /* Default behavior */
+ if (pd_context->panel_depth == 18) {
+ panel_fit_reg |= BIT(3);
+ }
+
+ /* Overwritten by set attribute */
+ if (pd_context->dither != 0xFFFF) {
+ if (pd_context->dither) {
+ panel_fit_reg |= BIT(3);
+ } else {
+ panel_fit_reg &= ~BIT(3);
+ }
+ }
+ }
+
+ if (pd_context->gn4_plus) {
+ unsigned long src_ratio, dest_ratio;
+ panel_fit_reg = 0;
+ if (pd_context->native_dtd &&
+ (pd_context->current_mode->width != pd_context->native_dtd->width ||
+ pd_context->current_mode->height !=
+ pd_context->native_dtd->height)) {
+ /* Enable panel fitter */
+ panel_fit_reg = 0x80000000;
+
+ /* Select the pipe */
+ if (pd_context->pipe & PD_SET_MODE_PIPE_B) {
+ panel_fit_reg |= BIT(29); /* bits[30:29] = 01 for pipe B */
+ }
+
+ /* Scaling mode:
+ * Default - Auto scaling src_ratio == dest_ratio
+ * Piller box scaling - src_ratio < dest_ratio
+ * Letter box scaling - src_ratio > dest_ratio */
+
+ /* To make this work correctly, port driver shall know the
+ * size of the framebuffer, not the src mode. Most of the
+ * times the src mode is fb, but not all the cases.
+ * User has an attribute to change
+ * 1. Between Pillerbox and auto, and vice versa
+ * and
+ * 2. Between Letterbox and auto, and vice versa.
+ */
+ if (pd_context->aspect_ratio) {
+ src_ratio = (pd_context->current_mode->width << 10)/
+ (pd_context->current_mode->height);
+ dest_ratio = (pd_context->native_dtd->width << 10)/
+ (pd_context->native_dtd->height);
+
+ if (dest_ratio > src_ratio) {
+ /* Pillarbox scaling */
+ panel_fit_reg |= BIT(27);
+ } else if (dest_ratio < src_ratio) {
+ /* Letterbox scaling */
+ panel_fit_reg |= BIT(27) | BIT(26);
+ }
+ }
+
+ /* Filter coefficient select: pd_context->text_tune = 0,1,2 */
+ panel_fit_reg |= (pd_context->text_tune << 24);
+ }
+ }
+
+ lvds_write_reg(pd_context, 0x61230, panel_fit_reg, 0xFFFFFFFF, PD_REG_MIO);
+ PD_DEBUG("panel_fit_reg 0x61230 = 0x%lx", panel_fit_reg);
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_dclk
+ *
+ * Description:
+ * Gets the Dclk for LVDS
+ *
+ * Parameters:
+ * [IN] pd_context: device context
+ * [OUT]lvds_info: Structure that contains the min and max dclk
+ *
+ * Return:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_get_dclk(lvds_context_t *pd_context, pd_dvo_info_t *lvds_info )
+{
+ PD_DEBUG("lvds_get_dclk()\n");
+ /* Get the min and max dclks for lvds */
+ if (pd_context->dual_channel) {
+ lvds_info->min_dclk = LVDS_MIN_DCLK * 2 ;
+ lvds_info->max_dclk = LVDS_MAX_DCLK * 2;
+ } else {
+ lvds_info->min_dclk = LVDS_MIN_DCLK;
+ lvds_info->max_dclk = LVDS_MAX_DCLK;
+ }
+/* This #define is the result of code size reduction effort. */
+#ifdef CONFIG_CTG
+ /* Set dclk for GM965 */
+ if(pd_context->chipset==PCI_DEVICE_ID_VGA_CTG){
+ /* Set dclk for GM965/CTG */
+ if (pd_context->dual_channel) {
+ lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+ lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+ } else {
+ lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+ lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+ }
+ }
+#else
+
+ /* Set dclk for 915GM */
+ if(pd_context->chipset==PCI_DEVICE_ID_VGA_915AL){
+ if (pd_context->dual_channel) {
+ lvds_info->min_dclk = LVDS_915GM_DUAL_MIN_DCLK ;
+ lvds_info->max_dclk = LVDS_915GM_DUAL_MAX_DCLK;
+ } else {
+ lvds_info->min_dclk = LVDS_915GM_SINGLE_MIN_DCLK;
+ lvds_info->max_dclk = LVDS_915GM_SINGLE_MAX_DCLK;
+ }
+ } else if(pd_context->chipset==PCI_DEVICE_ID_VGA_945GM ||
+ pd_context->chipset==PCI_DEVICE_ID_VGA_945GME){
+ /* Set dclk for 945GM */
+ if (pd_context->dual_channel) {
+ lvds_info->min_dclk = LVDS_945GM_DUAL_MIN_DCLK ;
+ lvds_info->max_dclk = LVDS_945GM_DUAL_MAX_DCLK;
+ } else {
+ lvds_info->min_dclk = LVDS_945GM_SINGLE_MIN_DCLK;
+ lvds_info->max_dclk = LVDS_945GM_SINGLE_MAX_DCLK;
+ }
+ } else if(pd_context->chipset==PCI_DEVICE_ID_VGA_GM965 ||
+ pd_context->chipset==PCI_DEVICE_ID_VGA_GME965){
+ /* Set dclk for GM965 */
+ if (pd_context->dual_channel) {
+ lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+ lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+ } else {
+ lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+ lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+ }
+ }
+#endif
+
+#ifdef CONFIG_TNC
+ /* Get the min and max dclks for Atom E6xx lvds */
+ if ((pd_context->chipset == PCI_DEVICE_ID_VGA_TNC) ||
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0) ||
+ (pd_context->chipset == PCI_DEVICE_ID_VGA_LNC)) {
+ lvds_info->min_dclk = LVDS_TNC_SINGLE_MIN_DCLK;
+ /* Experimental feature to raise TC LVDS clk to 110MHz. */
+ if (pd_context->tc_110MHz_clk) {
+ lvds_info->max_dclk = 110000L;
+ } else {
+ lvds_info->max_dclk = LVDS_TNC_SINGLE_MAX_DCLK;
+ }
+ }
+#endif
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
new file mode 100644
index 0000000..dd9cc87
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
@@ -0,0 +1,164 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is header file for Internal LVDS PORT DRIVER.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_LVDS_H
+#define _PD_LVDS_H
+
+#include <pd.h>
+#include <pci.h>
+
+/* Values received from DPG hardware engineer. These are for single channel. */
+
+#ifndef PCI_DEVICE_ID_VGA_855
+#define PCI_DEVICE_ID_VGA_855 0x3582
+#endif
+#ifndef PCI_DEVICE_ID_VGA_915AL
+#define PCI_DEVICE_ID_VGA_915AL 0x2592
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GM
+#define PCI_DEVICE_ID_VGA_945GM 0x27A2
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GME
+#define PCI_DEVICE_ID_VGA_945GME 0x27AE
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GM965
+#define PCI_DEVICE_ID_VGA_GM965 0x2A02
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GME965
+#define PCI_DEVICE_ID_VGA_GME965 0x2A12
+#endif
+#ifndef PCI_DEVICE_ID_VGA_CTG
+#define PCI_DEVICE_ID_VGA_CTG 0x2A42
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PLB
+#define PCI_DEVICE_ID_VGA_PLB 0x8108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC
+#define PCI_DEVICE_ID_VGA_TNC 0x4108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC_A0
+#define PCI_DEVICE_ID_VGA_TNC_A0 0x4100
+#endif
+#ifndef PCI_DEVICE_ID_VGA_LNC
+#define PCI_DEVICE_ID_VGA_LNC 0x4102
+#endif
+
+
+#define LVDS_MIN_DCLK 12000L /* in KHz */
+#define LVDS_MAX_DCLK 112000L /* in KHz */
+/* definition for 915GM */
+#define LVDS_915GM_SINGLE_MIN_DCLK 20000L
+#define LVDS_915GM_SINGLE_MAX_DCLK 112000L
+#define LVDS_915GM_DUAL_MIN_DCLK 25000L
+#define LVDS_915GM_DUAL_MAX_DCLK 224000L
+
+/* definition for 945GM */
+#define LVDS_945GM_SINGLE_MIN_DCLK 25000L
+#define LVDS_945GM_SINGLE_MAX_DCLK 112000L
+#define LVDS_945GM_DUAL_MIN_DCLK 25000L
+#define LVDS_945GM_DUAL_MAX_DCLK 224000L
+
+/* definition for GM965 */
+#define LVDS_GM965_SINGLE_MIN_DCLK 25000L
+#define LVDS_GM965_SINGLE_MAX_DCLK 112000L
+#define LVDS_GM965_DUAL_MIN_DCLK 25000L
+#define LVDS_GM965_DUAL_MAX_DCLK 224000L
+
+/* definition for Atom E6xx */
+#define LVDS_TNC_SINGLE_MIN_DCLK 19750L
+#define LVDS_TNC_SINGLE_MAX_DCLK 79500L
+
+#define LVDS_MIN(a, b) ((a)<(b)?(a):(b))
+
+/* Local attributes
+ * BIT15 of attribute Id specifies that it is a local attribute */
+#define LVDS_ATTR_ID_DATA_FORMAT (BIT(15)|1)
+#define LVDS_ATTR_ID_TC_LVDS_CLK (BIT(15)|2)
+
+/* Default values */
+#define LVDS_DEF_PANEL_DEPTH 18 /* Default panel depth */
+#define LVDS_DEF_DITHER 1 /* default=1 as default panel depth=18*/
+#define LVDS_DEF_SCALE_ON 1 /* Default scaling is on */
+#define LVDS_DEF_PANEL_FIT 1 /* Default panel fit in on */
+
+typedef struct _lvds_context {
+ unsigned short fp_width;
+ unsigned short fp_height;
+ unsigned short dual_channel;
+ unsigned short panel_type;
+ unsigned short panel_fit;
+ unsigned short panel_depth;
+ unsigned short dither;
+ unsigned short aspect_ratio;
+ unsigned long text_tune;
+ unsigned long pwm_intensity;
+ unsigned long inverter_freq;
+ unsigned long blm_legacy_mode;
+
+ unsigned long power_state;
+ unsigned short chipset;
+ unsigned char init_done;
+ unsigned char num_attrs;
+ unsigned long pipe;
+ unsigned short gfx_freq;
+ unsigned char gn4_plus;
+ unsigned char pwm_done;
+ unsigned char tc_110MHz_clk;
+
+ pd_callback_t *callback;
+ pd_timing_t *timing_table;
+ pd_attr_t *attr_list;
+ pd_timing_t *native_dtd;
+ pd_timing_t *current_mode;
+} lvds_context_t;
+
+extern int PD_MODULE_INIT(lvds_init, (void *handle));
+extern int PD_MODULE_EXIT(lvds_exit, (void));
+extern unsigned long lvds_validate(unsigned long cookie);
+extern int lvds_open(pd_callback_t *callback, void **context);
+extern int lvds_init_device(void *context);
+extern int lvds_close(void *context);
+extern int lvds_set_mode(void *context, pd_timing_t *mode,
+ unsigned long flags);
+extern int lvds_post_set_mode(void *context, pd_timing_t *mode,
+ unsigned long flags);
+extern int lvds_set_attrs(void *context, unsigned long num, pd_attr_t *list);
+extern int lvds_get_attrs(void *context, unsigned long*num, pd_attr_t **list);
+extern int lvds_get_timing_list(void *context, pd_timing_t *in_list,
+ pd_timing_t **list);
+extern int lvds_set_power(void *context, unsigned long state);
+extern int lvds_get_power(void *context, unsigned long *state);
+extern int lvds_save(void *context, void **state, unsigned long flags);
+extern int lvds_restore(void *context, void *state, unsigned long flags);
+extern int lvds_get_port_status(void *context, pd_port_status_t *port_status);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
new file mode 100644
index 0000000..f271b16
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
@@ -0,0 +1,25 @@
+# Copyright (c) 2002-2011, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+LIBRARY sdvo
+
+EXPORTS
+ get_version
+ dpd_init
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
new file mode 100644
index 0000000..81f458a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
@@ -0,0 +1,1484 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_attr.c
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Functions to
+ * Create Display Attribute table
+ * Query and Alter attributes
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_port.h"
+
+/* .......................................................................... */
+#ifndef CONFIG_MICRO
+#define MAKE_NAME(x) x
+#else
+#define MAKE_NAME(x) NULL
+#endif
+
+
+/* .......................................................................... */
+/* Panel Power Sequencing Parameters */
+static pd_range_attr_t g_panel_power_attr[] =
+{
+ /* ID Type Name */
+ /* Flags Default Value Current Value Min Max Step */
+ PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T1, PD_ATTR_TYPE_RANGE, "FP Power T1",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T2, PD_ATTR_TYPE_RANGE, "FP Power T2",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T3, PD_ATTR_TYPE_RANGE, "FP Power T3",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T4, PD_ATTR_TYPE_RANGE, "FP Power T4",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T5, PD_ATTR_TYPE_RANGE, "FP Power T5",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+};
+
+static pd_range_attr_t g_fp_attr[] = {
+ /* Do not change the order of entries */
+ /* ID Type Name */
+ /* Flags Default Value Current Value Min Max Step */
+ PD_MAKE_ATTR(PD_ATTR_ID_DISPLAY, PD_ATTR_TYPE_RANGE, "Display Type",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0x4000, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_PANEL_FIT, PD_ATTR_TYPE_BOOL, "PanelFit",
+ PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_TEXT_TUNING,PD_ATTR_TYPE_RANGE, "Text Enhancement",
+ 0, 0, 0, 0, 4, 1),
+
+ PD_MAKE_ATTR(PD_ATTR_ID_RB_SWAP_MODE, PD_ATTR_TYPE_BOOL,"RB Swap", 0, 0x00, 0x00, 0, 0, 0),
+};
+#ifndef CONFIG_MICRO
+static sdvo_tv_optimal_settings_t g_sdtv_op_settings[] =
+/* chron_tv_code [7:0]
+ * bits[7:2] = tv_format
+ * 480i = 0x00 ; 576i = 0x24 ; other TV line formats = 0xFF => for higher
+ * resolution, YPbPr is the implied connector
+ * bits [1:0] = output type
+ * CVBS = 0x00, SVIDEO = 0x01, YPbPr = 0x02, SCART = 0x03
+ * chron_tv_code, hue, saturation, brightness, contrast */
+{
+ /* SDTV [480i, 576i] - analog format w/
+ * CVBS / SVIDEO / SCART / YPbPr connector */
+ /* NTSC_M Composite */
+ {0x00, 0x3F, 0x35, 0x81, 0x2F},
+ /* NTSC_M Svideo */
+ {0x01, 0x3D, 0x30, 0x81, 0x2F},
+ /* PAL_B/D/G/H/I/K/L Composite */
+ {0x24, 0x41, 0x38, 0x74, 0x3B},
+ /* PAL_B/D/G/H/I/K/L Svideo */
+ {0x25, 0x3F, 0x30, 0x74, 0x3B},
+ /* SECAM xxx- */
+
+ /* EDTV [ 480p, 576p] + HDTV [720p, 1080i/p] ) -
+ * analog format w/ YPbPr connector */
+ {0xFF, 0x40, 0x45, 0x80, 0x2C},
+};
+#endif
+/* .......................................................................... */
+static sdvo_range_attr_data_t g_range_data[] =
+/* ID Name Bytes*/
+/* opcode_max opcode_get opcode_set */
+{
+ {PD_ATTR_ID_BRIGHTNESS, MAKE_NAME("Brightness"), 2,
+ GET_MAX_BRIGHTNESS, GET_BRIGHTNESS, SET_BRIGHTNESS},
+
+ {PD_ATTR_ID_PANEL_DEPTH, MAKE_NAME("Panel Depth"), 1,
+ GET_LVDS_PANEL_INFORMATION, GET_LVDS_PANEL_INFORMATION,
+ SET_LVDS_PANEL_INFORMATION},
+#ifndef CONFIG_MICRO
+ {PD_ATTR_ID_FP_BACKLIGHT_EN, MAKE_NAME("Backlight Level"), 1,
+ GET_MAX_BACKLIGHT_LEVEL, GET_BACKLIGHT_LEVEL, SET_BACKLIGHT_LEVEL},
+
+ {PD_ATTR_ID_FLICKER, MAKE_NAME("Flicker Filter"), 2,
+ GET_MAX_FLICKER_FILTER, GET_FLICKER_FILTER, SET_FLICKER_FILTER},
+
+ {PD_ATTR_ID_2D_FLICKER, MAKE_NAME("2D Flicker Filter"), 2,
+ GET_MAX_2D_FLICKER_FILTER, GET_2D_FLICKER_FILTER, SET_2D_FLICKER_FILTER},
+
+ {PD_ATTR_ID_SATURATION, MAKE_NAME("Saturation"), 2,
+ GET_MAX_SATURATION, GET_SATURATION, SET_SATURATION},
+
+ {PD_ATTR_ID_HUE, MAKE_NAME("Hue"), 2,
+ GET_MAX_HUE, GET_HUE, SET_HUE},
+
+ {PD_ATTR_ID_CONTRAST, MAKE_NAME("Contrast"), 2,
+ GET_MAX_CONTRAST, GET_CONTRAST, SET_CONTRAST},
+
+ {PD_ATTR_ID_HORZ_OVERSCAN, MAKE_NAME("Horz Overscan"), 2,
+ GET_MAX_HORIZONTAL_OVERSCAN, GET_HORIZONTAL_OVERSCAN,SET_HORIZONTAL_OVERSCAN},
+
+ {PD_ATTR_ID_VERT_OVERSCAN, MAKE_NAME("Vert Overscan"), 2,
+ GET_MAX_VERTICAL_OVERSCAN, GET_VERTICAL_OVERSCAN, SET_VERTICAL_OVERSCAN},
+
+ {PD_ATTR_ID_HPOSITION, MAKE_NAME("Horz Position"), 2,
+ GET_MAX_HORIZONTAL_POSITION, GET_HORIZONTAL_POSITION,SET_HORIZONTAL_POSITION},
+
+ {PD_ATTR_ID_VPOSITION, MAKE_NAME("Vert Position"), 2,
+ GET_MAX_VERTICAL_POSITION, GET_VERTICAL_POSITION, SET_VERTICAL_POSITION},
+
+ {PD_ATTR_ID_SHARPNESS, MAKE_NAME("Sharpness"), 2,
+ GET_MAX_SHARPNESS, GET_SHARPNESS, SET_SHARPNESS},
+
+ {PD_ATTR_ID_CHROMA_FILTER, MAKE_NAME("TV Chroma Filter"), 2,
+ GET_MAX_TV_CHROMA_FILTER, GET_TV_CHROMA_FILTER, SET_TV_CHROMA_FILTER},
+
+ {PD_ATTR_ID_LUMA_FILTER, MAKE_NAME("TV Luma Filter"), 2,
+ GET_MAX_TV_LUMA_FILTER, GET_TV_LUMA_FILTER, SET_TV_LUMA_FILTER},
+
+ {PD_ATTR_ID_ADAPTIVE_FLICKER, MAKE_NAME("Adaptive Flicker Filter"), 2,
+ GET_MAX_ADAPTIVE_FLICKER_FILTER, GET_ADAPTIVE_FLICKER_FILTER, SET_ADAPTIVE_FLICKER_FILTER},
+
+ {PD_ATTR_ID_SSC, MAKE_NAME("Spread Spectrum Clocking"), 1,
+ GET_MAX_SSC, GET_SSC, SET_SSC},
+#endif
+};
+
+
+/* .......................................................................... */
+static sdvo_bool_attr_data_t g_bool_data[] =
+/* ID Name Bit_Mask_Cur Bit_Mask_Def */
+/* opcode_get opcode_set */
+{
+ {PD_ATTR_ID_2_CHANNEL_PANEL, MAKE_NAME("Dual Channel"), 0x10, 0,
+ GET_LVDS_PANEL_INFORMATION, SET_LVDS_PANEL_INFORMATION},
+
+ /* 0-spwg, 1-openldi */
+ {PD_ATTR_ID_LVDS_PANEL_TYPE, MAKE_NAME("LVDS Panel Type"), 0x04, 0,
+ GET_LVDS_PANEL_INFORMATION, SET_LVDS_PANEL_INFORMATION},
+
+ {PD_ATTR_ID_DITHER, MAKE_NAME("Dither"), 0x01, 0x02,
+ GET_DITHER, SET_DITHER},
+
+#ifndef CONFIG_MICRO
+ {PD_ATTR_ID_DOT_CRAWL, MAKE_NAME("Dot Crawl"), 0x01, 0x02,
+ GET_DOT_CRAWL, SET_DOT_CRAWL},
+
+ {PD_ATTR_ID_PANEL_PROTECT_HSYNC, MAKE_NAME("HSync Panel Protection"), 0x01, 0,
+ GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+
+ {PD_ATTR_ID_PANEL_PROTECT_VSYNC, MAKE_NAME("VSync Panel Protection"), 0x02, 0,
+ GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+
+ {PD_ATTR_ID_PANEL_PROTECT_PIXCLK, MAKE_NAME("Pixel Clock Protection"), 0x04, 0,
+ GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+#endif
+};
+
+/* .......................................................................... */
+#ifndef CONFIG_MICRO
+/* List entries for the TV format, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_tv_format[] =
+{
+ {PD_TV_STD_NTSC_M, MAKE_NAME("NTSC_M"), 0, 0x01},
+ {PD_TV_STD_NTSC_M_J, MAKE_NAME("NTSC_J"), 0, 0x02},
+ {PD_TV_STD_NTSC_433, MAKE_NAME("NTSC_433"), 0, 0x04},
+ {PD_TV_STD_PAL_B, MAKE_NAME("PAL_B"), 0, 0x08},
+ {PD_TV_STD_PAL_D, MAKE_NAME("PAL_D"), 0, 0x10},
+ {PD_TV_STD_PAL_G, MAKE_NAME("PAL_G"), 0, 0x20},
+ {PD_TV_STD_PAL_H, MAKE_NAME("PAL_H"), 0, 0x40},
+ {PD_TV_STD_PAL_I, MAKE_NAME("PAL_I"), 0, 0x80},
+
+ {PD_TV_STD_PAL_M, MAKE_NAME("PAL_M"), 1, 0x01},
+ {PD_TV_STD_PAL_N, MAKE_NAME("PAL_N"), 1, 0x02},
+ {PD_TV_STD_PAL_NC, MAKE_NAME("PAL_NC"), 1, 0x04},
+ {PD_TV_STD_PAL_60, MAKE_NAME("PAL_60"), 1, 0x08},
+ {PD_TV_STD_SECAM_B, MAKE_NAME("SECAM_B"), 1, 0x10},
+ {PD_TV_STD_SECAM_D, MAKE_NAME("SECAM_D"), 1, 0x20},
+ {PD_TV_STD_SECAM_G, MAKE_NAME("SECAM_G"), 1, 0x40},
+ {PD_TV_STD_SECAM_K, MAKE_NAME("SECAM_K"), 1, 0x80},
+
+ {PD_TV_STD_SECAM_K1, MAKE_NAME("SECAM_K1"), 2, 0x01},
+ {PD_TV_STD_SECAM_L, MAKE_NAME("SECAM_L"), 2, 0x02},
+ {PD_TV_STD_SECAM_60, MAKE_NAME("SECAM_60"), 2, 0x04},
+
+ {PD_HDTV_STD_SMPTE_240M_1080i59, MAKE_NAME("SMPTE_240M_1080i59"), 2, 0x08},
+ {PD_HDTV_STD_SMPTE_240M_1080i60, MAKE_NAME("SMPTE_240M_1080i60"), 2, 0x10},
+ {PD_HDTV_STD_SMPTE_260M_1080i59, MAKE_NAME("SMPTE_260M_1080i59"), 2, 0x20},
+ {PD_HDTV_STD_SMPTE_260M_1080i60, MAKE_NAME("SMPTE_260M_1080i60"), 2, 0x40},
+ {PD_HDTV_STD_SMPTE_274M_1080i50, MAKE_NAME("SMPTE_274M_1080i50"), 2, 0x80},
+
+ {PD_HDTV_STD_SMPTE_274M_1080i59, MAKE_NAME("SMPTE_274M_1080i59"), 3, 0x01},
+ {PD_HDTV_STD_SMPTE_274M_1080i60, MAKE_NAME("SMPTE_274M_1080i60"), 3, 0x02},
+ {PD_HDTV_STD_SMPTE_274M_1080p23, MAKE_NAME("SMPTE_274M_1080p23"), 3, 0x04},
+ {PD_HDTV_STD_SMPTE_274M_1080p24, MAKE_NAME("SMPTE_274M_1080p24"), 3, 0x08},
+ {PD_HDTV_STD_SMPTE_274M_1080p25, MAKE_NAME("SMPTE_274M_1080p25"), 3, 0x10},
+ {PD_HDTV_STD_SMPTE_274M_1080p29, MAKE_NAME("SMPTE_274M_1080p29"), 3, 0x20},
+ {PD_HDTV_STD_SMPTE_274M_1080p30, MAKE_NAME("SMPTE_274M_1080p30"), 3, 0x40},
+ {PD_HDTV_STD_SMPTE_274M_1080p50, MAKE_NAME("SMPTE_274M_1080p50"), 3, 0x80},
+
+ {PD_HDTV_STD_SMPTE_274M_1080p59, MAKE_NAME("SMPTE_274M_1080p59"), 4, 0x01},
+ {PD_HDTV_STD_SMPTE_274M_1080p60, MAKE_NAME("SMPTE_274M_1080p60"), 4, 0x02},
+ {PD_HDTV_STD_SMPTE_295M_1080i50, MAKE_NAME("SMPTE_295M_1080i50"), 4, 0x04},
+ {PD_HDTV_STD_SMPTE_295M_1080p50, MAKE_NAME("SMPTE_295M_1080p50"), 4, 0x08},
+ {PD_HDTV_STD_SMPTE_296M_720p59, MAKE_NAME("SMPTE_296M_720p59"), 4, 0x10},
+ {PD_HDTV_STD_SMPTE_296M_720p60, MAKE_NAME("SMPTE_296M_720p60"), 4, 0x20},
+ {PD_HDTV_STD_SMPTE_296M_720p50, MAKE_NAME("SMPTE_296M_720p50"), 4, 0x40},
+ {PD_HDTV_STD_SMPTE_293M_480p59, MAKE_NAME("SMPTE_293M_480p59"), 4, 0x80},
+
+ {PD_HDTV_STD_SMPTE_170M_480i59, MAKE_NAME("MPTE_170M_480i59"), 5, 0x01},
+ {PD_HDTV_STD_ITURBT601_576i50, MAKE_NAME("ITURBT601_576i50"), 5, 0x02},
+ {PD_HDTV_STD_ITURBT601_576p50, MAKE_NAME("TURBT601_576p50"), 5, 0x04},
+ {PD_HDTV_STD_EIA_7702A_480i60, MAKE_NAME("EIA_7702A_480i60"), 5, 0x08},
+ {PD_HDTV_STD_EIA_7702A_480p60, MAKE_NAME("EIA_7702A_480p60"), 5, 0x10},
+ {0, NULL, 0, 0}
+};
+
+/* Enable below attributes once upper layers hooked up copyprotection API */
+
+/* List entries for the analog source, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_analog_src[] =
+{
+ {PD_ANALOG_SRC_NO_DATA, MAKE_NAME("No Data"), 0, 0x00},
+ {PD_ANALOG_SRC_PRE_RECORDED, MAKE_NAME("Pre-recorded Packaged"), 0, 0x20},
+ {PD_ANALOG_SRC_NOT_PRE_RECORDED, MAKE_NAME("Not Analog Pre-recorded"), 0, 0x30},
+ {0, NULL, 0, 0}
+};
+
+/* List entries for the scan information, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_scan_info[] =
+{
+ {PD_SCAN_NO_DATA, MAKE_NAME("No Data"), 0, 0x00},
+ {PD_SCAN_OVERSCANNED, MAKE_NAME("Overscanned"), 0, 0x40},
+ {PD_SCAN_UNDERSCANNED, MAKE_NAME("Underscanned"), 0, 0x80},
+ {0, NULL, 0, 0}
+};
+
+/* List entries for the aspect ratio, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_aspect_ratio[] =
+{
+ {PD_SCAN_NO_DATA, MAKE_NAME("No Data"), 1, 0x00},
+ {PD_SCAN_OVERSCANNED, MAKE_NAME("4:3"), 1, 0x01},
+ {PD_SCAN_UNDERSCANNED, MAKE_NAME("16:9"), 1, 0x02},
+ {0, NULL, 0, 0}
+};
+
+/* List entries for the active format, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_active_format[] =
+{
+ {PD_ACTIVE_FORMAT_NO_DATA,
+ MAKE_NAME("No Data"), 1, 0x00},
+ {PD_ACTIVE_FORMAT_SQUARE_PIXELS,
+ MAKE_NAME("Square Pixels"), 1, 0x20},
+ {PD_ACTIVE_FORMAT_4_3_CENTER,
+ MAKE_NAME("4:3 Center"), 1, 0x24},
+ {PD_ACTIVE_FORMAT_16_9_CENTER,
+ MAKE_NAME("16:9 Center"), 1, 0x28},
+ {PD_ACTIVE_FORMAT_14_9_CENTER,
+ MAKE_NAME("14:9 Center"), 1, 0x2C},
+ {PD_ACTIVE_FORMAT_16_9_LETTERBOX_TOP,
+ MAKE_NAME("16:9 Letterbox(Top)"), 1, 0x08},
+ {PD_ACTIVE_FORMAT_14_9_LETTERBOX_TOP,
+ MAKE_NAME("14:9 Letterbox(Top)"), 1, 0x0C},
+ {PD_ACTIVE_FORMAT_16_9_LETTERBOX_CENTER,
+ MAKE_NAME("16:9 Letterbox(Center)"), 1, 0x10},
+ {PD_ACTIVE_FORMAT_4_3_SHOOT_PROTECT_14_9_CENTER,
+ MAKE_NAME("4:3(with shoot & protect 14:9 center)"), 1, 0x34},
+ {PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_14_9_CENTER,
+ MAKE_NAME("16:9(with shoot & protect 14:9 center)"), 1, 0x38},
+ {PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_4_3_CENTER,
+ MAKE_NAME("16:9(with shoot & protect 4:3 center)"), 1, 0x3C},
+ {0, NULL, 0, 0}
+};
+
+static sdvo_attr_list_header_t g_list_header[] =
+{
+ {45, PD_ATTR_ID_TVFORMAT, MAKE_NAME("TV Out Format"),
+ GET_TV_OUTPUT_FORMAT, SET_TV_OUTPUT_FORMAT,
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ g_list_entry_tv_format},
+
+/* Enable below attributes once upper layers hooked up copyprotection API */
+
+ { 3, PD_ATTR_ID_ANALOG_SRC, MAKE_NAME("Analog Source"),
+ GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+ {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ g_list_entry_analog_src},
+
+ { 3, PD_ATTR_ID_SCAN_INFO, MAKE_NAME("Scan Information"),
+ GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+ {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ g_list_entry_scan_info},
+
+ { 3, PD_ATTR_ID_PICTURE_ASPECT_RATIO, MAKE_NAME("Picture Aspect Ratio"),
+ GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+ {0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ g_list_entry_aspect_ratio},
+
+ {11, PD_ATTR_ID_ACTIVE_FORMAT, MAKE_NAME("Active Format Aspect Ratio"),
+ GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+ {0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ g_list_entry_active_format},
+
+ { 0 }
+};
+
+#endif
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_set_tv_optimal_settings(sdvo_device_context_t *p_ctx,
+ unsigned char chron_tv_code)
+{
+
+ sdvo_status_t status = SS_SUCCESS;
+ pd_attr_t *p_attr;
+ int i;
+
+
+ for (i= 0;i <5;i ++)
+ if (chron_tv_code == g_sdtv_op_settings[i].tv_code) {
+ /* set hue */
+ p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_HUE, 0);
+ if (NULL != p_attr)
+ {
+ status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+ g_sdtv_op_settings[i].hue);
+ p_attr->current_value = g_sdtv_op_settings[i].hue; //update table
+ }
+
+ /* set saturation */
+ p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_SATURATION, 0);
+ if (NULL != p_attr)
+ {
+ status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+ g_sdtv_op_settings[i].saturation);
+
+ p_attr->current_value = g_sdtv_op_settings[i].saturation;
+ }
+
+ /* set brightness */
+ p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_BRIGHTNESS, 0);
+ if (p_attr)
+ {
+ status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+ g_sdtv_op_settings[i].brightness);
+
+ p_attr->current_value = g_sdtv_op_settings[i].brightness;
+ }
+
+ /* set contrast */
+ p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_CONTRAST, 0);
+ if (p_attr)
+ {
+ status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+ g_sdtv_op_settings[i].contrast);
+
+ p_attr->current_value = g_sdtv_op_settings[i].contrast;
+ }
+ }
+
+ return status;
+}
+#endif
+
+/* .......................................................................... */
+/* .......................................................................... */
+/* ============================================================================
+ Function : sdvo_get_static_attrs
+
+ Parameters : p_attr : Returns the list of avaliable static attributes
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_get_static_attrs(sdvo_device_context_t *p_ctx,
+ pd_attr_t *p_attr_list1)
+{
+ int num_attrs = 0;
+ pd_range_attr_t *p_attr_list = (pd_range_attr_t *)p_attr_list1;
+
+ if (p_attr_list == NULL) {
+
+ /* Just return the number of available attributes */
+
+ if (p_ctx->out_type.flags & FP_DISP_MASK) {
+ num_attrs ++;
+
+ /* Enable Text Tuning */
+ if ((p_ctx->out_type.flags & LVDS_DISP_MASK) &&
+ (p_ctx->dev_cap.up_scaling)) {
+ num_attrs++;
+ }
+ }
+
+ /* Add Display Attribute only if sDVO returned more than one
+ display type from GetDeviceCapabilities */
+ if (sdvo_is_multi_display_device(p_ctx)) {
+ num_attrs++;
+ }
+
+ /* Red Blue Swap for DRGB output */
+ if((p_ctx->out_type.flags & DRGB_DISP_MASK) && (p_ctx->dev_cap.vendor_id == 0x81)){
+ num_attrs++;
+ }
+ return num_attrs;
+ }
+
+ /* ...................................................................... */
+ /* Fill in the available attributes */
+
+ /* Width and Height Attributes are available for LVDS and TMDS only */
+ if (p_ctx->out_type.flags & FP_DISP_MASK) {
+ p_attr_list[num_attrs] = g_fp_attr[1]; /* PANELFIT */
+ /* There are initial values */
+ p_attr_list[num_attrs].current_value = p_ctx->dev_cap.up_scaling;
+ p_ctx->up_scaling = p_ctx->dev_cap.up_scaling;
+ num_attrs++;
+
+ /* Enable Text Tuning */
+ if ((p_ctx->out_type.flags & LVDS_DISP_MASK) &&
+ (p_ctx->dev_cap.up_scaling)) {
+ p_attr_list[num_attrs] = g_fp_attr[2]; /* Text tuning */
+ num_attrs++;
+ }
+ }
+
+ /* Add Display Attribute only if sDVO returned more than one
+ display type from GetDeviceCapabilities */
+ if (sdvo_is_multi_display_device(p_ctx)) {
+ p_attr_list[num_attrs] = g_fp_attr[0];
+ p_attr_list[num_attrs].default_value = p_ctx->dev_cap.output.flags;
+ p_attr_list[num_attrs].current_value = p_ctx->out_type.flags;
+ num_attrs++;
+ }
+
+ /* Red Blue Swap for DRGB output */
+ if((p_ctx->out_type.flags & DRGB_DISP_MASK) && (p_ctx->dev_cap.vendor_id == 0x81)){
+ p_attr_list[num_attrs] = g_fp_attr[3];
+ num_attrs++;
+ }
+
+
+#ifdef DEBUG_BUILD_TYPE
+ /* ...................................................................... */
+ {
+ int i;
+ for (i = 0; i < num_attrs; i++) {
+ pd_attr_t *p_attr_cur = (pd_attr_t *)&p_attr_list[i];
+ PD_DEBUG("sdvo : sdvo_get_static_attrs : "
+ "Adding attr='%s', id=%ld, type=%ld, default=%ld, current=%ld",
+ SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id, p_attr_cur->type,
+ p_attr_cur->default_value, p_attr_cur->current_value);
+ }
+ }
+#endif
+
+ /* ...................................................................... */
+ return num_attrs;
+}
+
+
+/* ============================================================================
+ Function : sdvo_query_static_attr
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_static_attr(sdvo_device_context_t *p_ctx,
+ pd_attr_t *p_attr)
+{
+ int b_error = 1;
+ i2c_reg_t temp_reg;
+
+ switch (p_attr->id) {
+ case PD_ATTR_ID_DISPLAY :
+ p_attr->current_value = p_ctx->out_type.flags;
+ b_error = 0;
+ break;
+
+ case PD_ATTR_ID_PANEL_FIT:
+ if (p_ctx->out_type.flags & FP_DISP_MASK) {
+ p_attr->current_value = p_ctx->up_scaling;
+ b_error = 0;
+ }
+ break;
+
+ case PD_ATTR_ID_TEXT_TUNING:
+ p_attr->current_value = p_ctx->text_tune;
+ b_error = 0;
+ break;
+ case PD_ATTR_ID_RB_SWAP_MODE:
+ {
+ sdvo_read_i2c_reg(p_ctx, 0x30, &temp_reg);
+ if (!(p_attr->flags & PD_ATTR_FLAG_NEED_RESTORE)){
+ p_attr->current_value = (temp_reg & 0x2)?1:0;
+ }
+ /*Impossible to return correct value since the encoder
+ has been reset.*/
+
+ b_error = 0;
+ }
+ break;
+ }
+
+ /* ..................................................................... */
+ if (b_error) {
+
+ PD_ERROR("sdvo : Error ! sdvo_query_static_attr : "
+ "Invalid attr='%s, id=%ld",
+ SDVO_GET_ATTR_NAME(p_attr), p_attr->id);
+
+ return SS_INVALID_ARGUMENT;
+ }
+
+ return SS_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_alter_static_attr
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_static_attr(sdvo_device_context_t *p_ctx,
+ pd_attr_t *p_attr, unsigned long new_value)
+{
+ int b_error = 1;
+ i2c_reg_t temp_reg;
+
+ switch (p_attr->id) {
+ case PD_ATTR_ID_PANEL_FIT:
+ if (p_ctx->out_type.flags & FP_DISP_MASK) {
+ p_ctx->up_scaling = (unsigned char)
+ ((p_ctx->dev_cap.up_scaling)?new_value:0);
+ b_error = 0;
+ }
+ break;
+
+ case PD_ATTR_ID_TEXT_TUNING:
+ if (sdvo_set_upscalar_coefficient(p_ctx,(i2c_reg_t)new_value) ==
+ SS_SUCCESS) {
+ p_ctx->text_tune = (i2c_reg_t)new_value;
+ }
+ b_error = 0;
+ break;
+ case PD_ATTR_ID_RB_SWAP_MODE:
+ sdvo_read_i2c_reg(p_ctx, 0x30, &temp_reg);
+ if(new_value){
+ temp_reg |= 0x2;
+ p_attr->current_value = 1;
+ }else{
+ temp_reg &= ~(0x2);
+ p_attr->current_value = 0;
+ }
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ p_attr->flags &= ~PD_ATTR_FLAG_NEED_RESTORE;
+ sdvo_write_i2c_reg(p_ctx, 0x30, temp_reg);
+ b_error = 0;
+ break;
+ }
+
+ /* ..................................................................... */
+ if (b_error) {
+ PD_ERROR("sdvo : Error ! sdvo_alter_static_attr : "
+ "Invalid attr='%s, id=%ld",
+ SDVO_GET_ATTR_NAME(p_attr), p_attr->id);
+ return SS_INVALID_ARGUMENT;
+ }
+ return SS_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_panel_pwr_seq_attrs
+
+ Parameters : pp_Attr : Returns the list of avaliable attributes
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_get_panel_pwr_seq_attrs(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr)
+{
+ sdvo_status_t status;
+ i2c_reg_t ret_val[8];
+ int i;
+
+ status = sdvo_execute_command(p_ctx,
+ GET_MAX_PANEL_POWER_SEQUENCING_PARAMETER,
+ 0, NULL,
+ 7, ret_val);
+ if (status != SS_SUCCESS) {
+ return 0;
+ }
+
+ if (p_attr == NULL) {
+ /* Just return the number of available attributes */
+ return ARRAY_SIZE(g_panel_power_attr);
+ }
+
+ /* ...................................................................... */
+ g_panel_power_attr[0].max=((unsigned long)(ret_val[5]&0x03)<<8)|ret_val[0];
+ g_panel_power_attr[1].max=((unsigned long)(ret_val[5]&0x0C)<<6)|ret_val[1];
+ g_panel_power_attr[2].max=((unsigned long)(ret_val[5]&0x30)<<4)|ret_val[2];
+ g_panel_power_attr[3].max=((unsigned long)(ret_val[5]&0xC0)<<2)|ret_val[3];
+ g_panel_power_attr[4].max=((unsigned long)(ret_val[6]&0x03)<<8)|ret_val[4];
+
+ for (i = 0; i < 5; i++) {
+ pd_range_attr_t *p_attr_cur = &g_panel_power_attr[i];
+ p_attr_cur->flags |= PD_ATTR_FLAG_DYNAMIC;
+#ifndef CONFIG_MICRO
+ status = sdvo_query_panel_pwr_seq_attr(p_ctx, p_attr_cur);
+ if (status != SS_SUCCESS) {
+ return 0;
+ }
+ p_attr_cur->default_value = p_attr_cur->current_value;
+#endif
+ PD_DEBUG("sdvo : sdvo_get_panel_pwr_seq_attrs : "
+ "Adding attr='%s', id=%ld, default=%ld, current=%ld, min=%ld, "
+ "max=%ld, step=%ld",
+ SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id,
+ p_attr_cur->default_value, p_attr_cur->current_value,
+ p_attr_cur->min, p_attr_cur->max, p_attr_cur->step);
+
+ }
+
+ pd_memcpy(p_attr, g_panel_power_attr, sizeof(g_panel_power_attr));
+ return ARRAY_SIZE(g_panel_power_attr);
+}
+
+
+/* ============================================================================
+ Function :
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr)
+{
+#ifndef CONFIG_MICRO
+ sdvo_status_t status;
+ i2c_reg_t ret_val[8];
+
+ status = sdvo_execute_command(p_ctx, GET_PANEL_POWER_SEQUENCING_PARAMETER,
+ 0, NULL,
+ 7, ret_val);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ switch (p_attr->id) {
+
+ case PD_ATTR_ID_FP_PWR_T1 :
+ p_attr->current_value = p_ctx->t1 =
+ ((unsigned short)(ret_val[5] & 0x03) << 8) | ret_val[0];
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T2 :
+ p_attr->current_value = p_ctx->t2 =
+ ((unsigned short)(ret_val[5] & 0x0C) << 6) | ret_val[1];
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T3 :
+ p_attr->current_value = p_ctx->t3 =
+ ((unsigned short)(ret_val[5] & 0x30) << 4) | ret_val[2];
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T4 :
+ p_attr->current_value = p_ctx->t4 =
+ ((unsigned short)(ret_val[5] & 0xC0) << 2) | ret_val[3];
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T5 :
+ p_attr->current_value = p_ctx->t5 =
+ ((unsigned short)(ret_val[6] & 0x03) << 8) | ret_val[4];
+ break;
+
+ default :
+ return SS_INVALID_ARGUMENT;
+ }
+#endif
+ return SS_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_alter_panel_pwr_seq_attr
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr,
+ unsigned long new_value)
+{
+ sdvo_status_t status;
+ i2c_reg_t arg[8];
+ i2c_reg_t new_val_low = (i2c_reg_t)(new_value & 0xFF);
+ i2c_reg_t new_val_high = (i2c_reg_t)((new_value & 0x0300) >> 8);
+
+ if ((new_value < p_attr->min) || (new_value > p_attr->max)) {
+ PD_DEBUG("Requested values out of range, new_value = %lu.",
+ new_value);
+ return SS_INVALID_ARGUMENT;
+ }
+
+ status = sdvo_execute_command(p_ctx, GET_PANEL_POWER_SEQUENCING_PARAMETER,
+ 0, NULL, 7, arg);
+ if (status != SS_SUCCESS) {
+ PD_DEBUG("GET_PANEL_POWER_SEQUENCING_PARAMETER failed status = %u",
+ status);
+ return status;
+ }
+
+ switch (p_attr->id) {
+ case PD_ATTR_ID_FP_PWR_T1 :
+ p_ctx->t1 = (unsigned short)new_value;
+ arg[0] = new_val_low;
+ arg[5] &= 0xFC;
+ arg[5] |= new_val_high;
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T2 :
+ p_ctx->t2 = (unsigned short)new_value;
+ arg[1] = new_val_low;
+ arg[5] &= 0xF3;
+ arg[5] |= (new_val_high << 2);
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T3 :
+ p_ctx->t3 = (unsigned short)new_value;
+ arg[2] = new_val_low;
+ arg[5] &= 0xCF;
+ arg[5] |= (new_val_high << 4);
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T4 :
+ p_ctx->t4 = (unsigned short)new_value;
+ arg[3] = new_val_low;
+ arg[5] &= 0x3F;
+ arg[5] |= (new_val_high << 6);
+ break;
+
+ case PD_ATTR_ID_FP_PWR_T5 :
+ p_ctx->t5 = (unsigned short)new_value;
+ arg[4] = new_val_low;
+ arg[6] &= 0xFC;
+ arg[6] |= new_val_high;
+ break;
+
+ default :
+ return SS_INVALID_ARGUMENT;
+ }
+
+ status = sdvo_execute_command(p_ctx, SET_PANEL_POWER_SEQUENCING_PARAMETER,
+ 7, arg,
+ 0, NULL);
+ return status;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_range_attrs returns all the available range
+ attributes
+
+ Parameters : pp_Attr : Returns the list of avaliable range attributes
+
+ Remarks : sdvo_get_range_attrs returns all the range attributes
+ from g_range_data table that are supported by the SDVO device.
+ It allocates memory for all possible range attributes.
+ The caller is responsible for adding the range attributes to
+ port driver attribute table and freeing the memory allocated
+ for pp_Attr.
+
+ Returns : Number of range attributes returned in pp_Attr list.
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_get_range_attrs(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr)
+{
+ unsigned long num_attrs, i;
+ sdvo_status_t status;
+ unsigned char byte_ret[4];
+
+ /* ..................................................................... */
+ if (p_attr == NULL) {
+ /* Just return the number of available attributes */
+ num_attrs = 0;
+
+ for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+ status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_max,
+ 0, NULL,
+ (i2c_reg_t)(g_range_data[i].num_bytes * 2),
+ byte_ret);
+ if (status != SS_SUCCESS) {
+ continue;
+ }
+
+ status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_get,
+ 0, NULL,
+ (i2c_reg_t)(g_range_data[i].num_bytes),
+ byte_ret);
+ if (status != SS_SUCCESS) {
+ continue;
+ }
+
+ num_attrs++;
+ }
+
+ return num_attrs;
+ }
+
+ /* ..................................................................... */
+ num_attrs = 0;
+
+ for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+ pd_range_attr_t *p_attr_cur = &p_attr[num_attrs];
+
+ status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_max,
+ 0, NULL,
+ (i2c_reg_t)(g_range_data[i].num_bytes * 2),
+ byte_ret);
+ if (status != SS_SUCCESS) {
+
+ continue;
+ }
+
+ p_attr_cur->id = g_range_data[i].id;
+ p_attr_cur->type = PD_ATTR_TYPE_RANGE;
+ p_attr_cur->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+#ifndef CONFIG_MICRO
+ pd_strcpy(p_attr_cur->name, g_range_data[i].p_name);
+#endif
+
+ p_attr_cur->default_value = g_range_data[i].num_bytes == 1 ?
+ byte_ret[1] : byte_ret[2] + (byte_ret[3] << 8);
+ p_attr_cur->min = 0;
+ p_attr_cur->step = 1;
+ p_attr_cur->max = g_range_data[i].num_bytes == 1 ?
+ byte_ret[0] : byte_ret[0] + (byte_ret[1] << 8);
+
+ status = sdvo_query_range_attr(p_ctx, p_attr_cur);
+ if (status != SS_SUCCESS) {
+ continue;
+ }
+
+ PD_DEBUG("sdvo : sdvo_get_range_attrs : "
+ "Adding attr='%s', id=%ld, default=%ld, current=%ld, min=%ld, "
+ "max=%ld, step=%ld",
+ SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id,
+ p_attr_cur->default_value, p_attr_cur->current_value,
+ p_attr_cur->min, p_attr_cur->max, p_attr_cur->step);
+
+ num_attrs++;
+ }
+
+ /* ..................................................................... */
+ return num_attrs;
+}
+
+
+/* ============================================================================
+ Function : sdvo_query_range_attr is called to query the current value
+ of a specific range attribute
+
+ Parameters : p_attr : Pointer to range attribute
+
+ Remarks : sdvo_query_range_attr scans the g_range_data list to find
+ the range attribute of id specified in p_attr.
+ If found it executes the opcode_get command to get the current
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_range_attr(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr)
+{
+ int i;
+ sdvo_status_t status;
+
+ for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+ if (g_range_data[i].id == p_attr->id) {
+
+ status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_get,
+ 0, NULL,
+ g_range_data[i].num_bytes,
+ (unsigned char *)&p_attr->current_value);
+
+ if (status == SS_SUCCESS) {
+ /* Special case for Panel depth */
+ if (g_range_data[i].id == PD_ATTR_ID_PANEL_DEPTH) {
+ p_attr->min = 18;
+ p_attr->step = 6;
+ p_attr->max = 24;
+ p_attr->default_value = 18;
+ if (p_attr->current_value & 0x01) {
+ p_attr->current_value = 24;
+ } else {
+ p_attr->current_value = 18;
+ }
+ }
+ }
+ return status;
+ }
+ }
+
+ return SS_INVALID_ARGUMENT;
+}
+
+
+/* ============================================================================
+ Function : sdvo_alter_range_attr is called to set the new value of a
+ specific range attribute
+
+ Parameters : p_attr : Pointer to range attribute
+
+ Remarks : sdvo_query_range_attr scans the g_range_data list to find
+ the range attribute of id specified in p_attr.
+ If found it executes the opcode_set command to set the new
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_range_attr(sdvo_device_context_t *p_ctx,
+ pd_range_attr_t *p_attr, unsigned long new_value)
+{
+ int i;
+ sdvo_status_t status;
+
+
+ if ((new_value < p_attr->min) || (new_value > p_attr->max)) {
+
+ return SS_INVALID_ARGUMENT;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+ if (g_range_data[i].id == p_attr->id) {
+ /* Special case handling for panel depth attribute */
+ if (p_attr->id == PD_ATTR_ID_PANEL_DEPTH) {
+ i2c_reg_t cur_value;
+ status = sdvo_execute_command(p_ctx,
+ g_range_data[i].opcode_get,
+ 0, NULL,
+ 1, &cur_value);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+
+ if (new_value == 24) {
+ /* 24-bit display */
+ new_value = cur_value | 0x01; /* set bits [1:0] = 01 */
+ } else {
+ /* 18-bit display */
+ new_value = cur_value & 0xFC; /* set bits [1:0] = 00 */
+ }
+ }
+
+ /*Special case handling for CH7308 EMI on/off operation */
+
+ if (p_attr->id == PD_ATTR_ID_SSC) {
+
+ i2c_reg_t reg;
+ if( new_value > 0) /* turn on EMI for value range from 1 - 15 */
+ {
+
+ sdvo_read_i2c_reg(p_ctx, 0x3C, ®);
+ sdvo_write_i2c_reg(p_ctx, 0x3C, (reg & 0xFC));
+ sdvo_read_i2c_reg(p_ctx, 0x3E, ®);
+ sdvo_write_i2c_reg(p_ctx, 0x3E, (reg | 0x80));
+ }
+ else /* turn off EMI */
+ {
+ sdvo_read_i2c_reg(p_ctx, 0x3C, ®);
+ sdvo_write_i2c_reg(p_ctx, 0x3C, (reg | 0x01));
+ sdvo_read_i2c_reg(p_ctx, 0x3E, ®);
+ sdvo_write_i2c_reg(p_ctx, 0x3E, (reg & 0x7F));
+
+ }
+
+
+ }
+
+
+ return sdvo_execute_command(p_ctx, g_range_data[i].opcode_set,
+ g_range_data[i].num_bytes,
+ (unsigned char *)&new_value,
+ 0, NULL);
+ }
+ }
+
+ return SS_INVALID_ARGUMENT;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_bool_attrs returns all the available boolean
+ attributes
+
+ Parameters : pp_Attr : Returns the list of avaliable boolean attributes
+
+ Remarks : sdvo_get_bool_attrs returns all the boolean attributes
+ from g_bool_data table that are supported by the SDVO device.
+ It allocates memory for all possible boolean attributes.
+ The caller is responsible for adding the booelan attributes
+ to the port driver attribute table and freeing the memory
+ allocated for pp_Attr.
+
+ Returns : Number of boolean attributes returned in pp_Attr list.
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_get_bool_attrs(sdvo_device_context_t *p_ctx,
+ pd_bool_attr_t *p_attr)
+{
+ unsigned long num_attrs, i;
+ sdvo_status_t status;
+
+ /* ..................................................................... */
+ if (p_attr == NULL) {
+
+ /* Just return the number of available attributes */
+ i2c_reg_t ret_value;
+
+ num_attrs = 0;
+
+ for (i = 0; i < ARRAY_SIZE(g_bool_data); i++) {
+ if((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS) &&
+ (p_ctx->dev_cap.device_id == 0x1) &&
+ ((g_bool_data[i].id == PD_ATTR_ID_PANEL_PROTECT_HSYNC) ||
+ (g_bool_data[i].id == PD_ATTR_ID_PANEL_PROTECT_VSYNC))) {
+
+ continue;
+ }
+ status = sdvo_execute_command(p_ctx, g_bool_data[i].opcode_get,
+ 0, NULL,
+ 1, &ret_value);
+ if (status != SS_SUCCESS) {
+
+ continue;
+ }
+
+ num_attrs++;
+ }
+
+ return num_attrs;
+ }
+
+ /* ..................................................................... */
+ num_attrs = 0;
+
+ for (i = 0; i < ARRAY_SIZE(g_bool_data); i++) {
+
+ pd_bool_attr_t *p_attr_cur = &p_attr[num_attrs];
+
+ p_attr_cur->id = g_bool_data[i].id;
+ p_attr_cur->type = PD_ATTR_TYPE_BOOL;
+ p_attr_cur->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+ if((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS) &&
+ (p_ctx->dev_cap.device_id == 0x1) &&
+ ((g_bool_data[i].id == PD_ATTR_ID_PANEL_PROTECT_HSYNC) ||
+ (g_bool_data[i].id == PD_ATTR_ID_PANEL_PROTECT_VSYNC))) {
+
+ continue;
+ }
+
+
+ status = sdvo_query_bool_attr(p_ctx, p_attr_cur);
+ if (status != SS_SUCCESS)
+ continue;
+
+ p_attr_cur->default_value = p_attr_cur->current_value;
+
+#ifndef CONFIG_MICRO
+ pd_strcpy(p_attr_cur->name, g_bool_data[i].p_name);
+#endif
+
+ PD_DEBUG("sdvo : sdvo_get_bool_attrs : "
+ "Adding attr='%s', id=%ld, default=%ld, current=%ld",
+ SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id,
+ p_attr_cur->default_value, p_attr_cur->current_value);
+
+ num_attrs++;
+ }
+
+ /* ..................................................................... */
+ return num_attrs;
+}
+
+
+/* ============================================================================
+ Function : sdvo_query_bool_attr is called to query the current value
+ of a specific boolean attribute
+
+ Parameters : p_attr : Pointer to boolean attribute
+
+
+ Remarks : sdvo_query_bool_attr scans the g_bool_data list to find
+ the boolean attribute of id specified in p_attr.
+ If found it executes the opcode_get command to get the current
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_bool_attr(sdvo_device_context_t *p_ctx,
+ pd_bool_attr_t *p_attr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(g_bool_data); i++) {
+
+ if (g_bool_data[i].id == p_attr->id) {
+
+ sdvo_status_t status;
+ i2c_reg_t ret_value;
+
+ status = sdvo_execute_command(p_ctx, g_bool_data[i].opcode_get,
+ 0, NULL,
+ 1, &ret_value);
+
+ if (status == SS_SUCCESS) {
+ if (ret_value & g_bool_data[i].bit_mask_cur) {
+ p_attr->current_value = 1;
+ } else {
+ p_attr->current_value = 0;
+ }
+
+ if (g_bool_data[i].bit_mask_def != 0) {
+ p_attr->default_value = ret_value & g_bool_data[i].bit_mask_def;
+ }
+ }
+
+ return status;
+ }
+ }
+
+ return SS_INVALID_ARGUMENT;
+}
+
+
+/* ============================================================================
+ Function : sdvo_alter_bool_attr is called to set the new value of a
+ specific boolean attribute
+
+ Parameters : p_attr : Pointer to boolean attribute
+
+ Remarks : sdvo_alter_range_attr scans the g_bool_data list to find
+ the bool attribute of id specified in p_attr.
+ If found it executes the opcode_set command to set the new
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_bool_attr(sdvo_device_context_t *p_ctx,
+ pd_bool_attr_t *p_attr, unsigned long new_value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(g_bool_data); i++) {
+ if (g_bool_data[i].id == p_attr->id) {
+ sdvo_status_t status;
+ i2c_reg_t cur_value;
+
+ status = sdvo_execute_command(p_ctx, g_bool_data[i].opcode_get,
+ 0, NULL,
+ 1, &cur_value);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+#ifndef CONFIG_MICRO
+ if(p_attr->id == PD_ATTR_ID_DITHER){
+ cur_value &= 0;
+ }
+#endif
+ if (new_value) {
+ cur_value |= g_bool_data[i].bit_mask_cur;
+ } else {
+ cur_value &= ~g_bool_data[i].bit_mask_cur;
+ }
+
+ status = sdvo_execute_command(p_ctx, g_bool_data[i].opcode_set,
+ 1, &cur_value,
+ 0, NULL);
+ return status;
+ }
+ }
+
+ return SS_INVALID_ARGUMENT;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_list_attrs returns all the available list
+ attributes
+
+ Parameters : p_attr : Returns the list of avaliable list attributes
+
+ Remarks : sdvo_get_list_attrs returns all the list attributes
+ from g_list_data table that are supported by the SDVO device.
+ It allocates memory for all possible list attributes.
+ The caller is responsible for adding the list attributes
+ to the port driver attribute table and freeing the memory
+ allocated for p_attr.
+
+ Returns : Number of list attributes returned in pp_Attr list.
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_get_list_attrs(sdvo_device_context_t *p_ctx,
+ pd_list_attr_t *p_attr)
+{
+#ifndef CONFIG_MICRO
+ unsigned long num_attrs, i, j;
+ sdvo_status_t status;
+ sdvo_attr_list_entry_t *list_item;
+
+ list_item = NULL;
+ num_attrs = 0;
+ i = j = 0;
+
+ /* ..................................................................... */
+ if (p_attr == NULL) {
+
+ /* Just return the number of available attributes */
+ i2c_reg_t ret_value[8];
+ while (g_list_header[i].num_entries) {
+
+ status = sdvo_execute_command(p_ctx, g_list_header[i].opcode_get,
+ 0, NULL, 8, ret_value);
+
+ if (status == SS_SUCCESS) {
+ num_attrs += (g_list_header[i].num_entries + 1);
+ }
+
+ ++i; /* Skip to the next list hdr */
+ }
+
+ return num_attrs;
+ }
+
+ while (g_list_header[i].num_entries) {
+
+ pd_list_attr_t *p_hdr = &p_attr[num_attrs];
+
+ p_hdr->type = PD_ATTR_TYPE_LIST;
+ p_hdr->id = g_list_header[i].id;
+ p_hdr->num_entries = g_list_header[i].num_entries;
+ p_hdr->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+ status = sdvo_query_list_attr(p_ctx, p_hdr);
+ if (status != SS_SUCCESS) {
+ ++i; /* Skip to the next list header */
+ continue;
+ }
+
+ pd_strcpy(p_hdr->name, g_list_header[i].p_name);
+ p_hdr->default_index = p_hdr->current_index;
+
+ PD_DEBUG("sdvo : sdvo_get_list_attrs : "
+ "Adding attr='%s', id=%ld, default=%ld, current=%ld, "
+ "num_entries=%ld",
+ SDVO_GET_ATTR_NAME(p_hdr), p_hdr->id, p_hdr->default_index, p_hdr->current_index,
+ p_hdr->num_entries);
+
+ ++num_attrs;
+ /* Copy the list entries */
+ list_item = g_list_header[i].attr_list;
+ for (j = 0; j < g_list_header[i].num_entries; ++j, ++num_attrs) {
+
+ pd_list_entry_attr_t *p_entry =
+ (pd_list_entry_attr_t *)&p_attr[num_attrs];
+
+ p_entry->id = g_list_header[i].id; /* Header ID */
+ p_entry->type = PD_ATTR_TYPE_LIST_ENTRY;
+ p_entry->value = list_item[j].id; /* Entry ID */
+ p_entry->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+ pd_strcpy(p_entry->name, list_item[j].p_name);
+ PD_DEBUG("sdvo : sdvo_get_list_attrs : Entry[%ld]=%s, id=%ld, "
+ "value=%ld",
+ j, SDVO_GET_ATTR_NAME(p_entry), p_entry->id,
+ p_entry->value);
+ }
+
+ ++i; /* Skip to the next list header */
+ }
+
+ /* ..................................................................... */
+ return num_attrs;
+#else
+ return 0;
+#endif
+}
+
+
+/* ============================================================================
+ Function : sdvo_query_list_attr is called to query the current value
+ of a specific list attribute
+
+ Parameters : p_attr : Pointer to list header attribute
+
+ Remarks : sdvo_query_list_attr scans the g_list_data list to find
+ the list attribute of id specified in p_attr.
+ If found it executes the opcode_get command to get the current
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_list_attr(sdvo_device_context_t *p_ctx,
+ pd_list_attr_t *p_attr)
+{
+#ifndef CONFIG_MICRO
+ i2c_reg_t ret_value[8];
+ int i, j;
+ sdvo_status_t status;
+ sdvo_attr_list_entry_t *list_item;
+
+ i = 0;
+ list_item = NULL;
+ while (g_list_header[i].num_entries) {
+
+ if (g_list_header[i].id != p_attr->id) {
+ ++i; /* Skip to the next list hdr */
+ continue;
+ }
+
+ status = sdvo_execute_command(p_ctx, g_list_header[i].opcode_get,
+ 0, NULL,
+ 8, ret_value);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ for (j = 0; j < 8; ++j) {
+ ret_value[j] &= g_list_header[i].bit_masks[j];
+ }
+
+ list_item = g_list_header[i].attr_list;
+ for (j = 0; j < g_list_header[i].num_entries; ++j) {
+
+ if (ret_value[list_item[j].reg_offset] == list_item[j].value) {
+ p_attr->current_index = j + 1;
+
+ return SS_SUCCESS;
+ }
+ }
+
+ /* If current_index isn't found then the default hardware state is
+ * not in one of the known states, then set it to the first one */
+ p_attr->current_index = 1;
+ return sdvo_alter_list_attr(p_ctx, p_attr, 1);
+ }
+
+ PD_ERROR("sdvo : Warning ! sdvo_query_list_attr : Unable to find list "
+ "header");
+#endif
+ return SS_INVALID_ARGUMENT;
+}
+
+
+/* ============================================================================
+ Function : sdvo_alter_list_attr is called to set the new value of a
+ specific list attribute
+
+ Parameters : p_attr : Pointer to list attribute
+
+ Remarks : sdvo_alter_list_attr scans the g_list_data list to find
+ the list attribute of id specified in p_attr.
+ If found it executes the opcode_set command to set the new
+ value of the attribute.
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_list_attr(sdvo_device_context_t *p_ctx,
+ pd_list_attr_t *p_attr, unsigned long new_index)
+{
+#ifndef CONFIG_MICRO
+ unsigned short i, j;
+ sdvo_status_t status;
+ i2c_reg_t ret_value[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ sdvo_attr_list_entry_t *list_item;
+
+ if (new_index > p_attr->num_entries) {
+ return SS_INVALID_ARGUMENT;
+ }
+
+ list_item = NULL;
+ i = 0;
+ while (g_list_header[i].num_entries) {
+ if (g_list_header[i].id != p_attr->id) {
+ ++i; /* Skip to the next list hdr */
+ continue;
+ }
+
+ /* Found the list header */
+ /* Get the current value of the attribute(s) */
+ status = sdvo_execute_command(p_ctx, g_list_header[i].opcode_get,
+ 0, NULL, 8, ret_value);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+
+ /* Mask out the parameter bits */
+ for (j = 0; j < 8; ++j) {
+ ret_value[j] &= ~g_list_header[i].bit_masks[j];
+ }
+
+ list_item = g_list_header[i].attr_list; /* Get the list entries */
+ /* Set new index bits */
+ ret_value[list_item[new_index - 1].reg_offset] |=
+ list_item[new_index - 1].value;
+
+ status = sdvo_execute_command(p_ctx, g_list_header[i].opcode_set,
+ 8, ret_value, 0, NULL);
+ /* If opcode_set(new_value) is failed, assuming it will stay at old value.
+ * If this isn't the case, then opcode_set(old_value) is required. */
+ if (status != SS_SUCCESS) {
+ /* Set old value */
+ }
+ return status;
+ }
+#endif
+ return SS_INVALID_ARGUMENT;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
new file mode 100644
index 0000000..4c58315
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
@@ -0,0 +1,141 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_attr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Definitions for display attribute
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_ATTR_H_
+#define _SDVO_ATTR_H_
+
+unsigned long sdvo_get_static_attrs(sdvo_device_context_t *p_ctx, pd_attr_t *p_attr);
+sdvo_status_t sdvo_query_static_attr(sdvo_device_context_t *p_ctx, pd_attr_t *p_attr);
+sdvo_status_t sdvo_alter_static_attr(sdvo_device_context_t *p_ctx, pd_attr_t *p_attr,
+ unsigned long new_value);
+
+unsigned long sdvo_get_panel_pwr_seq_attrs(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_query_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_alter_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr,
+ unsigned long new_value);
+
+unsigned long sdvo_get_range_attrs(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_query_range_attr(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_alter_range_attr(sdvo_device_context_t *p_ctx, pd_range_attr_t *p_attr,
+ unsigned long new_value);
+
+unsigned long sdvo_get_bool_attrs(sdvo_device_context_t *p_ctx, pd_bool_attr_t *p_attr);
+sdvo_status_t sdvo_query_bool_attr(sdvo_device_context_t *p_ctx, pd_bool_attr_t *p_attr);
+sdvo_status_t sdvo_alter_bool_attr(sdvo_device_context_t *p_ctx, pd_bool_attr_t *p_attr,
+ unsigned long new_value);
+
+unsigned long sdvo_get_list_attrs(sdvo_device_context_t *p_ctx, pd_list_attr_t *p_attr);
+sdvo_status_t sdvo_query_list_attr(sdvo_device_context_t *p_ctx, pd_list_attr_t *p_attr);
+sdvo_status_t sdvo_alter_list_attr(sdvo_device_context_t *p_ctx, pd_list_attr_t *p_attr,
+ unsigned long new_value);
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_set_tv_optimal_settings(sdvo_device_context_t *p_ctx, unsigned char chron_tv_code);
+#endif
+
+/* .......................................................................... */
+/* Attribute Definitions */
+
+typedef struct {
+
+ unsigned long id;
+ char *p_name;
+ unsigned char num_bytes;
+ unsigned char opcode_max, opcode_get, opcode_set;
+
+} sdvo_range_attr_data_t;
+
+typedef struct {
+
+ unsigned long id;
+ char *p_name;
+ unsigned char bit_mask_cur, bit_mask_def;
+ unsigned char opcode_get, opcode_set;
+
+} sdvo_bool_attr_data_t;
+
+typedef struct {
+ unsigned long id;
+ char *p_name;
+ unsigned char reg_offset;
+ unsigned char value;
+} sdvo_attr_list_entry_t;
+
+typedef struct {
+ unsigned char num_entries;
+ unsigned long id;
+ char *p_name;
+ unsigned char opcode_get, opcode_set;
+ unsigned char bit_masks[8];
+ sdvo_attr_list_entry_t *attr_list;
+} sdvo_attr_list_header_t;
+
+#ifndef CONFIG_MICRO
+typedef struct {
+ unsigned char tv_code;
+ unsigned char hue;
+ unsigned char saturation;
+ unsigned char brightness;
+ unsigned char contrast;
+} sdvo_tv_optimal_settings_t;
+#endif
+
+#define PD_LVDS_COLOR_DEPTH_18 0
+#define PD_LVDS_COLOR_DEPTH_24 1
+
+#define PD_LVDS_CONNECTOR_SPWG 0
+#define PD_LVDS_CONNECTOR_OPEN_LDI 1
+
+#define PD_ANALOG_SRC_NO_DATA 0
+#define PD_ANALOG_SRC_PRE_RECORDED 2
+#define PD_ANALOG_SRC_NOT_PRE_RECORDED 3
+
+#define PD_SCAN_NO_DATA 0
+#define PD_SCAN_OVERSCANNED 1
+#define PD_SCAN_UNDERSCANNED 2
+
+#define PD_ASPECT_RATIO_NO_DATA 0
+#define PD_ASPECT_RATIO_4_3 1
+#define PD_ASPECT_RATIO_16_9 2
+
+#define PD_ACTIVE_FORMAT_NO_DATA 0
+#define PD_ACTIVE_FORMAT_SQUARE_PIXELS 8
+#define PD_ACTIVE_FORMAT_4_3_CENTER 9
+#define PD_ACTIVE_FORMAT_16_9_CENTER 10
+#define PD_ACTIVE_FORMAT_14_9_CENTER 11
+#define PD_ACTIVE_FORMAT_16_9_LETTERBOX_TOP 2
+#define PD_ACTIVE_FORMAT_14_9_LETTERBOX_TOP 3
+#define PD_ACTIVE_FORMAT_16_9_LETTERBOX_CENTER 4
+#define PD_ACTIVE_FORMAT_4_3_SHOOT_PROTECT_14_9_CENTER 13
+#define PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_14_9_CENTER 14
+#define PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_4_3_CENTER 15
+
+#endif /* _SDVO_ATTR_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
new file mode 100644
index 0000000..81dd8f7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
@@ -0,0 +1,524 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_hdmi.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Port driver HDMI interface functions
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_hdmi.h"
+
+#if 0
+ /* HDMI Attributes
+ Currently if omitting out this attributes as this should NOT be avalable
+ to user
+ TODO: Integrate this attributes into HDMI */
+/* HDMI attributes */
+#define PD_HDMI_COLORIMETRY_256_RGB 0
+#define PD_HDMI_COLORIMETRY_220_RGB 1
+#define PD_HDMI_COLORIMETRY_422_YCRCB 2
+#define PD_HDMI_COLORIMETRY_444_YCRCB 3
+
+#define PD_HDMI_PIXEL_REPLICATION_1X_REPITION 1
+#define PD_HDMI_PIXEL_REPLICATION_2X_REPITION 2
+#define PD_HDMI_PIXEL_REPLICATION_4X_REPITION 4
+/-----------------------------------------------------------------------------/
+ {PD_ATTR_ID_COLORIMETRY, MAKE_NAME("Colorimetry"), {4}, {0x0F},
+ GET_CURRENT_COLORIMETRY, SET_CURRENT_COLORIMETRY},
+
+ /* 256 RGB is passthrough, real value is 0x01 but 0x00 works as well
+ and upon boot up the value is 0x00 */
+ {PD_HDMI_COLORIMETRY_256_RGB,
+ MAKE_NAME("RGB 256 level"), {0}, {0x00}, 0, 0},
+ {PD_HDMI_COLORIMETRY_220_RGB,
+ MAKE_NAME("RGB 220 level"), {0}, {0x02}, 0, 0},
+ {PD_HDMI_COLORIMETRY_422_YCRCB,
+ MAKE_NAME("4:2:2 YcrCb"), {0}, {0x04}, 0, 0},
+ {PD_HDMI_COLORIMETRY_444_YCRCB,
+ MAKE_NAME("4:4:4 YcrCb"), {0}, {0x08}, 0, 0},
+
+ {PD_ATTR_ID_PIXEL_REPLICATION, MAKE_NAME("Pixel Replication"), {3}, {0x1F},
+ GET_PIXEL_REPLICATION, SET_PIXEL_REPLICATION},
+
+ {PD_HDMI_PIXEL_REPLICATION_1X_REPITION,
+ MAKE_NAME("No Repetition"), {0}, {0x00}, 0, 0},
+ {PD_HDMI_PIXEL_REPLICATION_2X_REPITION,
+ MAKE_NAME("1X Repetition"), {0}, {0x01}, 0, 0},
+ {PD_HDMI_PIXEL_REPLICATION_4X_REPITION,
+ MAKE_NAME("3X Repetition"), {0}, {0x03}, 0, 0},
+#endif
+#if defined(SDVO_HDMI)
+
+/* ============================================================================
+ Function : sdvo_hdmi_transmitter
+
+ Parameters :
+
+ Remarks : Detect if transmitter is a HDMI transmitter.
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_transmitter(sdvo_device_context_t *p_ctx)
+{
+ return sdvo_get_supported_encoding_modes(p_ctx,&(p_ctx->hdmi.version));
+}
+
+/* ============================================================================
+ Function : sdvo_hdmi_support is called to see if the transmitter
+ and the monitor device support HDMI.
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+
+ Remarks :
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_support(void *p_context)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status = SS_SUCCESS;
+
+ /* Monitor support is determined by valid CEA 861 extension and */
+ /* vendor block with 0xC03 IEEE regstration ID */
+ /*
+ if((p_ctx->p_callback->eld) == NULL){
+ return SS_NOT_SUPPORTED;
+ }
+
+ if((*p_ctx->p_callback->eld)->vendor_block_size) {
+ return SS_NOT_SUPPORTED;
+ }
+
+ if((*p_ctx->p_callback->eld)->vendor_ieee_id != CEA_IEEE_HDMI_ID) {
+ return SS_NOT_SUPPORTED;
+ }
+ */
+ /* Transmitter support is determined by SDVO GetSupportDigitalEncodingModes */
+ status = sdvo_hdmi_transmitter(p_ctx);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+
+ return SS_SUCCESS;
+}
+
+
+
+/* ============================================================================
+ Function : sdvo_hdmi_audio_characteristic
+
+ Parameters :
+
+ Remarks : Set audio characteristic to be used in ELD calcilation.
+ TODO: Make sure this is recalled if hotplug is detected
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_audio_characteristic(sdvo_device_context_t *p_ctx)
+{
+ sdvo_status_t status;
+ i2c_reg_t hdmi_audio_char[3];
+
+ /* Skip since no CEA data available */
+ if((!p_ctx->p_callback) || ((p_ctx->p_callback->eld) == NULL)){
+ return SS_NOT_SUPPORTED;
+ }
+ if(*(p_ctx->p_callback->eld) == NULL){
+ return SS_NOT_SUPPORTED;
+ }
+
+ status = sdvo_get_hdmi_audio_transmission_char(p_ctx, hdmi_audio_char);
+ if(status == SS_SUCCESS){
+ (*p_ctx->p_callback->eld)->audio_flag |= PD_AUDIO_CHAR_AVAIL;
+ (*p_ctx->p_callback->eld)->NPL = hdmi_audio_char[0];
+ (*p_ctx->p_callback->eld)->K0 = hdmi_audio_char[1];
+ (*p_ctx->p_callback->eld)->K1 = hdmi_audio_char[2];
+ }else{
+ (*p_ctx->p_callback->eld)->audio_flag &= ~PD_AUDIO_CHAR_AVAIL;
+ }
+
+ return SS_SUCCESS;
+}
+
+/* ============================================================================
+ Function : sdvo_hdmi_configure is called to program AVI infoframes, SPD
+ infoframes, ELD data for audio, colorimetry and pixel replication.
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+ p_mode: Point to current video output display mode
+
+ Remarks :
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_configure(sdvo_device_context_t *p_ctx)
+{
+ i2c_reg_t data;
+ sdvo_status_t status = SS_SUCCESS;
+ i2c_reg_t encoding_mode = DVI_MODE;
+
+ if((p_ctx->p_callback->eld) == NULL){
+ sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+ return SS_NOT_SUPPORTED;
+ }
+ if(*(p_ctx->p_callback->eld) == NULL){
+ sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+ return SS_NOT_SUPPORTED;
+ }
+
+ /* Prepare buffer for video information. Video only requires a total of 3
+ * buffers. (0)ELD (1)AVI (2)SPD. SO we will set it to 2 indexbased buffer */
+ status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+ 0, NULL,
+ 1, &data);
+ data = 2;
+ status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+ 1, &data,
+ 0, NULL);
+
+ /* Send pixel replication and colorimetry */
+ if (sdvo_hdmi_pr_and_color(p_ctx) != SS_SUCCESS) {
+ PD_ERROR("Fail toset pixel replication and colorimetry");
+ }
+
+ /* Build and send ELD Info Frames */
+ if(sdvo_hdmi_send_eld(p_ctx) != SS_SUCCESS){
+ PD_ERROR("Fail to write ELD to transmitter");
+ }
+
+ /* Build and send AVI Info Frames */
+ if (sdvo_hdmi_avi_info_frame(p_ctx) != SS_SUCCESS) {
+ PD_ERROR("Fail to write AVI infoframes to transmitter");
+ }
+
+ /* Build and send SPD Info Frames */
+#ifndef CONFIG_MICRO
+ if (sdvo_hdmi_spd_info_frame(p_ctx) != SS_SUCCESS) {
+ PD_ERROR("Fail to write SPD Infoframes to transmitter");
+ }
+#endif
+ /* Set to HDMI mode */
+ if((*p_ctx->p_callback->eld)->audio_support){
+ encoding_mode = HDMI_MODE;
+ }
+ status = sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+ if (status != SS_SUCCESS) {
+ PD_DEBUG("sdvo: Fail to set HDMI mode ");
+ }
+
+ return SS_SUCCESS;
+}
+/* ============================================================================
+ Function : sdvo_hdmi_pr_and_color is called to send pixel replication
+ and colorimetry data to SDVO device.
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+
+ Remarks :
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_pr_and_color(sdvo_device_context_t *p_context)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status = SS_SUCCESS;
+ i2c_reg_t pixel_rep = (i2c_reg_t)(*p_ctx->p_callback->eld)->pixel_rep - 1;
+ i2c_reg_t quantization = (i2c_reg_t)(*p_ctx->p_callback->eld)->quantization;
+
+ /* Set pixel replication */
+ status = sdvo_execute_command(p_ctx, SET_PIXEL_REPLICATION,
+ 1, &pixel_rep,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+
+ /* Set colorimetry */
+ status = sdvo_execute_command(p_ctx, SET_CURRENT_COLORIMETRY,
+ 1, &quantization,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ return status;
+ }
+ return status;
+};
+/* ============================================================================
+ Function : sdvo_hdmi_send_eld
+
+ Parameters :
+
+ Remarks : Builds eld structure and write it into SDVO ELD buffers
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_send_eld(sdvo_device_context_t *p_ctx)
+{
+ sdvo_status_t status;
+ sdvo_audio_state_t audio_state;
+
+ if((p_ctx->p_callback->eld) == NULL){
+ return SS_NOT_SUPPORTED;
+ }
+ if(*(p_ctx->p_callback->eld) == NULL){
+ return SS_NOT_SUPPORTED;
+ }
+ if(!((*p_ctx->p_callback->eld)->audio_flag & ELD_AVAIL)){
+ PD_DEBUG("Eld not available");
+ return SS_NOT_SUPPORTED;
+ }
+
+ /* ELD 1.0, CEA version retrieve from callback */
+ (*p_ctx->p_callback->eld)->cea_ver = 0;
+ (*p_ctx->p_callback->eld)->eld_ver = 1;
+
+ /* Capability Flags */
+ (*p_ctx->p_callback->eld)->repeater = 0;
+ (*p_ctx->p_callback->eld)->hdcp = 0;
+#ifdef CONFIG_MICRO
+ (*p_ctx->p_callback->eld)->_44ms = 0;
+#endif
+
+ /* We do not provide Monitor length */
+ (*p_ctx->p_callback->eld)->mnl = 0;
+
+#ifdef CONFIG_MICRO
+ (*p_ctx->p_callback->eld)->sadc = 0;
+#endif
+
+ audio_state.value = 0;
+ audio_state.eld_valid = FALSE;
+ audio_state.presense_detect = TRUE;
+ status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
+ 1, (i2c_reg_t *)&audio_state,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("Set Audio eld_valid fail (FALSE)");
+ return status;
+ }
+
+ /* Write ELD to SDVO buffers */
+ status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_ELD_BUFFER ,
+ 0, (*p_ctx->p_callback->eld)->eld_ptr, SDVO_HDMI_ELD_BUFFER_SIZE);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("Write ELD Failed !");
+ return status;
+ }
+
+ /* Send audio state change by toggling eld_valid bit */
+ audio_state.eld_valid = TRUE;
+ status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
+ 1, (i2c_reg_t *)&audio_state,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("Set Audio eld_valid fail (TRUE)");
+ return status;
+ }
+
+ return SS_SUCCESS;
+}
+/* ============================================================================
+ Function : sdvo_hdmi_avi_info_frame is called to program AVI infoframes
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+ p_mode: Point to current video output display mode
+
+ Remarks :
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_avi_info_frame(sdvo_device_context_t *p_context)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status = SS_SUCCESS;
+ unsigned long sum = 0;
+ int i;
+ sdvo_avi_info_t avi;
+
+ /* Initialize AVI InfoFrame to no scan info, no bar info, no active format */
+ /* mode rgb, active format same as picture format */
+ /* no aspect ratio, no colorimetry, no scaling */
+ pd_memset(&avi, 0, sizeof(sdvo_avi_info_t));
+ avi.header.type = SDVO_HDMI_AVI_INFO_TYPE;
+ avi.header.version = 2;
+ avi.header.length = SDVO_HDMI_AVI_BUFFER_SIZE - sizeof(sdvo_info_header_t);
+
+ /* Fill in VIC, colorimetry, aspect ratio */
+
+ /* Set Video ID Code */
+ avi.video_id_code = (unsigned char)(*p_ctx->p_callback->eld)->video_code;
+
+ /* Set aspect ratio */
+ avi.pic_aspect_ratio = (unsigned char)(*p_ctx->p_callback->eld)->aspect_ratio;
+
+ /* Set Colorimetry */
+ avi.colorimetry = (unsigned char)(*p_ctx->p_callback->eld)->colorimetry;
+
+ /* Calc checksum */
+ for (i= 0; i < SDVO_HDMI_AVI_BUFFER_SIZE; i++) {
+ sum += avi.data[i];
+ }
+ avi.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
+
+ /* Send data to SDVO device */
+ status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_AVI_BUFFER, 0, avi.data,
+ SDVO_HDMI_AVI_BUFFER_SIZE);
+ return status;
+};
+/* ============================================================================
+ Function : sdvo_hdmi_spd_info_frame is called to program SPD infoframes
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+
+ Remarks :
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_spd_info_frame(sdvo_device_context_t *p_context)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status = SS_SUCCESS;
+ sdvo_spd_info_t spd;
+ unsigned long sum = 0;
+ int i;
+
+ /* Initialize SPD InfoFrame to zero */
+ pd_memset(&spd, 0, sizeof(sdvo_spd_info_t));
+ spd.header.type = SDVO_HDMI_SPD_INFO_TYPE;
+ spd.header.version = 1;
+ spd.header.length = SDVO_HDMI_SPD_BUFFER_SIZE - sizeof(sdvo_info_header_t);
+
+ pd_memcpy(spd.vendor_name, SDVO_HDMI_VENDOR_NAME, SDVO_HDMI_INTEL_VENDOR_NAME_SIZE);
+ pd_memcpy(spd.product_desc,
+ SDVO_HDMI_VENDOR_DESCRIPTION, SDVO_HDMI_IEGD_VENDOR_DESCRIPTION_SIZE);
+ spd.source_device = SDVO_HDMI_SPD_SOURCE_PC;
+
+ /* Calc checksum */
+ for (i= 0; i < SDVO_HDMI_SPD_BUFFER_SIZE; i++) {
+ sum += spd.data[i];
+ }
+ spd.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
+
+ /* Send data to SDVO device */
+ status = sdvo_hdmi_write_buffer
+ (p_ctx, SDVO_HDMI_SPD_BUFFER, 0, spd.data, SDVO_HDMI_SPD_BUFFER_SIZE);
+ return status;
+};
+/* ============================================================================
+ Function : sdvo_hdmi_write_buffer
+
+ Parameters :
+
+ Remarks : Write into SDVO buffers
+
+ Returns :
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_write_buffer
+ (sdvo_device_context_t *p_ctx,unsigned char index,
+ unsigned char offset, unsigned char *input, int len)
+{
+ sdvo_status_t status;
+ i2c_reg_t hdmi_index[2],data[8];
+ int buffer_size = 0;
+ unsigned char total_bytes, *p_sdvo_buffer, *ori_p_sdvo_buffer;
+
+ /* Set Buffer index and offset */
+ hdmi_index[0] = index;
+ hdmi_index[1] = offset;
+ status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_INDEX,
+ 2, hdmi_index,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("HDMI wirte buffer fail : Set index");
+ return status;
+ }
+
+ /* Setup buffer transmit rate */
+ if(index != SDVO_HDMI_ELD_BUFFER){
+ data[0] = SDVO_HDMI_TRANSMIT_EVERY;
+ status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_TRANSMIT_RATE,
+ 1, data,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("HDMI wirte buffer fail : Transmite rate");
+ return status;
+ }
+ }
+ else {
+ status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_TRANSMIT_RATE,
+ 0, NULL,
+ 1, data);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("HDMI wirte buffer fail : Transmite rate");
+ return status;
+ }
+ }
+
+ /* Get buffer size info */
+ status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_INFO,
+ 0, NULL,
+ 1, (i2c_reg_t *)&data);
+ buffer_size = data[0] + 1;
+ /* Minimum buffer size is 3 then something is wrong */
+ if (status != SS_SUCCESS || buffer_size <0x03) {
+ PD_ERROR("HDMI wirte buffer fail : Buffer size");
+ return status;
+ }
+
+ /* Make sure to query size of buffer from SDVO and use it, not size of source infoframe buffers */
+ /* copy structs into cleared memory the size of SDVO buffer */
+ p_sdvo_buffer = pd_malloc(buffer_size);
+ ori_p_sdvo_buffer = p_sdvo_buffer;
+ pd_memset(p_sdvo_buffer, 0, buffer_size);
+ pd_memcpy(p_sdvo_buffer, input, (len < buffer_size) ? len : buffer_size);
+
+ while(buffer_size) {
+ //total_bytes = (buffer_size >= 8) ? 8:buffer_size;
+ if(buffer_size >= 8) total_bytes = 8;
+ else total_bytes = (unsigned char)buffer_size;
+
+ status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_DATA,
+ total_bytes, (i2c_reg_t *)p_sdvo_buffer,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("HDMI wirte buffer fail : Set buffer data");
+ return status;
+ }
+ p_sdvo_buffer +=total_bytes;
+ buffer_size -= total_bytes;
+ };
+
+ pd_free(ori_p_sdvo_buffer);
+ return SS_SUCCESS;
+}
+
+#endif/* SDVO_HDMI */
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
new file mode 100644
index 0000000..64c06c1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
@@ -0,0 +1,182 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_hdmi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Main include file for SDVO port driver HDMI interface function
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_PORT_HDMI_H_
+#define _SDVO_PORT_HDMI_H_
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+#include "sdvo_port.h"
+#include "sdvo_intf.h"
+
+/* VBios abstraction macro */
+#if !defined(CONFIG_MICRO)
+#define SDVO_HDMI
+#endif
+
+
+#if defined(SDVO_HDMI)
+
+#define SDVO_HDMI_ELD_BUFFER_SIZE 256
+#define SDVO_HDMI_AVI_BUFFER_SIZE 17
+#define SDVO_HDMI_SPD_BUFFER_SIZE 29
+#define SDVO_HDMI_ELD_BUFFER 0 /* ELD buffer index */
+#define SDVO_HDMI_AVI_BUFFER 1 /* AVI buffer index */
+#define SDVO_HDMI_SPD_BUFFER 2 /* SPD buffer index */
+#define SDVO_HDMI_ELD_INFO_TYPE 0x00 /* ELD buffer type */
+#define SDVO_HDMI_AVI_INFO_TYPE 0x82 /* AVI buffer type */
+#define SDVO_HDMI_SPD_INFO_TYPE 0x83 /* SPD buffer type */
+#define SDVO_HDMI_AVI_BUFFER_SIZE 17
+#define SDVO_HDMI_TRANSMIT_DISABLE 0x00
+#define SDVO_HDMI_TRANSMIT_ONCE 0x80
+#define SDVO_HDMI_TRANSMIT_EVERY 0xC0
+
+#define SDVO_HDMI_VENDOR_NAME "Intel"
+#define SDVO_HDMI_VENDOR_DESCRIPTION "IEGD Driver"
+#define SDVO_HDMI_INTEL_VENDOR_NAME_SIZE 6
+#define SDVO_HDMI_IEGD_VENDOR_DESCRIPTION_SIZE 12
+
+#define SDVO_HDMI_VENDOR_NAME_SIZE 8
+#define SDVO_HDMI_VENDOR_DESCRIPTION_SIZE 16
+#define SDVO_HDMI_SPD_SOURCE_PC 0x09
+
+#define DVI_MODE 0
+#define HDMI_MODE 1
+sdvo_status_t sdvo_hdmi_transmitter(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_support(void *p_context);
+sdvo_status_t sdvo_hdmi_audio_characteristic(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_configure(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_hdmi_pr_and_color(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_send_eld(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_hdmi_avi_info_frame(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_spd_info_frame(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_write_buffer
+ (sdvo_device_context_t *p_ctx,unsigned char index,
+ unsigned char offset, unsigned char *input, int len);
+
+typedef union
+{
+ unsigned char value;
+ struct {
+ unsigned char eld_valid: 1;
+ unsigned char presense_detect: 1;
+ unsigned char cp_ready: 1;
+ unsigned char reserved: 5;
+ };
+} sdvo_audio_state_t;
+/* AVI Info Frames version 2 */
+typedef struct
+{
+ unsigned char type;
+ unsigned char version;
+ unsigned char length;
+ unsigned char chksum;
+} sdvo_info_header_t;
+
+typedef union
+{
+ unsigned char data[SDVO_HDMI_AVI_BUFFER_SIZE];
+ struct {
+ sdvo_info_header_t header;
+ union {
+ unsigned char data1;
+ struct {
+ unsigned char scan_info: 2;
+ unsigned char bar_info: 2;
+ unsigned char active_format: 1;
+ unsigned char color_space: 2;
+ unsigned char reserved1: 1;
+ };
+ };
+ union {
+ unsigned char data2;
+ struct {
+ unsigned char format_aspect_ratio: 4;
+ unsigned char pic_aspect_ratio: 2;
+ unsigned char colorimetry: 2;
+ };
+ };
+ union {
+ unsigned char data3;
+ struct {
+ unsigned char pic_scaling: 2;
+ unsigned char reserved2: 6;
+ };
+ };
+ union {
+ unsigned char data4;
+ struct {
+ unsigned char video_id_code: 7;
+ unsigned char reserved3: 1;
+ };
+ };
+ union {
+ unsigned char data5;
+ struct {
+ unsigned char pixel_rep: 4;
+ unsigned char reserved4: 4;
+ };
+ };
+ unsigned char bar1;
+ unsigned char bar2;
+ unsigned char bar3;
+ unsigned char bar4;
+ unsigned char bar5;
+ unsigned char bar6;
+ unsigned char bar7;
+ unsigned char bar8;
+ };
+} sdvo_avi_info_t;
+
+typedef union
+{
+ unsigned char data[SDVO_HDMI_SPD_BUFFER_SIZE];
+ struct {
+ sdvo_info_header_t header;
+ unsigned char vendor_name[SDVO_HDMI_VENDOR_NAME_SIZE];
+ unsigned char product_desc[SDVO_HDMI_VENDOR_DESCRIPTION_SIZE];
+ unsigned char source_device;
+ };
+} sdvo_spd_info_t;
+
+
+#define SDVO_INIT_HDMI(a) sdvo_hdmi_audio_characteristic(a)
+#define SDVO_IS_HDMI_SUPPORTED(a) sdvo_hdmi_support(a)
+#define SDVO_CONFIGURE_HDMI(a) sdvo_hdmi_configure(a)
+#else
+#define SDVO_INIT_HDMI(a)
+#define SDVO_IS_HDMI_SUPPORTED(a) SS_NOT_SUPPORTED
+#define SDVO_CONFIGURE_HDMI(a)
+#endif /* SDVO_HDMI */
+
+#endif /* _SDVO_PORT_HDMI_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
new file mode 100644
index 0000000..e2fb741
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
@@ -0,0 +1,725 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_intf.c
+ * $Revision: 1.12 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Functions that provide interface to SDVO device
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_port.h"
+
+/* .......................................................................... */
+void sdvo_convert_parm_to_dtd(i2c_reg_t parm[16], sdvo_dtd_t *p_dtd);
+void sdvo_convert_dtd_to_parm(
+ sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd,
+ i2c_reg_t parm[16]);
+
+
+/* .......................................................................... */
+/* .......................................................................... */
+/* ============================================================================
+ Function : sdvo_execute_command transfers a command and argument to
+ the SDVO device and returns the status of execution
+
+ Parameters : opcode : One of the sdvo_opcode_t opcodes
+ num_args : Number of arguments 0-8
+ p_arg : List of arguments
+ num_returns : Expected number of returns 0-8
+ p_ret_value : List of return values
+
+ Remarks : sdvo_execute_command is core function that is called by other
+ SDVO interface functions to execute a command.
+ The arguments of the command are transferred to the argument
+ I2C registers of the SDVO device
+ The opcode is then transferred to the opcode I2C register
+ It then waits for the command to complete by reading the
+ status I2C register up to 3 times
+
+ Returns : sdvo_status_t : Status of command execution
+ ------------------------------------------------------------------------- */
+sdvo_status_t sdvo_execute_command(sdvo_device_context_t *p_ctx,
+ sdvo_opcode_t opcode,
+ i2c_reg_t num_args, i2c_reg_t *p_arg,
+ i2c_reg_t num_returns, i2c_reg_t *p_ret_value)
+{
+ i2c_reg_t status, i;
+
+ /* ..................................................................... */
+ /* Error checking */
+ if ((num_args > SDVO_MAX_ARGS) || (num_returns > SDVO_MAX_RETURNS)) {
+
+ return SS_UNSUCCESSFUL;
+ }
+
+ if ((num_args > 0) && (p_arg == NULL)) {
+
+ return SS_UNSUCCESSFUL;
+ }
+
+ if ((num_returns > 0) && (p_ret_value == NULL)) {
+
+ return SS_UNSUCCESSFUL;
+ }
+
+ /* ..................................................................... */
+ /* Write the arguments and the opcode */
+ for (i = 0; i < num_args; i++) {
+
+ if (! sdvo_write_i2c_reg(p_ctx, (i2c_reg_t)(SDVO_REG_ARG_START - i),
+ p_arg[i])) {
+
+ return SS_WRITE_FAILED;
+ }
+ }
+
+ if (! sdvo_write_i2c_reg(p_ctx, (i2c_reg_t)SDVO_REG_OPCODE,
+ (i2c_reg_t)opcode)) {
+
+ return SS_WRITE_FAILED;
+ }
+
+ /* ..................................................................... */
+ /* Wait for command to complete */
+ for (i = 0; i < SDVO_MAX_RETRIES; i++) {
+
+ if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_STATUS, &status)) {
+
+ return SS_READ_FAILED;
+ }
+
+ if (status != SS_PENDING) {
+
+ break;
+ }
+ }
+
+ /* ..................................................................... */
+ /* Read the return parameters if command succeeded */
+ if (status == SS_SUCCESS) {
+
+ for (i = 0; i < num_returns; i++) {
+
+ if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_RETURN_START + i,
+ &p_ret_value[i])) {
+
+ return SS_READ_FAILED;
+ }
+ }
+ }
+
+ return status;
+}
+
+sdvo_status_t sdvo_execute_command_read (sdvo_device_context_t *p_ctx,
+ i2c_reg_t num_returns, i2c_reg_t *p_ret_value)
+{
+ i2c_reg_t status, i;
+
+ for (i = 0; i < SDVO_MAX_RETRIES; i++) {
+ if (!sdvo_read_i2c_reg(p_ctx, SDVO_REG_STATUS, &status)) {
+ return SS_READ_FAILED;
+ }
+
+ if (status != SS_PENDING) {
+ break;
+ }
+ }
+
+ /* Read the return parameters if command succeeded */
+ if (status == SS_SUCCESS) {
+ for (i = 0; i < num_returns; i++) {
+ if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_RETURN_START + i,
+ &p_ret_value[i])) {
+ return SS_READ_FAILED;
+ }
+ }
+ }
+ return status;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_reset(sdvo_device_context_t *p_ctx)
+{
+ return sdvo_execute_command(p_ctx, RESET,
+ 0, NULL,
+ 0, NULL);
+}
+#endif
+
+sdvo_status_t sdvo_get_device_capabilities(sdvo_device_context_t *p_ctx,
+ sdvo_device_capabilities_t *p_Dev_Cap)
+{
+ return sdvo_execute_command(p_ctx, GET_DEVICE_CAPABILITIES,
+ 0, NULL,
+ 8, (i2c_reg_t *)p_Dev_Cap);
+}
+
+
+sdvo_status_t sdvo_get_trained_inputs(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Out)
+{
+ return sdvo_execute_command(p_ctx, GET_TRAINED_INPUTS,
+ 0, NULL,
+ 1, p_Out);
+}
+
+
+sdvo_status_t sdvo_get_active_outputs(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t *p_Out_Flags)
+{
+ return sdvo_execute_command(p_ctx, GET_ACTIVE_OUTPUTS,
+ 0, NULL,
+ 2, (i2c_reg_t *)p_Out_Flags);
+}
+
+
+sdvo_status_t sdvo_set_active_outputs(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags)
+{
+ return sdvo_execute_command(p_ctx, SET_ACTIVE_OUTPUTS,
+ 2, (i2c_reg_t *)&out_flags,
+ 0, NULL);
+}
+
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_in_out_map(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags[2])
+{
+ return sdvo_execute_command(p_ctx, GET_IN_OUT_MAP,
+ 0, NULL,
+ 4, (i2c_reg_t *)out_flags);
+}
+#endif
+
+sdvo_status_t sdvo_set_in_out_map(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags[2])
+{
+ return sdvo_execute_command(p_ctx, SET_IN_OUT_MAP,
+ 4, (i2c_reg_t *)out_flags,
+ 0, NULL);
+}
+
+
+sdvo_status_t sdvo_get_attached_displays(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t *p_Out_Flags)
+{
+ i2c_reg_t status, i;
+
+ status = sdvo_execute_command(p_ctx, GET_ATTACHED_DISPLAYS,
+ 0, NULL,
+ 2, (i2c_reg_t *)p_Out_Flags);
+
+
+ PD_DEBUG("sdvo: GET_ATTACHED_DISPLAYS status = %d]", status);
+ for (i=0; i<5; i++) {
+ if (status == SS_SUCCESS)
+ break;
+ else {
+ pd_ui_usleep(50000); /* wait for 50ms */
+ status = sdvo_execute_command_read(p_ctx, 2, (i2c_reg_t *)p_Out_Flags);
+ }
+ }
+
+ PD_DEBUG("sdvo: sdvo_execute_command_read- no. of tries = [%d]", i);
+ return status;
+}
+
+
+sdvo_status_t sdvo_set_target_input(sdvo_device_context_t *p_ctx,
+ sdvo_target_input_t input)
+{
+ i2c_reg_t arg_value = input == SDVO0 ? 0 : 1;
+
+ return sdvo_execute_command(p_ctx, SET_TARGET_INPUT,
+ 1, (i2c_reg_t *)&arg_value,
+ 0, NULL);
+}
+
+
+sdvo_status_t sdvo_set_target_output(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags)
+{
+ return sdvo_execute_command(p_ctx, SET_TARGET_OUTUT,
+ 2, (i2c_reg_t *)&out_flags,
+ 0, NULL);
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd)
+{
+ sdvo_status_t status;
+ i2c_reg_t ret[16];
+
+ status = sdvo_execute_command(p_ctx, GET_INPUT_TIMINGS_PART1,
+ 0, NULL,
+ 8, ret);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ status = sdvo_execute_command(p_ctx, GET_INPUT_TIMINGS_PART2,
+ 0, NULL,
+ 8, &ret[8]);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+ return status;
+}
+#endif
+
+sdvo_status_t sdvo_set_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd)
+{
+ sdvo_status_t status;
+ i2c_reg_t parm[16];
+
+ sdvo_convert_dtd_to_parm(p_ctx, p_dtd, parm);
+
+ status = sdvo_execute_command(p_ctx, SET_INPUT_TIMINGS_PART1,
+ 8, parm,
+ 0, NULL);
+
+ if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+
+ return status;
+ }
+
+ status = sdvo_execute_command(p_ctx, SET_INPUT_TIMINGS_PART2,
+ 8, &parm[8],
+ 0, NULL);
+
+ return status;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_output_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd)
+{
+ sdvo_status_t status;
+ i2c_reg_t ret[16];
+
+ status = sdvo_execute_command(p_ctx, GET_OUTPUT_TIMINGS_PART1,
+ 0, NULL,
+ 8, ret);
+ if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+
+ return status;
+ }
+
+ status = sdvo_execute_command(p_ctx, GET_OUTPUT_TIMINGS_PART2,
+ 0, NULL,
+ 8, &ret[8]);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+ return status;
+}
+#endif
+
+sdvo_status_t sdvo_set_output_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd)
+{
+ sdvo_status_t status;
+ i2c_reg_t parm[16];
+
+ sdvo_convert_dtd_to_parm(p_ctx, p_dtd, parm);
+
+ status = sdvo_execute_command(p_ctx, SET_OUTPUT_TIMINGS_PART1,
+ 8, parm,
+ 0, NULL);
+
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ status = sdvo_execute_command(p_ctx, SET_OUTPUT_TIMINGS_PART2,
+ 8, &parm[8],
+ 0, NULL);
+
+ return status;
+}
+
+
+sdvo_status_t sdvo_get_preferred_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_create_preferred_timings_t *p_Timings,
+ sdvo_dtd_t *p_dtd)
+{
+ sdvo_status_t status;
+ i2c_reg_t ret[16];
+
+ /* ..................................................................... */
+ status = sdvo_execute_command(p_ctx, CREATE_PREFERRED_INPUT_TIMINGS,
+ 7, (i2c_reg_t *)p_Timings,
+ 0, NULL);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ /* ..................................................................... */
+ status = sdvo_execute_command(p_ctx, GET_PREFERRED_INPUT_TIMINGS_PART1,
+ 0, NULL,
+ 8, ret);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ status = sdvo_execute_command(p_ctx, GET_PREFERRED_INPUT_TIMINGS_PART2,
+ 0, NULL,
+ 8, &ret[8]);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ /* ..................................................................... */
+ sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+ return status;
+}
+
+
+/* in_clock[0] = min, in_clock[1] = max */
+sdvo_status_t sdvo_get_input_pixel_clock_range(sdvo_device_context_t *p_ctx,
+ unsigned short in_clock[2])
+{
+ return sdvo_execute_command(p_ctx, GET_INPUT_PIXEL_CLOCK_RANGE,
+ 0, NULL,
+ 4, (i2c_reg_t *)in_clock);
+}
+
+#ifndef CONFIG_MICRO
+/* out_Clock[0] = min, out_Clock[1] = max */
+sdvo_status_t sdvo_get_output_pixel_clock_range(sdvo_device_context_t *p_ctx,
+ unsigned short out_Clock[2])
+{
+ return sdvo_execute_command(p_ctx, GET_OUTPUT_PIXEL_CLOCK_RANGE,
+ 0, NULL,
+ 4, (i2c_reg_t *)out_Clock);
+}
+
+sdvo_status_t sdvo_get_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+ sdvo_clock_rate_mult_t *p_mult)
+{
+ *p_mult = 0;
+
+ return sdvo_execute_command(p_ctx, GET_SDVO_CLOCK_RATE_MULTIPLIER,
+ 0, NULL,
+ 1, (i2c_reg_t *)p_mult);
+}
+#endif
+
+
+sdvo_status_t sdvo_set_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+ sdvo_clock_rate_mult_t mult)
+{
+ return sdvo_execute_command(p_ctx, SET_SDVO_CLOCK_RATE_MULTIPLIER,
+ 1, (i2c_reg_t *)&mult,
+ 0, NULL);
+}
+
+
+sdvo_status_t sdvo_get_supported_power_states(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_pwr_state)
+{
+ return sdvo_execute_command(p_ctx, GET_SUPPORTED_POWER_STATES,
+ 0, NULL,
+ 1, p_pwr_state);
+}
+
+
+sdvo_status_t sdvo_get_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_pwr_state)
+{
+ return sdvo_execute_command(p_ctx, GET_POWER_STATE,
+ 0, NULL,
+ 1, p_pwr_state);
+}
+
+
+sdvo_status_t sdvo_set_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t pwr_state)
+{
+ return sdvo_execute_command(p_ctx, SET_POWER_STATE,
+ 1, &pwr_state,
+ 0, NULL);
+}
+
+
+sdvo_status_t sdvo_set_display_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t disp_pwr_state)
+{
+ return sdvo_execute_command(p_ctx, SET_DISPLAY_POWER_STATE,
+ 1, &disp_pwr_state,
+ 0, NULL);
+}
+#if !defined(CONFIG_MICRO)
+sdvo_status_t sdvo_set_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+ i2c_reg_t digital_encoding_mode)
+{
+ return sdvo_execute_command(p_ctx, SET_DIGITAL_ENCODING_MODE,
+ 1, &digital_encoding_mode,
+ 0, NULL);
+}
+sdvo_status_t sdvo_get_hdmi_audio_transmission_char(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *hdmi_reg)
+{
+ return sdvo_execute_command(p_ctx, GET_HDMI_AUDIO_TRANSMISSION_CHARACTERISTICS,
+ 0, NULL,
+ 3, (i2c_reg_t*)hdmi_reg);
+}
+sdvo_status_t sdvo_get_supported_encoding_modes(sdvo_device_context_t *p_ctx,
+ sdvo_digital_encode_modes_t *digital_encoding_modes)
+{
+ return sdvo_execute_command(p_ctx, GET_SUPPORTED_DIGITAL_ENCODING_MODES,
+ 0, NULL,
+ 8, (i2c_reg_t*)digital_encoding_modes);
+}
+
+sdvo_status_t sdvo_get_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *digital_encoding_mode)
+{
+ return sdvo_execute_command(p_ctx, GET_DIGITAL_ENCODING_MODE,
+ 0, NULL,
+ 1, (i2c_reg_t*)digital_encoding_mode);
+}
+/* ------------------------------------------------------------------------- */
+#endif
+sdvo_status_t sdvo_set_upscalar_coefficient(sdvo_device_context_t *p_ctx,
+ i2c_reg_t upscalar_coefficient)
+{
+ return sdvo_execute_command(p_ctx, SET_UPSCALAR_COEFFICIENTS,
+ 1, &upscalar_coefficient,
+ 0, NULL);
+}
+
+sdvo_status_t sdvo_get_tv_output_format(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_TV_Output_Format_Flag)
+{
+ return sdvo_execute_command(p_ctx, GET_TV_OUTPUT_FORMAT,
+ 0, NULL,
+ 6, p_TV_Output_Format_Flag);
+}
+
+sdvo_status_t sdvo_get_sdtv_resolution_support(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Requested_SDTV_Format_Flag,
+ i2c_reg_t *p_Resolution_Support_Flags)
+{
+ return sdvo_execute_command(p_ctx, GET_SDTV_RESOLUTION_SUPPORT,
+ 3, p_Requested_SDTV_Format_Flag,
+ 3, p_Resolution_Support_Flags);
+}
+
+sdvo_status_t sdvo_get_scaled_hdtv_resolution_support(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Requested_HDTV_Format_Flag,
+ i2c_reg_t *p_Resolution_Support_Flags)
+{
+ return sdvo_execute_command(p_ctx, GET_SCALED_HDTV_RESOLUTION_SUPPORT,
+ 4, p_Requested_HDTV_Format_Flag,
+ 8, p_Resolution_Support_Flags);
+}
+
+void sdvo_convert_parm_to_dtd(i2c_reg_t parm[16], sdvo_dtd_t *p_dtd)
+{
+ pd_memset(p_dtd, 0, sizeof(sdvo_dtd_t));
+
+ p_dtd->pixel_clock = (parm[1] << 8) | parm[0];
+ p_dtd->horz_active = ((parm[4] & 0xF0) << 4) | parm[2];
+ p_dtd->horz_blanking = ((parm[4] & 0x0F) << 8) | parm[3];
+ p_dtd->vert_active = ((parm[7] & 0xF0) << 4) | parm[5];
+ p_dtd->vert_blanking = ((parm[7] & 0x0F) << 8) | parm[6];
+ p_dtd->horz_sync_offset = ((parm[11] & 0xC0) << 2) | parm[8];
+ p_dtd->horz_sync_pulse_width= ((parm[11] & 0x30) << 4) | parm[9];
+ p_dtd->vert_sync_offset = (parm[14] & 0xC0) | ((parm[11] & 0x0C) << 2) |
+ ((parm[10] & 0xF0) >> 4);
+ p_dtd->vert_sync_pulse_width= ((parm[11] & 0x03) << 4) | (parm[10] & 0x0F);
+ p_dtd->dtd_flags = parm[12];
+ p_dtd->sdvo_flags = parm[13];
+}
+
+
+void sdvo_convert_dtd_to_parm(
+ sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd,
+ i2c_reg_t parm[16])
+{
+ unsigned int multp;
+
+ parm[0] = (p_dtd->pixel_clock & 0xFF);
+ parm[1] = ((p_dtd->pixel_clock & 0xFF00) >> 8);
+
+ if (p_ctx->st_sdvo) {
+ if (p_dtd->pixel_clock > 10000) { /* 100-200 MHz */
+ multp = 1;
+ } else if (p_dtd->pixel_clock > 5000) { /* 50-100 Mhz */
+ multp = 2;
+ } else { /* 25-50 Mhz */
+ multp = 4;
+ }
+
+ parm[2] = ((p_dtd->horz_active * multp) & 0xFF);
+ parm[3] = ((p_dtd->horz_blanking * multp) & 0xFF);
+ parm[4] = ((((p_dtd->horz_active * multp) & 0xF00) >> 4) |
+ (((p_dtd->horz_blanking * multp) & 0xF00) >> 8));
+ } else {
+ parm[2] = (p_dtd->horz_active & 0xFF);
+ parm[3] = (p_dtd->horz_blanking & 0xFF);
+ parm[4] = ((p_dtd->horz_active & 0xF00) >> 4) |
+ ((p_dtd->horz_blanking & 0xF00) >> 8);
+ }
+ parm[5] = (p_dtd->vert_active & 0xFF);
+ parm[6] = (p_dtd->vert_blanking & 0xFF);
+ parm[7] = ((p_dtd->vert_active & 0xF00) >> 4) |
+ ((p_dtd->vert_blanking & 0xF00) >> 8);
+ parm[8] = (p_dtd->horz_sync_offset & 0xFF);
+ parm[9] = (p_dtd->horz_sync_pulse_width & 0xFF);
+ parm[10] = ((p_dtd->vert_sync_offset & 0x0F) << 4) |
+ (p_dtd->vert_sync_pulse_width & 0x0F);
+ parm[11] = ((p_dtd->horz_sync_offset & 0x300) >> 2) |
+ ((p_dtd->horz_sync_pulse_width & 0x300) >> 4) |
+ ((p_dtd->vert_sync_offset & 0x30) >> 2) |
+ ((p_dtd->vert_sync_pulse_width & 0x30) >> 4);
+ parm[12] = p_dtd->dtd_flags;
+ parm[13] = p_dtd->sdvo_flags;
+ parm[14] = p_dtd->vert_sync_offset & 0xC0;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_min_max_pixel_clock(sdvo_device_context_t *p_ctx,
+ unsigned long *p_min_clock,
+ unsigned long *p_max_clock)
+{
+ sdvo_status_t status;
+ sdvo_clock_rate_mult_t clock_mult;
+ unsigned short in_range[2], out_range[2];
+
+ status = sdvo_get_clock_rate_multiplier(p_ctx, &clock_mult);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ status = sdvo_get_input_pixel_clock_range(p_ctx, in_range);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ status = sdvo_get_output_pixel_clock_range(p_ctx, out_range);
+ if (status != SS_SUCCESS) {
+
+ return status;
+ }
+
+ switch (clock_mult)
+ {
+ case CRM_1X :
+ break;
+
+ case CRM_2X :
+ in_range[0] *= 2;
+ break;
+
+ case CRM_4X :
+ in_range[0] *= 4;
+ break;
+
+ default :
+ return SS_INVALID_RETURN;
+ }
+
+ /* Minimum pixel clock supported is the maximum of min input/output */
+ /* pixel clock */
+ *p_min_clock = in_range[0] > out_range[0] ? in_range[0] : out_range[0];
+
+ /* Maximum pixel clock supported is minimum of max pixel clock of */
+ /* encoder and SDVO bus clock rate */
+ *p_max_clock = in_range[1] < out_range[1] ? in_range[1] : out_range[1];
+
+ return SS_SUCCESS;
+}
+#endif
+
+unsigned char sdvo_write_i2c_reg(sdvo_device_context_t *p_ctx, i2c_reg_t offset,
+ i2c_reg_t value)
+{
+ pd_reg_t reg_list[2];
+
+/* PD_DEBUG("sdvo : W : 0x%02x, 0x%02x", offset, value); */
+
+ reg_list[0].reg = offset;
+ reg_list[0].value = value;
+
+ reg_list[1].reg = PD_REG_LIST_END;
+
+ if (p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,
+ PD_REG_I2C)) {
+
+ return FALSE;
+
+ }else {
+
+ return TRUE;
+ }
+}
+
+
+unsigned char sdvo_read_i2c_reg(sdvo_device_context_t *p_ctx, unsigned char offset,
+ i2c_reg_t *p_Value)
+{
+ pd_reg_t reg_list[2];
+
+ reg_list[0].reg = offset;
+ reg_list[1].reg = PD_REG_LIST_END;
+
+ if (p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context, reg_list,
+ PD_REG_I2C)) {
+
+ return FALSE;
+
+ } else {
+
+ *p_Value = (i2c_reg_t)reg_list[0].value;
+
+/* PD_DEBUG("sdvo : R : 0x%02x, 0x%02x", offset, *p_Value); */
+
+ return TRUE;
+ }
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
new file mode 100644
index 0000000..e861af4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
@@ -0,0 +1,482 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_intf.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Definitions for SDVO interface
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_INTF_H_
+#define _SDVO_INTF_H_
+
+/* ......................................................................... */
+/* Opcode, Status Code, Register definitions */
+
+typedef enum {
+ /* General */
+ RESET = 0x1,
+ GET_DEVICE_CAPABILITIES,
+ GET_TRAINED_INPUTS,
+ GET_ACTIVE_OUTPUTS,
+ SET_ACTIVE_OUTPUTS,
+
+ /* Picture Routing */
+ GET_IN_OUT_MAP = 0x6,
+ SET_IN_OUT_MAP,
+
+ GET_ATTACHED_DISPLAYS = 0x0B,
+
+ /* Hot Plug */
+ GET_HOT_PLUG_SUPPORT = 0x0C,
+ SET_ACTIVE_HOT_PLUG,
+ GET_ACTIVE_HOT_PLUG,
+ GET_INTERRUPT_EVENT_SOURCE,
+
+ /* Input/Output Timings */
+ SET_TARGET_INPUT = 0x10,
+ SET_TARGET_OUTUT,
+ GET_INPUT_TIMINGS_PART1,
+ GET_INPUT_TIMINGS_PART2,
+ SET_INPUT_TIMINGS_PART1,
+ SET_INPUT_TIMINGS_PART2,
+ SET_OUTPUT_TIMINGS_PART1,
+ SET_OUTPUT_TIMINGS_PART2,
+ GET_OUTPUT_TIMINGS_PART1,
+ GET_OUTPUT_TIMINGS_PART2,
+ CREATE_PREFERRED_INPUT_TIMINGS,
+ GET_PREFERRED_INPUT_TIMINGS_PART1,
+ GET_PREFERRED_INPUT_TIMINGS_PART2,
+ GET_INPUT_PIXEL_CLOCK_RANGE,
+ GET_OUTPUT_PIXEL_CLOCK_RANGE,
+ GET_SUPPORTED_SDVO_CLOCK_RATE_MULTIPLIERS,
+ GET_SDVO_CLOCK_RATE_MULTIPLIER,
+ SET_SDVO_CLOCK_RATE_MULTIPLIER,
+
+ GET_SUPPORTED_TV_OUTPUT_FORMATS = 0x27,
+ GET_TV_OUTPUT_FORMAT,
+ SET_TV_OUTPUT_FORMAT,
+
+ /* Power Management */
+ GET_SUPPORTED_POWER_STATES = 0x2A,
+ GET_POWER_STATE,
+ SET_POWER_STATE,
+
+ /* Panel Power Sequencing */
+ GET_MAX_PANEL_POWER_SEQUENCING_PARAMETER = 0x2D,
+ GET_PANEL_POWER_SEQUENCING_PARAMETER,
+ SET_PANEL_POWER_SEQUENCING_PARAMETER,
+
+ GET_MAX_BACKLIGHT_LEVEL,
+ GET_BACKLIGHT_LEVEL,
+ SET_BACKLIGHT_LEVEL,
+
+ GET_AMBIENT_LIGHT,
+ SET_AMBIENT_LIGHT,
+
+ SET_UPSCALAR_COEFFICIENTS = 0x36,
+
+ GET_SSC,
+ SET_SSC,
+
+ /* Content Protection */
+ GET_ANCILLARY_VIDEO_INFORMATION,
+ SET_ANCILLARY_VIDEO_INFORMATION,
+
+ /* Picture Enhancements */
+ GET_MAX_FLICKER_FILTER = 0x4D,
+ GET_FLICKER_FILTER,
+ SET_FLICKER_FILTER,
+
+ GET_ADAPTIVE_FLICKER_FILTER,
+ SET_ADAPTIVE_FLICKER_FILTER,
+
+ GET_MAX_2D_FLICKER_FILTER,
+ GET_2D_FLICKER_FILTER,
+ SET_2D_FLICKER_FILTER,
+
+ GET_MAX_SATURATION,
+ GET_SATURATION,
+ SET_SATURATION,
+
+ GET_MAX_HUE,
+ GET_HUE,
+ SET_HUE,
+
+ GET_MAX_BRIGHTNESS,
+ GET_BRIGHTNESS,
+ SET_BRIGHTNESS,
+
+ GET_MAX_CONTRAST,
+ GET_CONTRAST,
+ SET_CONTRAST,
+
+ GET_MAX_HORIZONTAL_OVERSCAN,
+ GET_HORIZONTAL_OVERSCAN,
+ SET_HORIZONTAL_OVERSCAN,
+
+ GET_MAX_VERTICAL_OVERSCAN,
+ GET_VERTICAL_OVERSCAN,
+ SET_VERTICAL_OVERSCAN,
+
+ GET_MAX_HORIZONTAL_POSITION,
+ GET_HORIZONTAL_POSITION,
+ SET_HORIZONTAL_POSITION,
+
+ GET_MAX_VERTICAL_POSITION,
+ GET_VERTICAL_POSITION,
+ SET_VERTICAL_POSITION,
+
+ GET_MAX_SHARPNESS,
+ GET_SHARPNESS,
+ SET_SHARPNESS,
+
+ GET_DOT_CRAWL,
+ SET_DOT_CRAWL,
+
+ GET_DITHER,
+ SET_DITHER,
+
+ GET_MAX_TV_CHROMA_FILTER,
+ GET_TV_CHROMA_FILTER,
+ SET_TV_CHROMA_FILTER,
+
+ GET_MAX_TV_LUMA_FILTER,
+ GET_TV_LUMA_FILTER,
+ SET_TV_LUMA_FILTER,
+
+ /* Control Bus Switch */
+ SET_CONTROL_BUS_SWITCH = 0x7A,
+
+ /* Picture Enhancements */
+ GET_MAX_ADAPTIVE_FLICKER_FILTER = 0x7B,
+
+ /* Power Management */
+ SET_DISPLAY_POWER_STATE = 0x7D,
+
+ /* Panel Power Sequencing */
+ GET_MAX_SSC = 0x7E,
+ GET_LVDS_PANEL_INFORMATION,
+ SET_LVDS_PANEL_INFORMATION,
+ GET_LVDS_PANEL_PROTECTION,
+ SET_LVDS_PANEL_PROTECTION,
+
+ GET_SDTV_RESOLUTION_SUPPORT = 0x83,
+ GET_SUPPORTED_ENHANCEMENTS,
+ GET_SCALED_HDTV_RESOLUTION_SUPPORT,
+
+ /* General */
+ GET_FIRMWARE_VERSION = 0x86,
+ DETECT_LEGACY_VGA = 0x87,
+
+ /* HDMI */
+ PREPARE_TO_GENERATE_HDCPAN = 0x8A,
+ SET_PIXEL_REPLICATION = 0x8B,
+ GET_PIXEL_REPLICATION,
+ GET_COLORIMETRY_CAPABILITIES,
+ SET_CURRENT_COLORIMETRY,
+ GET_CURRENT_COLORIMETRY,
+ GET_AUDIO_ENCRYPTION_PREFERENCE,
+ SET_AUDIO_STATE,
+ GET_AUDIO_STATE,
+ SET_HDMI_BUFFER_INDEX,
+ GET_HDMI_BUFFER_INDEX,
+ GET_HDMI_BUFFER_INFO,
+ SET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+ GET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+ SET_HDMI_BUFFER_DATA,
+ GET_HDMI_BUFFER_DATA,
+ SET_HDMI_BUFFER_TRANSMIT_RATE,
+ GET_HDMI_BUFFER_TRANSMIT_RATE,
+ GET_HDMI_AUDIO_TRANSMISSION_CHARACTERISTICS,
+ GET_SUPPORTED_DIGITAL_ENCODING_MODES, /* 0x9D, */
+ GET_DIGITAL_ENCODING_MODE,
+ SET_DIGITAL_ENCODING_MODE,
+} sdvo_opcode_t;
+
+typedef enum {
+ SS_POWER_ON_STATE, /* 00: */
+ SS_SUCCESS, /* 01: Command successfully completed */
+ SS_NOT_SUPPORTED, /* 02: Invalid Opcode */
+ SS_INVALID_ARGUMENT, /* 03: Opcode is valid but arguments are not */
+ SS_PENDING, /* 04: Opcode is not completed yet */
+ SS_TARGET_UNSPECIFIED, /* 05: SetTargetInput/Output not called */
+ SS_SCALING_UNSUPPORTED, /* 06: Device does not support scaling */
+
+ /* New Errors */
+ SS_UNSUCCESSFUL = 10, /* 10: General Failure */
+ SS_INVALID_RETURN, /* 11: Unexpected return value */
+ SS_WRITE_FAILED, /* 12: Write Operation failed */
+ SS_READ_FAILED, /* 13: Read Operation failed */
+} sdvo_status_t;
+
+#define SDVO_MAX_ARGS 8
+#define SDVO_MAX_RETURNS 8
+
+#define SDVO_REG_ARG_START 0x07
+#define SDVO_REG_ARG_END 0x00
+#define SDVO_REG_OPCODE 0x08
+#define SDVO_REG_STATUS 0x09
+#define SDVO_REG_RETURN_START 0x0A
+#define SDVO_REG_RETURN_END 0x11
+
+#define SDVO_MAX_RETRIES 3
+
+/* ........................................................................ */
+/* Structure definitions for Commands */
+
+typedef unsigned char i2c_reg_t;
+
+/* SDVOOutputFlagStructure Byte 0 */
+typedef struct {
+ i2c_reg_t tmds : 1;
+ i2c_reg_t rgb : 1;
+ i2c_reg_t cvbs : 1;
+ i2c_reg_t svid : 1;
+ i2c_reg_t yprpb : 1;
+ i2c_reg_t scart : 1;
+ i2c_reg_t lvds : 1;
+ i2c_reg_t drgb : 1;
+} sdvo_display_output_t;
+
+/* Display masks */
+#define FP_DISP_MASK (BIT(0)|BIT(6)|BIT(7)|BIT(8)|BIT(14)) /*TMDS/LVDS/DRGB*/
+#define TV_DISP_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) /*CVBS0/SVID0/YPRPB0/SCART0*/
+#define CRT_EXT_DISP_MASK (BIT(1)|BIT(9)) /* External CRT */
+#define LVDS_DISP_MASK (BIT(6)|BIT(14)) /* LVDS */
+#define TMDS_DISP_MASK (BIT(0)|BIT(8))
+#define TV_SVIDEO_DISP_MASK (BIT(3)) /* S-VIDEO */
+#define TV_YPBPR_DISP_MASK (BIT(4)) /* YPBPR/Yipper */
+#define DRGB_DISP_MASK (BIT(7)) /* DRGB0 */
+typedef struct {
+ union {
+ struct {
+ sdvo_display_output_t out0;
+ sdvo_display_output_t out1;
+ };
+ unsigned short flags;
+ };
+} sdvo_output_flags_t;
+
+typedef struct {
+ i2c_reg_t vendor_id; /* 00: Vendor ID */
+ i2c_reg_t device_id; /* 01: Device ID */
+ i2c_reg_t revision_id; /* 02: Revision ID */
+ i2c_reg_t version_minor; /* 03 : sDVO Minor Version (00) */
+ i2c_reg_t version_major; /* 04 : sDVO Major Version (01) */
+ /* 05 : Device capabilities */
+ i2c_reg_t num_inputs :2; /* 10 : Number of sDVO inputs (1 or 2) */
+ i2c_reg_t smooth_scaling:1; /* 2 : Smooth (Graphics) Scaling */
+ i2c_reg_t sharp_scaling :1; /* 3 : Sharp (Text) scaling */
+ i2c_reg_t up_scaling :1; /* 4 : Up Scaling */
+ i2c_reg_t down_scaling :1; /* 5 : Down Scaling */
+ i2c_reg_t stall :1; /* 6 : Stall */
+ i2c_reg_t reserved :1; /* 7 : Reserved */
+ sdvo_output_flags_t output; /* 06&07: Ouput supported by sDVO device */
+} sdvo_device_capabilities_t;
+
+typedef struct {
+ unsigned short pixel_clock; /* Pixel clock / 10,000 */
+ unsigned short active_horz_pixels; /* 12 bits of horizontal active */
+ unsigned short active_vert_pixels; /* 12 bits of vertical active */
+ unsigned char b_interlaced :1; /* 1:Interlaced, 0: Non-Interlaced */
+ unsigned char b_scaled :1; /* 1:Image to be scaled, 0:Otherwise*/
+ unsigned char resv_bits :6; /* Reserved bits */
+ unsigned char resv_byte;
+} sdvo_create_preferred_timings_t;
+
+typedef enum {
+ CRM_1X = BIT(0),
+ CRM_2X = BIT(1),
+ CRM_4X = BIT(3),
+} sdvo_clock_rate_mult_t;
+
+/* Detailed Timing Descriptor */
+typedef struct {
+ unsigned short pixel_clock; /* Pixel Clock / 10,000 */
+ unsigned short horz_active; /* Horizontal Active */
+ unsigned short horz_blanking; /* Horizontal Blanking */
+ unsigned short vert_active; /* Vertical Active */
+ unsigned short vert_blanking; /* Vertical Blanking */
+ unsigned short horz_sync_offset; /* Pixels from blanking start */
+ unsigned short horz_sync_pulse_width;
+ unsigned char vert_sync_offset;
+ unsigned char vert_sync_pulse_width;
+ unsigned char dtd_flags;
+ unsigned char sdvo_flags;
+} sdvo_dtd_t;
+
+typedef enum {
+ SDVO0,
+ SDVO1,
+} sdvo_target_input_t;
+
+typedef struct {
+ i2c_reg_t dev_D0 :1; /* SDVO On */
+ i2c_reg_t dev_D1 :1;
+ i2c_reg_t dev_D2 :1;
+ i2c_reg_t dev_D3 :1; /* SDVO Off */
+ i2c_reg_t disp_D0:1; /* Display On : Vsync/Hsync/Video Active */
+ i2c_reg_t disp_D1:1; /* Display Standby : Vsync Active, Hsync/Video Off */
+ i2c_reg_t disp_D2:1; /* Display Suspend : Hsync Active, Vsync/Video Off */
+ i2c_reg_t disp_D3:1; /* Display Off : All signals Off */
+} sdvo_power_states_t;
+
+typedef struct {
+ struct{
+ i2c_reg_t minor_DVI_rev :4;
+ i2c_reg_t major_DVI_rev :4;
+ };
+ struct{
+ i2c_reg_t minor_HDMI_rev:4;
+ i2c_reg_t major_HDMI_rev:4;
+ };
+
+ i2c_reg_t reserved[6]; /* reserved for future use */
+} sdvo_digital_encode_modes_t;
+
+typedef struct{
+ sdvo_digital_encode_modes_t version;
+}sdvo_hdmi_context_t;
+
+
+typedef struct _sdvo_device_context {
+ sdvo_target_input_t inp_dev;
+ sdvo_output_flags_t out_type;
+ sdvo_device_capabilities_t dev_cap;
+ pd_callback_t *p_callback;
+ pd_attr_t *p_attr_table;
+ unsigned long num_attrs;
+ pd_timing_t *p_mode_table;
+ pd_timing_t *native_dtd;
+ unsigned short fp_width;
+ unsigned short fp_height;
+ unsigned char supp_pwr_states;
+ unsigned char device_pwr_state, display_pwr_state;
+ unsigned char up_scaling;
+ unsigned short t1; /* power state delays */
+ unsigned short t2; /* power state delays */
+ unsigned short t3; /* power state delays */
+ unsigned short t4;
+ unsigned short t5;
+ unsigned short text_tune;
+ sdvo_hdmi_context_t hdmi;
+ unsigned short st_sdvo;
+} sdvo_device_context_t;
+
+typedef struct sdvo_state {
+ unsigned long power_state;
+ pd_timing_t timing;
+} sdvo_state_t;
+
+/* ......................................................................... */
+sdvo_status_t sdvo_execute_command(sdvo_device_context_t *p_ctx,
+ sdvo_opcode_t opcode,
+ i2c_reg_t num_args, i2c_reg_t *p_arg,
+ i2c_reg_t num_returns, i2c_reg_t *p_ret_value);
+
+sdvo_status_t sdvo_reset(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_get_device_capabilities(sdvo_device_context_t *p_ctx,
+ sdvo_device_capabilities_t *p_Dev_Cap);
+sdvo_status_t sdvo_get_trained_inputs(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Out);
+sdvo_status_t sdvo_get_active_outputs(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t *p_Out_Flags);
+sdvo_status_t sdvo_set_active_outputs(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags);
+
+sdvo_status_t sdvo_get_in_out_map(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags[2]);
+sdvo_status_t sdvo_set_in_out_map(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags[2]);
+sdvo_status_t sdvo_set_upscalar_coefficient(sdvo_device_context_t *p_ctx,
+ i2c_reg_t upscalar_coefficient);
+
+sdvo_status_t sdvo_get_attached_displays(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t *p_Out_Flags);
+
+sdvo_status_t sdvo_set_target_input(sdvo_device_context_t *p_ctx,
+ sdvo_target_input_t input);
+sdvo_status_t sdvo_set_target_output(sdvo_device_context_t *p_ctx,
+ sdvo_output_flags_t out_flags);
+
+sdvo_status_t sdvo_get_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_set_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd);
+
+sdvo_status_t sdvo_get_output_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_set_output_timings(sdvo_device_context_t *p_ctx,
+ sdvo_dtd_t *p_dtd);
+
+sdvo_status_t sdvo_get_input_pixel_clock_range(sdvo_device_context_t *p_ctx,
+ unsigned short p_Pixel[2]);
+
+sdvo_status_t sdvo_get_preferred_input_timings(sdvo_device_context_t *p_ctx,
+ sdvo_create_preferred_timings_t *p_Timings,
+ sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_get_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+ sdvo_clock_rate_mult_t *p_mult);
+sdvo_status_t sdvo_set_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+ sdvo_clock_rate_mult_t mult);
+
+sdvo_status_t sdvo_get_supported_power_states(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_pwr_state);
+sdvo_status_t sdvo_get_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Power_State);
+sdvo_status_t sdvo_set_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t pwr_state);
+sdvo_status_t sdvo_set_display_power_state(sdvo_device_context_t *p_ctx,
+ i2c_reg_t display_state);
+#if !defined(CONFIG_MICRO) /* These are not used in vBIOS */
+sdvo_status_t sdvo_set_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+ i2c_reg_t digital_encoding_mode);
+sdvo_status_t sdvo_get_hdmi_audio_transmission_char(
+ sdvo_device_context_t *p_ctx, i2c_reg_t *hdmi_reg);
+sdvo_status_t sdvo_get_supported_encoding_modes(sdvo_device_context_t *p_ctx,
+ sdvo_digital_encode_modes_t *digital_encoding_modes);
+sdvo_status_t sdvo_get_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *digital_encoding_mode);
+/* ------------------------------------------------------------------------- */
+#endif
+sdvo_status_t sdvo_get_min_max_pixel_clock(sdvo_device_context_t *p_ctx,
+ unsigned long *p_min_clock, unsigned long *p_max_clock);
+
+sdvo_status_t sdvo_get_tv_output_format(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_TV_Output_Format_Flag);
+
+sdvo_status_t sdvo_get_sdtv_resolution_support(sdvo_device_context_t *p_ctx,
+ i2c_reg_t *p_Requested_SDTV_Format_Flag, i2c_reg_t *p_Resolution_Support_Flags);
+
+sdvo_status_t sdvo_get_scaled_hdtv_resolution_support(
+ sdvo_device_context_t *p_ctx, i2c_reg_t *p_Requested_HDTV_Format_Flag,
+ i2c_reg_t *p_Resolution_Support_Flags);
+
+sdvo_status_t sdvo_execute_command_read(sdvo_device_context_t *p_ctx,
+ i2c_reg_t num_returns, i2c_reg_t *p_ret_value);
+
+#endif /* _SDVO_INTF_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
new file mode 100644
index 0000000..d8c848e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
@@ -0,0 +1,3899 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_port.c
+ * $Revision: 1.31 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Port driver interface functions
+ *-----------------------------------------------------------------------------
+ */
+
+
+#include <linux/kernel.h>
+
+
+#include "sdvo_port.h"
+
+#define PFIT_CONTROL 0x61230 /* Panel Fitting Control Register Address*/
+#define PFIT_PIPEB_ENABLED 0xA0000000
+#define CH7308_VENDOR_ID 2
+#define CH7308_DEVICE_ID 0x41
+#define CH7308_REVISION_ID 1
+
+/* .......................................................................... */
+
+int sdvo_open(pd_callback_t *p_callback, void **p_context);
+int sdvo_init_device(void *p_context);
+int sdvo_get_timing_list(void *p_context, pd_timing_t *p_in_list,
+ pd_timing_t **pp_out_list);
+int sdvo_set_mode(void *p_context, pd_timing_t *p_mode, unsigned long flags);
+int sdvo_post_set_mode(void *p_context, pd_timing_t *p_mode,
+ unsigned long flags);
+int sdvo_get_attributes(void *p_context, unsigned long *p_num_attr,
+ pd_attr_t **pp_list);
+int sdvo_set_attributes(void *p_context, unsigned long num_attr,
+ pd_attr_t *p_list);
+unsigned long sdvo_validate(unsigned long cookie);
+int sdvo_close(void *p_context);
+int sdvo_set_power(void *p_context, unsigned long state);
+int sdvo_get_power(void *p_context, unsigned long *p_state);
+int sdvo_save(void *p_context, void **pp_state, unsigned long flags);
+int sdvo_restore(void *p_context, void *p_state, unsigned long flags);
+int sdvo_get_port_status(void *p_context, pd_port_status_t *port_status);
+#ifndef CONFIG_MICRO
+int sdvo_set_tv_settings(void *p_context, i2c_reg_t tv_format);
+#endif
+char *sdvo_get_output_type(sdvo_display_output_t out, unsigned char byte);
+int sdvo_init_attribute_table(sdvo_device_context_t *p_ctx);
+void sdvo_convert_pd_timing_to_dtd(pd_timing_t *p_mode, sdvo_dtd_t *p_dtd,
+ unsigned long dclk);
+void sdvo_convert_dtd_to_pd_timing(sdvo_dtd_t *p_dtd, pd_timing_t *p_mode);
+
+#ifndef CONFIG_MICRO
+static sdvo_status_t sdvo_reset_encoder(sdvo_device_context_t *p_ctx);
+#endif
+
+static pd_version_t g_sdvo_version = {3, 4, 0, 0};
+static unsigned long g_sdvo_dab_list[] = {0x70, 0x72, PD_DAB_LIST_END};
+
+static pd_driver_t g_sdvo_drv = {
+ PD_SDK_VERSION,
+ "SDVO Port Driver",
+ 0,
+ &g_sdvo_version,
+ PD_DISPLAY_FP,
+ PD_FLAG_CLOCK_MASTER,
+ g_sdvo_dab_list,
+ 1000,
+ sdvo_validate,
+ sdvo_open,
+ sdvo_init_device,
+ sdvo_close,
+ sdvo_set_mode,
+ sdvo_post_set_mode,
+ sdvo_set_attributes,
+ sdvo_get_attributes,
+ sdvo_get_timing_list,
+ sdvo_set_power,
+ sdvo_get_power,
+ sdvo_save,
+ sdvo_restore,
+ sdvo_get_port_status
+};
+
+pd_timing_t sdvo_sdtv_timing_table[] =
+{
+#ifndef CONFIG_MICRO
+#if 0
+ /* byte 0 */
+ {
+ 320, 200, /* width, height */
+ 60, 19140, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 319, 1286, /* hblank_start, hblank_end (will be set) */
+ 561, 593, /* hsync_start, hsync_end (will be set) */
+ 249, /* vtotal */
+ 199, 249, /* vblank_start, vblank_end (will be set) */
+ 216, 218, /* vsync_start, vsync_end (will be set) */
+ 648, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 320, 240, /* width, height */
+ 60, 22970, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 319, 1286, /* hblank_start, hblank_end (will be set) */
+ 561, 593, /* hsync_start, hsync_end (will be set) */
+ 299, /* vtotal */
+ 239, 299, /* vblank_start, vblank_end (will be set) */
+ 260, 262, /* vsync_start, vsync_end (will be set) */
+ 658, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 400, 300, /* width, height */
+ 60, 28330, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 399, 1286, /* hblank_start, hblank_end (will be set) */
+ 621, 653, /* hsync_start, hsync_end (will be set) */
+ 369, /* vtotal */
+ 299, 369, /* vblank_start, vblank_end (will be set) */
+ 322, 324, /* vsync_start, vsync_end (will be set) */
+ 662, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 640, 350, /* width, height */
+ 60, 32930, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 639, 1286, /* hblank_start, hblank_end (will be set) */
+ 801, 833, /* hsync_start, hsync_end (will be set) */
+ 429, /* vtotal */
+ 349, 429, /* vblank_start, vblank_end (will be set) */
+ 376, 378, /* vsync_start, vsync_end (will be set) */
+ 768, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 640, 400, /* width, height */
+ 60, 37520, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 639, 1286, /* hblank_start, hblank_end (will be set) */
+ 801, 833, /* hsync_start, hsync_end (will be set) */
+ 489, /* vtotal */
+ 399, 489, /* vblank_start, vblank_end (will be set) */
+ 429, 431, /* vsync_start, vsync_end (will be set) */
+ 772, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#else
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+#endif
+ {
+ 640, 480, /* width, height */
+ 60, 45180, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 639, 1286, /* hblank_start, hblank_end (will be set) */
+ 801, 833, /* hsync_start, hsync_end (will be set) */
+ 589, /* vtotal */
+ 479, 589, /* vblank_start, vblank_end (will be set) */
+ 516, 518, /* vsync_start, vsync_end (will be set) */
+ 599, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#ifndef CONFIG_MICRO
+#if 0
+ {
+ 704, 480, /* width, height */
+ 60, 45180, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 703, 1286, /* hblank_start, hblank_end (will be set) */
+ 849, 881, /* hsync_start, hsync_end (will be set) */
+ 589, /* vtotal */
+ 479, 589, /* vblank_start, vblank_end (will be set) */
+ 516, 518, /* vsync_start, vsync_end (will be set) */
+ 776, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 704, 576, /* width, height */
+ 60, 54370, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 703, 1286, /* hblank_start, hblank_end (will be set) */
+ 849, 881, /* hsync_start, hsync_end (will be set) */
+ 709, /* vtotal */
+ 575, 709, /* vblank_start, vblank_end (will be set) */
+ 620, 622, /* vsync_start, vsync_end (will be set) */
+ 786, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 1 */
+ {
+ 720, 350, /* width, height */
+ 60, 32930, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 719, 1286, /* hblank_start, hblank_end (will be set) */
+ 861, 893, /* hsync_start, hsync_end (will be set) */
+ 429, /* vtotal */
+ 349, 429, /* vblank_start, vblank_end (will be set) */
+ 376, 378, /* vsync_start, vsync_end (will be set) */
+ 790, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 720, 400, /* width, height */
+ 60, 37520, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 719, 1286, /* hblank_start, hblank_end (will be set) */
+ 861, 893, /* hsync_start, hsync_end (will be set) */
+ 489, /* vtotal */
+ 399, 489, /* vblank_start, vblank_end (will be set) */
+ 429, 431, /* vsync_start, vsync_end (will be set) */
+ 800, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#else
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+
+ {
+ 720, 480, /* width, height */
+ 60, 45180, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 719, 1286, /* hblank_start, hblank_end (will be set) */
+ 861, 893, /* hsync_start, hsync_end (will be set) */
+ 589, /* vtotal */
+ 479, 589, /* vblank_start, vblank_end (will be set) */
+ 516, 518, /* vsync_start, vsync_end (will be set) */
+ 804, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+#if 0
+ {
+ 720, 540, /* width, height */
+ 60, 51310, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 719, 1286, /* hblank_start, hblank_end (will be set) */
+ 861, 893, /* hsync_start, hsync_end (will be set) */
+ 669, /* vtotal */
+ 539, 669, /* vblank_start, vblank_end (will be set) */
+ 583, 585, /* vsync_start, vsync_end (will be set) */
+ 808, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#else
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+
+ {
+ 720, 576, /* width, height */
+ 60, 36250, /* refresh (will be set), dot clock */
+ 857, /* htotal */
+ 719, 857, /* hblank_start, hblank_end (will be set) */
+ 754, 786, /* hsync_start, hsync_end (will be set) */
+ 709, /* vtotal */
+ 575, 709, /* vblank_start, vblank_end (will be set) */
+ 620, 622, /* vsync_start, vsync_end (will be set) */
+ 818, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+#if 0
+ {
+ 768, 576, /* width, height */
+ 60, 54370, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 767, 1286, /* hblank_start, hblank_end (will be set) */
+ 897, 929, /* hsync_start, hsync_end (will be set) */
+ 709, /* vtotal */
+ 575, 709, /* vblank_start, vblank_end (will be set) */
+ 620, 622, /* vsync_start, vsync_end (will be set) */
+ 822, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#else
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+#endif
+ {
+ 800, 600, /* width, height */
+ 60, 56670, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 799, 1286, /* hblank_start, hblank_end (will be set) */
+ 921, 953, /* hsync_start, hsync_end (will be set) */
+ 739, /* vtotal */
+ 599, 739, /* vblank_start, vblank_end (will be set) */
+ 646, 648, /* vsync_start, vsync_end (will be set) */
+ 601, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#ifndef CONFIG_MICRO
+#if 0
+ {
+ 832, 624, /* width, height */
+ 60, 58970, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 831, 1286, /* hblank_start, hblank_end (will be set) */
+ 945, 977, /* hsync_start, hsync_end (will be set) */
+ 769, /* vtotal */
+ 623, 769, /* vblank_start, vblank_end (will be set) */
+ 672, 674, /* vsync_start, vsync_end (will be set) */
+ 832, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 2 */
+ {
+ 920, 766, /* width, height */
+ 60, 71990, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 919, 1286, /* hblank_start, hblank_end (will be set) */
+ 1011, 1043, /* hsync_start, hsync_end (will be set) */
+ 939, /* vtotal */
+ 765, 939, /* vblank_start, vblank_end (will be set) */
+ 823, 825, /* vsync_start, vsync_end (will be set) */
+ 836, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#else
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+
+ {
+ 1024, 768, /* width, height */
+ 60, 72750, /* refresh (will be set), dot clock */
+ 1286, /* htotal */
+ 1023, 1286, /* hblank_start, hblank_end (will be set) */
+ 1089, 1121, /* hsync_start, hsync_end (will be set) */
+ 949, /* vtotal */
+ 767, 949, /* vblank_start, vblank_end (will be set) */
+ 828, 830, /* vsync_start, vsync_end (will be set) */
+ 609, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1280, 1024, /* width, height */
+ 60, 128660, /* refresh (will be set), dot clock */
+ 1715, /* htotal */
+ 1279, 1715, /* hblank_start, hblank_end (will be set) */
+ 1388, 1420, /* hsync_start, hsync_end (will be set) */
+ 1259, /* vtotal */
+ 1023, 1259, /* vblank_start, vblank_end (will be set) */
+ 1086, 1088, /* vsync_start, vsync_end (will be set) */
+ 611, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+ PD_TIMING_TABLE_END
+};
+pd_timing_t sdvo_hdtv_timing_table[] =
+{
+ /* byte 0 */
+ {
+ 640, 480, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+
+ {
+ 800, 600, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#ifndef CONFIG_MICRO
+ {
+ 1024, 768, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1280, 960, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1400, 1050, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1600, 1200, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1920, 1440, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 2048, 1536, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 1 */
+ {
+ 2560, 1920, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL , /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 2 */
+ {
+ 848, 480, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1064, 600, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1280, 720, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1360, 768, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1704, 960, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1864, 1050, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1920, 1080, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 2128, 1200, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 3 */
+ {
+ 2560, 1400, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 2728, 1536, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 4 */
+ {
+ 768, 480, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 960, 600, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1152, 720, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1124, 768, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1536, 960, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1680, 1050, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1728, 1080, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 1920, 1200, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 5 */
+ {
+ 2304, 1440, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 2456, 1536, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 6 */
+ {
+ 1280, 1024, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+
+ /* byte 7 */
+ {
+ 1280, 768, /* width, height */
+ 60, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ PD_MODE_SUPPORTED| /* this mode is supported */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+ {
+ 0, 0, /* width, height */
+ 0, 0, /* refresh (will be set), dot clock */
+ 0, /* htotal */
+ 0, 0, /* hblank_start, hblank_end (will be set) */
+ 0, 0, /* hsync_start, hsync_end (will be set) */
+ 0, /* vtotal */
+ 0, 0, /* vblank_start, vblank_end (will be set) */
+ 0, 0, /* vsync_start, vsync_end (will be set) */
+ 0, /* mode number */
+ 0, /* mode info flags */
+ 0, 0, /* x, y offset */
+ NULL, /* mode extenstion pointer (will bet set) */
+ 0, 0 /* Reserved */
+ },
+#endif
+ PD_TIMING_TABLE_END
+};
+
+/* .......................................................................... */
+/* .......................................................................... */
+/*============================================================================
+ Function : pd_init is the first function that is invoked by IEG driver.
+
+ Parameters : handle : not used
+
+ Remarks : pd_init initializes pd_driver_t structure and registers the
+ port driver with IEG driver by calling pd_register function
+
+ Returns : Status returned by pd_register function.
+ ------------------------------------------------------------------------- */
+int PD_MODULE_INIT(sdvo_init, (void *handle))
+{
+ int status;
+
+ PD_DEBUG("sdvo: pd_init()");
+
+ status = pd_register(handle, &g_sdvo_drv);
+ if (status != PD_SUCCESS) {
+ PD_DEBUG("sdvo: Error ! pd_init: pd_register() failed with "
+ "status=%#x", status);
+ }
+ return status;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: sdvo_exit()
+ *
+ * Description: This is the exit function for SDVO port driver to unload
+ * the driver.
+ *
+ * Parameters: None.
+ *
+ * Return: PD_SUCCESS(0) success
+ * PD_ERR_XXXXXX otherwise
+ *----------------------------------------------------------------------*/
+int PD_MODULE_EXIT(sdvo_exit, (void))
+{
+ return (PD_SUCCESS);
+} /* end sdvo_exit() */
+
+
+/* ============================================================================
+ Function : sdvo_open is called for each combination of port and dab
+ registers to detect the SDVO device.
+
+ Parameters : p_callback : Contains pointers to read_regs/write_regs
+ functions to access I2C registes.
+
+ pp_context : Pointer to port driver allocated context
+ structure is returned in this argument
+
+ Remarks : sdvo_open detects the presence of SDVO device for specified
+ port.
+
+ Returns : PD_SUCCESS If SDVO device is detected
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_open(pd_callback_t *p_callback, void **pp_context)
+{
+ sdvo_device_context_t *p_ctx;
+ sdvo_status_t status;
+ sdvo_output_flags_t output_flags;
+ unsigned long power_state;
+#ifndef CONFIG_MICRO
+ i2c_reg_t reg;
+#endif
+
+ PD_DEBUG("sdvo: sdvo_open(): port_num=%ld", p_callback->port_num);
+
+ p_ctx = pd_malloc(sizeof(sdvo_device_context_t));
+ if (p_ctx == NULL) {
+ PD_ERROR("sdvo: Error ! sdvo_open: pd_malloc() failed");
+ return PD_ERR_NOMEM;
+ }
+
+ pd_memset(p_ctx, 0, sizeof(sdvo_device_context_t));
+
+ *pp_context = p_ctx;
+ p_ctx->p_callback = p_callback;
+
+#ifndef CONFIG_MICRO
+ /* reset context to avoid wrong timing list */
+ if ((p_ctx->dev_cap.vendor_id != VENDOR_ID_LAPIS)
+ && (p_ctx->dev_cap.device_id != 0x1) && p_callback->reset ){
+ PD_DEBUG("Resetting encoder\n");
+ sdvo_reset_encoder(p_ctx);
+ }
+#endif
+
+ status = sdvo_get_device_capabilities(p_ctx, &p_ctx->dev_cap);
+ if (status != SS_SUCCESS) {
+
+ PD_DEBUG("sdvo: Error ! sdvo_open: sdvo_get_device_capabilities() "
+ "failed with status=%d", status);
+ pd_free(p_ctx);
+ return PD_ERR_NODEV;
+ }
+
+ PD_DEBUG("sdvo: Device Capabilities:");
+ PD_DEBUG("sdvo: vendor=%d, device=%d, revision=%d,",
+ p_ctx->dev_cap.vendor_id, p_ctx->dev_cap.device_id,
+ p_ctx->dev_cap.revision_id);
+ PD_DEBUG("sdvo: version_major=%d, version_minor=%d, num sDVO inputs=%d",
+ p_ctx->dev_cap.version_major, p_ctx->dev_cap.version_minor,
+ p_ctx->dev_cap.num_inputs);
+ PD_DEBUG("sdvo: Scaling support: smooth=%d, sharp=%d, up=%d, down=%d,",
+ p_ctx->dev_cap.smooth_scaling, p_ctx->dev_cap.sharp_scaling,
+ p_ctx->dev_cap.up_scaling,
+ p_ctx->dev_cap.down_scaling);
+ PD_DEBUG("sdvo: Stall support=%d", p_ctx->dev_cap.stall);
+
+ PD_DEBUG("sdvo: out0:%s",
+ sdvo_get_output_type(p_ctx->dev_cap.output.out0, 0));
+ PD_DEBUG("sdvo: out1:%s",
+ sdvo_get_output_type(p_ctx->dev_cap.output.out1, 1));
+
+ /* Detecting STMicro device */
+ if ((p_ctx->dev_cap.vendor_id == 0x82) &&
+ (p_ctx->dev_cap.device_id==0x01)) {
+
+ p_ctx->st_sdvo = 1;
+ }
+
+ /* ...................................................................... */
+ p_ctx->out_type = p_ctx->dev_cap.output;
+
+ /*Workaround:
+ * st_sdvo has two potential modes lvds and rgba
+ * As we dont have the relevant information from xorg (attr/9(
+ * at this point to correctly identify which one the user wants
+ * and as set target will fail if sent 2 output types
+ * This if has been added
+ */
+ if(!p_ctx->st_sdvo)
+ {
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+
+ }
+
+ status = sdvo_get_supported_power_states(p_ctx, &p_ctx->supp_pwr_states);
+ if (status == SS_SUCCESS) {
+ PD_DEBUG("sdvo: Supported Power States = %#x",
+ p_ctx->supp_pwr_states);
+ } else {
+ PD_DEBUG("sdvo: GetSupported Power States FAILED with status = %d",status);
+ }
+
+ /* ...................................................................... */
+ /* Assume SDVO0 connected to Port B and SDVO1 connected to Port C */
+ /* However the correct way to determine SDVO port to device mapping at */
+ /* run-time is via Get_Trained_Inputs opcode */
+ p_ctx->inp_dev = SDVO0;
+
+
+#ifndef CONFIG_MICRO
+ /*We want this in (Windows XP driver) AND
+ (in VBIOS when LVDS is not linked.)*/
+ if ((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS)
+ && (p_ctx->dev_cap.device_id == 0x1)){
+ status = sdvo_set_target_input(p_ctx, p_ctx->inp_dev);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_target_input()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+
+
+ /*Workaround:
+ * st_sdvo has two potential modes lvds and rgba
+ * As we dont have the relevant information from xorg (attr/9(
+ * at this point to correctly identify which one the user wants
+ * and as set target will fail if sent 2 output types
+ * This if has been added
+ */
+ if(!p_ctx->st_sdvo)
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_target_output()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+
+ /* ...................................................................... */
+ status = sdvo_get_supported_power_states(p_ctx, &p_ctx->supp_pwr_states);
+ if (status == SS_SUCCESS) {
+ PD_DEBUG("sdvo: Supported Power States = %#x",
+ p_ctx->supp_pwr_states);
+ }
+ }
+#endif
+
+
+ /* This code is to find out whether a TV encoder is used to get VGA display
+ * or TVout display */
+
+ /* Read the power state */
+ sdvo_get_power(p_ctx, &power_state);
+
+ /* set device to DO before performing connection detect attempt */
+ sdvo_set_power(p_ctx, PD_POWER_MODE_D0);
+
+ status = sdvo_get_attached_displays(p_ctx, &output_flags);
+ /*
+ * sdvo_get_attached_displays returns "0" when sdvo cable is
+ * disconnected. Need to make sure out_type flags not
+ * overridden.
+ */
+ if (status == SS_SUCCESS && output_flags.flags != 0) {
+ p_ctx->out_type.flags &= output_flags.flags;
+ } else {
+ /* If display detection fails, reset the hardware and try again: */
+ PD_ERROR("get_attached_display() did not succeed; trying HW reset");
+ status = sdvo_reset(p_ctx);
+ PD_DEBUG("sdvo_reset returned %u", status);
+ status = sdvo_get_attached_displays(p_ctx, &output_flags);
+ if (status == SS_SUCCESS && output_flags.flags != 0) {
+ p_ctx->out_type.flags &= output_flags.flags;
+ } else {
+ PD_ERROR("get_attached_display() did not succeed again; giving up");
+ return PD_ERR_NODEV;
+ }
+ }
+
+ /* If component video (YPbPr) is connected, for some reason, both ypbpr
+ * and s_video are 1 when sdvo_get_attached_displays is called. We need
+ * to set only ypbpr to 1 because, apparently, the attribute table
+ * would not be created if multiple outputs are on (as in this case).
+ */
+ if (p_ctx->out_type.flags & TV_YPBPR_DISP_MASK) {
+ p_ctx->out_type.flags &= TV_YPBPR_DISP_MASK;
+ }
+
+ /* restore the previous power state */
+ sdvo_set_power(p_ctx, power_state);
+ g_sdvo_drv.flags &= ~(PD_FLAG_CLK_SOURCE|PD_FLAG_PIPE_MASTER);
+
+ /* Set the display type */
+ if (p_ctx->out_type.flags & CRT_EXT_DISP_MASK) {
+ g_sdvo_drv.type = PD_DISPLAY_CRT_EXT;
+ } else if (p_ctx->out_type.flags & DRGB_DISP_MASK) {
+ g_sdvo_drv.type = PD_DISPLAY_DRGB;
+ } else if (p_ctx->out_type.flags & FP_DISP_MASK) {
+ status = SDVO_IS_HDMI_SUPPORTED(p_ctx);
+ if (status == SS_SUCCESS) {
+ PD_DEBUG("sdvo: HDMI transmiter ");
+ g_sdvo_drv.type = PD_DISPLAY_HDMI_EXT;
+ } else{
+ g_sdvo_drv.type = PD_DISPLAY_FP;
+ }
+ } else if (p_ctx->out_type.flags & TV_DISP_MASK) {
+ g_sdvo_drv.type = PD_DISPLAY_TVOUT;
+
+ /* TV display is PIPE master and also generates clock */
+ g_sdvo_drv.flags |= (PD_FLAG_CLK_SOURCE|PD_FLAG_PIPE_MASTER);
+
+ /* CH7021: Initialize H/V Overscan */
+ sdvo_write_i2c_reg(p_ctx, 0x38, 0x1F);
+ sdvo_write_i2c_reg(p_ctx, 0x39, 0x1F);
+
+#ifndef CONFIG_MICRO
+ /*Set optimal TV settings*/
+
+ /*identify tv output systems in terms of line, and frame rate*/
+ sdvo_read_i2c_reg(p_ctx, 0x36, ®);
+
+ if (reg != 0 && reg != 0x24) //not 480i, and 576i system
+ reg = 0xFF;
+
+ status = sdvo_set_tv_settings(p_ctx,reg);
+
+ if (status != SS_SUCCESS) {
+ PD_DEBUG("sdvo: Error ! sdvo_open(): sdvo_set_tv_settings "
+ "failed with status=%d", status);
+ }
+#endif
+
+ }
+
+ /* Indicate main driver about upscaling */
+ if (p_ctx->dev_cap.up_scaling && g_sdvo_drv.type != PD_DISPLAY_CRT_EXT) {
+ g_sdvo_drv.flags |= PD_FLAG_UP_SCALING;
+ } else {
+ /* Remove the upscaling dev caps for VGA bypass. There are functions
+ * that decides on upscaling based on the caps and not the flags. */
+ p_ctx->dev_cap.up_scaling = 0;
+ }
+
+ /* ...................................................................... */
+ /* CH7308 up-scaling workaround */
+ if ((p_ctx->dev_cap.vendor_id == 2) && (p_ctx->dev_cap.device_id == 0x41) &&
+ (p_ctx->dev_cap.revision_id == 1)) {
+ i2c_reg_t reg;
+ sdvo_read_i2c_reg(p_ctx, 0x5D, ®);
+ reg |= 1;
+ sdvo_write_i2c_reg(p_ctx, 0x5D, reg);
+ }
+ /* ...................................................................... */
+
+ /* CH7021A XUD VGAbypass */
+ if (((p_ctx->dev_cap.vendor_id == 2) &&
+ ((p_ctx->dev_cap.device_id==0xC2)||(p_ctx->dev_cap.device_id==0x42)))&&
+ (p_ctx->dev_cap.revision_id == 2) &&
+ (g_sdvo_drv.type == PD_DISPLAY_CRT_EXT)) {
+ i2c_reg_t reg;
+ sdvo_read_i2c_reg(p_ctx, 0x7F, ®);
+ reg |= 1;
+ sdvo_write_i2c_reg(p_ctx, 0x7F, reg);
+
+ sdvo_read_i2c_reg(p_ctx, 0x6C, ®);
+ reg |= 0x03;
+ sdvo_write_i2c_reg(p_ctx, 0x6C, reg);
+
+ sdvo_read_i2c_reg(p_ctx, 0x7F, ®);
+ reg &= 0xFE;
+ sdvo_write_i2c_reg(p_ctx, 0x7F, reg);
+ }
+
+ return PD_SUCCESS;
+}
+
+/* ============================================================================
+ Function : sdvo_init_device is called to initialize a SDVO device
+
+ Parameters : p_context : Pointer to port driver allocated context
+ structure
+
+ Remarks :
+
+ Returns : PD_SUCCESS If initialization is successful
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_init_device(void *p_context)
+{
+ PD_DEBUG("sdvo: sdvo_init_device()");
+#ifndef CONFIG_MICRO
+ if(g_sdvo_drv.type == PD_DISPLAY_HDMI_EXT){
+ /* Initialize transmitter audio capability if available */
+ SDVO_INIT_HDMI(p_context);
+ }
+#endif
+ return PD_SUCCESS;
+}
+
+/* ============================================================================
+ Function : sdvo_get_timing_list is called to get the list of display
+ modes supported by the SDVO device and the display.
+
+ Parameters : p_context: Pointer to port driver allocated context
+ structure
+ p_in_list: List of display modes supported by the IEG driver
+ pp_out_list: List of modes supported by the SDVO device
+
+ Remarks :
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_get_timing_list(void *p_context, pd_timing_t *p_in_list,
+ pd_timing_t **pp_out_list)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ unsigned short pixel_range[2];
+ pd_dvo_info_t sdvo_info = {0, 0, 0, 0, 0, 0, 0, 0};
+ pd_display_info_t sdvo_display_info = {0, 0, 0, 0, NULL};
+ int ret = PD_SUCCESS;
+ pd_timing_t *tv_timing;
+ unsigned char hdtv = 0; /* 0: standard ; 1: high definition */
+
+ PD_DEBUG("sdvo: sdvo_get_timing_list()");
+
+ /* ...................................................................... */
+ status = sdvo_set_target_input(p_ctx, p_ctx->inp_dev);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_get_timing_list: sdvo_set_target_input()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ status = sdvo_get_input_pixel_clock_range(p_ctx, pixel_range);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_get_timing_list: "
+ "sdvo_get_input_pixel_clock_range() failed with status=%d",
+ status);
+ sdvo_info.min_dclk = 0;
+ sdvo_info.max_dclk = 0;
+ } else {
+ sdvo_info.min_dclk = (unsigned long)pixel_range[0] * 10;
+ if (p_ctx->st_sdvo) {
+ sdvo_info.min_dclk = 25000;
+ }
+ sdvo_info.max_dclk = (unsigned long)pixel_range[1] * 10;
+ }
+
+ sdvo_info.upscale = p_ctx->dev_cap.up_scaling;
+ sdvo_info.downscale = p_ctx->dev_cap.down_scaling;
+ sdvo_display_info.panel_fit = p_ctx->up_scaling;
+
+ if (!(p_ctx->out_type.flags & TV_DISP_MASK)) {
+ /* For VGA, DVI, LVDS and HDMI displays,
+ * call helper function to filter the modes */
+ ret = pd_filter_timings(p_ctx->p_callback->callback_context,
+ p_in_list, &p_ctx->p_mode_table, &sdvo_info, &sdvo_display_info);
+
+ /* Helper function returns the below values */
+ p_ctx->native_dtd = sdvo_display_info.native_dtd;
+ p_ctx->fp_width = sdvo_display_info.width;
+ p_ctx->fp_height = sdvo_display_info.height;
+ *pp_out_list = p_ctx->p_mode_table;
+ } else {
+ sdvo_create_preferred_timings_t pref_timings;
+ sdvo_dtd_t dtd_in;
+ unsigned char params[6] = {0,0,0,0,0,0};
+ unsigned char ret_value[8] = {0,0,0,0,0,0,0,0};
+ unsigned long *temp = (unsigned long *)¶ms[2];
+ unsigned char i=0, j=0;
+
+ status = sdvo_get_tv_output_format(p_ctx,params);
+ if (params[0] > 0 || params[1] > 0 || (params[2] > 0 &&
+ params[2] < 0x08)) {
+ /* SDTV support */
+ status = sdvo_get_sdtv_resolution_support(p_ctx,params,ret_value);
+ tv_timing = sdvo_sdtv_timing_table;
+
+ } else {
+ /* HDTV support */
+ (*temp) >>= 3;
+ status = sdvo_get_scaled_hdtv_resolution_support(
+ p_ctx, ¶ms[2], ret_value);
+ tv_timing = sdvo_hdtv_timing_table;
+ hdtv = 1;
+ }
+
+
+ /* For TV displays generate supported timing table */
+
+ while (tv_timing->width != PD_TIMING_LIST_END) {
+ /* Fill-in pref timings */
+ /* Go through bits 0 to 7 of the returned byte and check to see if
+ * it is on. If yes, calculate the preferred timing */
+
+ for (j=0; j<8; j++) {
+ tv_timing->mode_info_flags &= ~PD_MODE_SUPPORTED;
+ /* Cannot request preferred input timing for width/height = 0 */
+ if (!tv_timing->width || !tv_timing->height) {
+ tv_timing++;
+ continue;
+ }
+ if (ret_value[i] & BIT(j)) {
+ pd_memset(&pref_timings, 0, sizeof(pref_timings));
+ /* pref_timings.pixel_clock=(unsigned short)(t1->dclk/10);*/
+ pref_timings.active_horz_pixels = tv_timing->width;
+ pref_timings.active_vert_pixels = tv_timing->height;
+ status = sdvo_get_preferred_input_timings(p_ctx,
+ &pref_timings, &dtd_in);
+
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo_get_timing_list: %ux%u cannot be "
+ "supported status = %u",
+ tv_timing->width, tv_timing->height, status);
+ } else {
+ PD_DEBUG("sdvo_get_timing_list: "
+ "device returned values = %ux%u dclk=%u",
+ dtd_in.horz_active, dtd_in.vert_active,
+ dtd_in.pixel_clock);
+ }
+ if (dtd_in.horz_active && dtd_in.vert_active) {
+ sdvo_convert_dtd_to_pd_timing(&dtd_in, tv_timing);
+ }
+ PD_DEBUG("sdvo_get_timing_list: after conversion: "
+ "device returned values = %ux%u dclk=%lu",
+ tv_timing->width, tv_timing->height,
+ tv_timing->dclk);
+ tv_timing->refresh = 60; /* This is for OS to see */
+ tv_timing->mode_info_flags |= PD_MODE_SUPPORTED;
+ } /* end checking ret_value[i] */
+ tv_timing++;
+ } /* end for loop */
+ i++; /* grab next returned byte */
+ } /* end while timing list */
+
+ if (hdtv) {
+ *pp_out_list = sdvo_hdtv_timing_table;
+ }
+ else {
+ *pp_out_list = sdvo_sdtv_timing_table;
+ }
+ }
+ /* end tv if */
+ return ret;
+}
+
+/* ============================================================================
+ Function : sdvo_set_mode is called to test if specified mode can be
+ supported or to set it.
+
+ Parameters : p_context: Pointer to port driver allocated context
+ p_mode : New mode
+ flags : In test mode it is set to PD_SET_MODE_FLAG_TEST
+
+ Remarks : sdvo_set_mode first verifies that the new mode is
+ supportable.
+ If not it returns an error status
+ If the flags is not set to PD_SET_MODE_FLAG_TEST it sets the
+ new mode.
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_set_mode(void *p_context, pd_timing_t *p_mode, unsigned long flags)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ sdvo_dtd_t dtd_out, dtd_in;
+ sdvo_clock_rate_mult_t clock_mult;
+ unsigned char b_use_scaled_timing;
+ pd_timing_t *p_native_mode;
+ unsigned long dclk;
+
+ PD_DEBUG("sdvo: sdvo_set_mode() mode=%dx%d@%d",
+ p_mode->width, p_mode->height, p_mode->refresh);
+
+ p_native_mode = p_ctx->native_dtd;
+
+ if (p_ctx->out_type.flags & TV_DISP_MASK) {
+ p_native_mode = p_mode;
+ }
+
+ /* ...................................................................... */
+ status = sdvo_set_target_input(p_ctx, p_ctx->inp_dev);
+ if (status != SS_SUCCESS) {
+
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_target_input()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ /*Workaround:
+ * st_sdvo has two potential modes lvds and rgba
+ * As we dont have the relevant information from xorg (attr/9(
+ * at this point to correctly identify which one the user wants
+ * and as set target will fail if sent 2 output types
+ * This if has been added
+ */
+ if(!p_ctx->st_sdvo)
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_target_output()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ /* ...................................................................... */
+ /* Test mode. Specified mode is supported by this device return success */
+ if (flags & PD_SET_MODE_FLAG_TEST) {
+ return PD_SUCCESS;
+ }
+
+ /* ...................................................................... */
+ /* Set power state to D0 */
+ sdvo_set_power(p_context, PD_POWER_MODE_D0);
+ /* ...................................................................... */
+ /* Initialize the DTD structure and set output and input timings */
+ b_use_scaled_timing = FALSE;
+ /* p_ctx->unscaled_Mode.width = 0; */
+
+ dclk = p_mode->dclk;
+
+ /* If this sDVO device supports scaling and if native mode was specified */
+ /* get the preferred input timings for native output timings */
+ if (((p_native_mode) &&
+ ((p_native_mode->width != p_mode->width) ||
+ (p_native_mode->height != p_mode->height)) &&
+
+ ((p_ctx->up_scaling) || (p_ctx->dev_cap.down_scaling))) ||
+
+ (p_ctx->out_type.flags & TV_DISP_MASK)) {
+
+ sdvo_create_preferred_timings_t pref_timings;
+
+ sdvo_convert_pd_timing_to_dtd(p_native_mode, &dtd_out,
+ p_native_mode->dclk);
+
+ status = sdvo_set_output_timings(p_ctx, &dtd_out);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_output_timings() "
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ pd_memset(&pref_timings, 0, sizeof(pref_timings));
+ pref_timings.pixel_clock = (unsigned short)(p_native_mode->dclk / 10);
+ pref_timings.active_horz_pixels = p_mode->width;
+ pref_timings.active_vert_pixels = p_mode->height;
+
+ if (!(p_ctx->out_type.flags & TV_DISP_MASK)) {
+ pref_timings.b_scaled = 1;
+ if (p_native_mode->mode_info_flags & PD_SCAN_INTERLACE) {
+ pref_timings.b_interlaced = 1;
+ }
+ }
+
+ status = sdvo_get_preferred_input_timings(p_ctx, &pref_timings,&dtd_in);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: "
+ "sdvo_get_preferred_input_timings() failed with status=%d",
+ status);
+ } else {
+ PD_DEBUG("sdvo: sdvo_set_mode: pref_in_timings = %ux%u dclk=%u",
+ dtd_in.horz_active, dtd_in.vert_active, dtd_in.pixel_clock);
+ b_use_scaled_timing = TRUE;
+ dclk = p_native_mode->dclk;
+ }
+ }
+
+ /* ...................................................................... */
+ /* Determine clock rate multiplier */
+ if (dclk > 100000) { /* 100-200 MHz */
+ clock_mult = CRM_1X;
+ } else if (dclk > 50000) { /* 50-100 Mhz */
+ clock_mult = CRM_2X;
+ } else { /* 25-50 Mhz */
+ clock_mult = CRM_4X;
+ }
+
+ PD_DEBUG("sdvo: Clock Multiplier = %d dclk = %lu", clock_mult, dclk);
+
+ /* ...................................................................... */
+ /* SI 1364 Autozone switch workaround */
+ if ((p_ctx->dev_cap.vendor_id == 4) && (p_ctx->dev_cap.device_id == 0xAA)) {
+ i2c_reg_t data;
+ if (clock_mult == CRM_1X) {
+ data = 0x4D;
+ } else {
+ data = 0x49;
+ }
+ sdvo_write_i2c_reg(p_ctx, 0x51, data);
+ }
+
+ /* ...................................................................... */
+ if (! b_use_scaled_timing) {
+ sdvo_convert_pd_timing_to_dtd(p_mode, &dtd_out, p_mode->dclk);
+ status = sdvo_set_output_timings(p_ctx, &dtd_out);
+ if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_output_timings() "
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+ dtd_in = dtd_out;
+ }
+
+#ifndef CONFIG_MICRO
+ /*We want this in (Windows XP driver) AND
+ (in VBIOS when LVDS is not linked.)*/
+ /* This workaround needed for LAPIS solution only.
+ It would probably give problem if the SDVO is connected to
+ analog display, but that is not the usage model for LAPIS.
+ */
+ if ((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS)
+ && (p_ctx->dev_cap.device_id == 0x1)){
+ /* The LAPIS SDVO receiver to return âInvalid Argumentâ when:
+ (1) Horizontal Active < 600
+ (2) Horizontal Blanking < 16
+ (3) HSync pulse width < 2
+ (4) (HSync Offset + HSync pulse width) > Horizontal Blanking
+ (5) Vertical Active < 480
+ (6) Vertical Blanking < 3
+ (7) VSync pulse width < 1
+ (8) (VSync Offset + VSync pulse width) > Vertical Blanking
+ (9) Interlace mode or unacceptable sync ( Part2/4 must be "00011xxx" )
+ (10) SDVO STALL mode
+ (11) SDVO Scaling mode
+
+ We have seen that (4) and (8) are problematic. The work around is
+ to moved Horizontal VBlank and Vertical VBlank so it is always
+ at least 1 pixel bigger than offset + pulse width.
+
+ There is no problem with Chrontel 7307 even with
+ horz_vblank < (HSync Offset + HSync pulse width)
+ and I assume it is the same with other SDVO card.
+ */
+ if ((dtd_in.horz_sync_offset + dtd_in.horz_sync_pulse_width) >
+ dtd_in.horz_blanking){
+ dtd_in.horz_blanking = dtd_in.horz_sync_offset +
+ dtd_in.horz_sync_pulse_width + 1;
+ }
+
+ if ((dtd_in.vert_sync_offset + dtd_in.vert_sync_pulse_width) >
+ dtd_in.vert_blanking){
+ dtd_in.vert_blanking = dtd_in.vert_sync_offset +
+ dtd_in.vert_sync_pulse_width + 1;
+ }
+
+ }
+#endif
+ /*
+ * Disable panel fitting for CH7308 card on Pipe B if enabled, because it
+ * handles its own upscaling
+ */
+ if ((p_ctx->dev_cap.vendor_id == CH7308_VENDOR_ID) &&
+ (p_ctx->dev_cap.device_id == CH7308_DEVICE_ID) &&
+ (p_ctx->dev_cap.revision_id == CH7308_REVISION_ID)) {
+ pd_reg_t reg_list[2];
+
+ reg_list[0].reg = PFIT_CONTROL;
+ reg_list[1].reg = PD_REG_LIST_END;
+
+ /*Read the current value of the panel fitting control register*/
+ p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context,
+ reg_list, PD_REG_MIO);
+
+ PD_DEBUG("PFIT_CONTROL 0x%lx = 0x%lx", PFIT_CONTROL,reg_list[0].value);
+
+ if((reg_list[0].value & PFIT_PIPEB_ENABLED) == PFIT_PIPEB_ENABLED ){
+ /* Disable panel fitting */
+ reg_list[0].value = 0x0;
+ p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context,
+ reg_list, PD_REG_MIO);
+ PD_DEBUG(" Value 0x%lx written to PFIT_CONTROL 0x%lx",
+ reg_list[0].value,PFIT_CONTROL);
+ }
+ }
+
+ status = sdvo_set_input_timings(p_ctx, &dtd_in);
+ if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+ PD_ERROR("sdvo: Error ! sdvo_set_mode: sdvo_set_input_timings() "
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ status = sdvo_set_clock_rate_multiplier(p_ctx, clock_mult);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error!sdvo_set_mode: sdvo_set_clock_rate_multiplier() "
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ return PD_SUCCESS;
+}
+
+/* ============================================================================
+ Function : sdvo_post_set_mode
+
+ Parameters : p_context: Pointer to port driver allocated context
+ p_mode :
+ flags :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+int sdvo_post_set_mode(void *p_context, pd_timing_t *p_mode,
+ unsigned long flags)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ i2c_reg_t trained = 0;
+ sdvo_output_flags_t out_flags[2];
+ int pd_status = PD_SUCCESS;
+ sdvo_output_flags_t output_flags;
+ /*sdvo_output_flags_t is_attached display;*/
+
+ PD_DEBUG("sdvo: sdvo_post_set_mode()");
+
+#ifndef CONFIG_MICRO
+ /* This is a workaround specific to LAPIS */
+ if((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS)
+ && (p_ctx->dev_cap.device_id == 0x1)){
+
+ pd_timing_t local_p_mode;
+ /* pd_reg_t reg_list[2]; */
+ /* unsigned long temp, portreg; */
+ local_p_mode = *p_mode;
+
+ sdvo_reset_encoder(p_context);
+ /* sdvo_reset(p_context);*/ /* THIS is workaround for LAPIS SDVO flashing issue.*/
+ sdvo_set_power(p_context, 0);
+ if (p_ctx->display_pwr_state == 0x0)
+ {
+
+ pd_attr_t *p_attr_temp =
+ pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_RB_SWAP_MODE, 0 );
+
+ /* RB SWAP */
+ sdvo_alter_static_attr(p_ctx, p_attr_temp, p_attr_temp->current_value);
+
+ sdvo_set_mode(p_context, &local_p_mode,0);
+ } else {
+ sdvo_set_power(p_context, p_ctx->display_pwr_state);
+ }
+
+ }
+#endif
+
+ status = sdvo_get_trained_inputs(p_ctx, &trained);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_get_trained_inputs() failed with "
+ "status=%d", status);
+ } else {
+ if (trained == 0) {
+ PD_DEBUG("sdvo: Error ! sdvo_post_set_mode: "
+ "No inputs are trained");
+ } else {
+ PD_DEBUG("sdvo: Success ! sdvo_post_set_mode: "
+ "Inputs are trained");
+ }
+ }
+
+ status = sdvo_get_attached_displays(p_ctx, &output_flags);
+ if (status == SS_SUCCESS) {
+ PD_DEBUG("sdvo: get_attached_display returned => [0x%x]",
+ output_flags.flags);
+ } else {
+ /* TODO: What if display detection fails? */
+ /* pd_status = PD_ERR_NODEV; */
+ output_flags.flags = 0;
+ }
+
+ /* To enable YPbPr, the attribute 9 must be set to 16 in xorg.conf;
+ * if it set, then p_ctx->out_type.flags would be changed to 16 in,
+ * sdvo_set_attributes. Here, we are just making sure that if YPbPr
+ * is enabled, then output_flags must be changed to 16. This needs to
+ * be done because, when component video (ypbpr) is connected, both ypbpr
+ * and s_video are 1 when read from the registers (sdvo_get_attached_displays).
+ */
+ if (p_ctx->out_type.flags & TV_YPBPR_DISP_MASK) {
+ output_flags.flags &= TV_YPBPR_DISP_MASK;
+ }
+
+ if (output_flags.flags == 0) {
+ output_flags.flags = p_ctx->out_type.flags;
+ }else if(output_flags.flags != p_ctx->out_type.flags){
+ /* enable switching tv output type on-the-fly;
+ * also to enable cvbs+svideo simul display */
+ /* NOTE: Removed on-the-fly support with PRD change.
+ p_ctx->out_type.flags will always retain the registry
+ settings. Setting multiple bits out_type.flags for
+ sdvo_set_target_output will caused INVALID_ARGUMENT error
+ which in turn causes un-trained output. */
+ /*p_ctx->out_type.flags = output_flags.flags; */
+ }
+
+ /* set inout map */
+ PD_DEBUG("sdvo_post_set_mode: out_type.flags:[0x%x]",
+ output_flags.flags);
+
+ /* For ST SDVO device, when the jumper is set to LVDS or
+ * DRGB, output flags get set to 0xC0. We need to then
+ * set the output flags to only DRGB.
+ */
+ if (p_ctx->st_sdvo) {
+ PD_DEBUG("sdvo_post_set_mode: out_type.flags [0x%x]->[0x%x]",
+ output_flags.flags, p_ctx->out_type.flags);
+ output_flags.flags = p_ctx->out_type.flags;
+ }
+
+ PD_DEBUG("sdvo_post_set_mode: out0:%s, out 1:%s",
+ sdvo_get_output_type(p_ctx->out_type.out0, 0),
+ sdvo_get_output_type(p_ctx->out_type.out1, 1));
+
+ /* set inout map */
+ if(output_flags.flags & TV_DISP_MASK){
+ /* Ensure only one output (SVIDEO) is used since in out map
+ * command can only handle one active port. SDVO specs also
+ * states that any tv setting would be applied to all connectors */
+ out_flags[0].flags = TV_SVIDEO_DISP_MASK;
+ }else{
+ out_flags[0].flags = output_flags.flags;
+ /* in0 = required output type */
+ }
+ out_flags[1].flags = 0; /* in1 = 0 */
+ status = sdvo_set_in_out_map(p_ctx, out_flags);
+ /* Some encoders doesn't support INOUT Map */
+ if (status != SS_SUCCESS && status != SS_NOT_SUPPORTED) {
+ PD_ERROR("sdvo: Error ! sdvo_post_set_mode: sdvo_set_in_out_map() "
+ "failed with status=%d", status);
+ pd_status = PD_ERR_INTERNAL;
+ }
+
+ /* set active outputs */
+ status = sdvo_set_active_outputs(p_ctx, output_flags);
+ if (status != SS_SUCCESS) {
+
+ PD_ERROR("sdvo: Error ! sdvo_post_set_mode: sdvo_set_active_outputs() "
+ "failed with status=%d", status);
+ pd_status = PD_ERR_INTERNAL;
+ }
+#ifndef CONFIG_MICRO
+ status = SDVO_IS_HDMI_SUPPORTED(p_context);
+ if(status == SS_SUCCESS){
+ SDVO_CONFIGURE_HDMI(p_ctx);
+ }
+#endif
+ /* Wait for panel power up sequence to complete */
+ pd_usleep((unsigned long)(p_ctx->t1+p_ctx->t2)*1000 + 10);
+
+ return pd_status;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_attributes is called to get the list of all the
+ available attributes
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ p_Num : Return the total number of attributes
+ pp_list : Return the list of port driver attributes
+
+ Remarks : sdvo_get_attributes calls SDVO interface functions to get all
+ available range,bool and list attributes supported by the
+ SDVO device
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_get_attributes(void *p_context, unsigned long *p_num_attr,
+ pd_attr_t **pp_list)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ unsigned long i;
+
+ PD_DEBUG("sdvo: sdvo_get_attributes()");
+
+ /* No attributes for external CRT */
+ if (p_ctx->out_type.flags & CRT_EXT_DISP_MASK) {
+ PD_DEBUG("No attributes available for SDVO CRT.");
+ *p_num_attr = 0;
+ return 0;
+ }
+#ifndef CONFIG_MICRO
+ /* This is a workaround specific to LAPIS */
+ if(p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS
+ && p_ctx->dev_cap.device_id == 0x1){
+ /* TODO: sdvo_set_target_output return pending when the power state is D3 on
+ * ML7213 A0. other sdvo cards don't have this problem and LAPIS don't see
+ * this problem on their site. verify this on A1 and remove the code if
+ * it return success */
+ sdvo_set_power(p_ctx, PD_POWER_MODE_D0);
+ }
+#endif
+
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_get_attributes: sdvo_set_target_output()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ if (p_ctx->p_attr_table == NULL) {
+ PD_DEBUG("sdvo: sdvo_get_attributes: "
+ "Attribute Table not initialized");
+ return PD_ERR_INTERNAL;
+ }
+ /* ...................................................................... */
+ for (i = 0; i < p_ctx->num_attrs ; i++) {
+ pd_attr_t *p_attr_cur = &p_ctx->p_attr_table[i];
+
+ if ((p_attr_cur->flags & PD_ATTR_FLAG_DYNAMIC) == 0) {
+ status = sdvo_query_static_attr(p_ctx, p_attr_cur);
+ } else {
+ if ((p_attr_cur->id >= PD_ATTR_ID_FP_PWR_T1) &&
+ (p_attr_cur->id <= PD_ATTR_ID_FP_PWR_T5)) {
+ status = sdvo_query_panel_pwr_seq_attr(p_ctx,
+ (pd_range_attr_t *)p_attr_cur);
+ } else if (p_attr_cur->type == PD_ATTR_TYPE_RANGE) {
+ status = sdvo_query_range_attr(p_ctx,
+ (pd_range_attr_t *)p_attr_cur);
+ } else if (p_attr_cur->type == PD_ATTR_TYPE_BOOL) {
+ status = sdvo_query_bool_attr(p_ctx,
+ (pd_bool_attr_t *)p_attr_cur);
+ } else if (p_attr_cur->type == PD_ATTR_TYPE_LIST) {
+ status = sdvo_query_list_attr(p_ctx,
+ (pd_list_attr_t *)p_attr_cur);
+ i += ((pd_list_attr_t *)p_attr_cur)->num_entries;
+ }
+
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_get_attributes: "
+ "Failed to query attr[%ld]='%s', id=%ld",
+ i, SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id);
+ }
+ }
+ }
+
+ /* ...................................................................... */
+ *pp_list = p_ctx->p_attr_table;
+ *p_num_attr = p_ctx->num_attrs ;
+ return PD_SUCCESS;
+}
+
+#ifndef CONFIG_MICRO
+int sdvo_set_tv_settings(void *p_context, i2c_reg_t tv_format)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+
+ unsigned char chron_tv_code;
+
+ PD_DEBUG("sdvo: sdvo_set_tv_settings: tv_format [0x%x]\n",tv_format);
+
+
+ if ((tv_format == 0xFF) || (p_ctx->out_type.flags & BIT(2)) ){
+ chron_tv_code = tv_format; /*HDTV or SDTV and composite type*/
+ } else {
+ chron_tv_code = tv_format | 0x01; /*include s-video and everything else*/
+ }
+
+ PD_DEBUG("sdvo: sdvo_set_tv_settings: chron_tv_code [0x%x]\n",chron_tv_code);
+
+ return sdvo_set_tv_optimal_settings(p_ctx,chron_tv_code);
+
+}
+#endif
+
+/* ============================================================================
+ Function : sdvo_set_attributes is called to modify one or more display
+ attributes
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ num : Number of attributes
+ p_list : List of attributes
+
+ Remarks : sdvo_set_attributes scans the attribute list to find the ones
+ that are to be modified by checking flags field in each
+ attribute for PD_ATTR_FLAG_VALUE_CHANGED bit. If this bit is
+ set it will call SDVO interface functions to set the new
+ value for the attribute.
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_set_attributes(void *p_context, unsigned long num_attrs,
+ pd_attr_t *p_list)
+{
+
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ sdvo_output_flags_t out_flags;
+ unsigned long i;
+ static unsigned char set_tvformat = 1;
+ unsigned short tvformat = 1; /* Index 1 is for NTSC */
+ int found_display_setting = 0;
+
+ PD_DEBUG("sdvo: sdvo_set_attributes(): num_attrs=%ld", num_attrs);
+ /* Search for PD_ATTR_ID_DISPLAY in the incoming attribute table, if it */
+ /* present and if sDVO supports > 1 displays use it to set TargetOutput */
+ for (i = 0; i < num_attrs; i++) {
+ if ((p_list[i].flags & PD_ATTR_FLAG_VALUE_CHANGED) == 0) {
+ continue;
+ }
+
+ /* overwrite the connected display with requested display */
+ if (p_list[i].id == PD_ATTR_ID_DISPLAY) {
+ p_ctx->out_type.flags = (unsigned short)p_list[i].current_value;
+
+ PD_DEBUG("sdvo: Success ! sdvo_set_attributes: "
+ "attr='%s', id=%ld, current_value=%ld",
+ SDVO_GET_ATTR_NAME((&p_list[i])), p_list[i].id,
+ p_list[i].current_value);
+ /* Clear attribute changed flag */
+ p_list[i].flags &= ~PD_ATTR_FLAG_VALUE_CHANGED;
+ found_display_setting = 1;
+ break;
+ }
+ }
+
+
+ /*in the situation where we have 2 potential outputs (e.g. lvds and drgb_
+ * and a preference has not been set in the xorg
+ * then we try and set an appropriate default, while outputting an error
+ * message
+ */
+ if(!found_display_setting && p_ctx->st_sdvo){
+ int defaultFound = 0;
+ printk("\n[EMGD] SDVO: ERROR !\n"
+ "\n\tALL/1/Port/2/Attr/9 is NOT set!"
+ "\n\tYou may want to set the value to either"
+ "\n\t\t0x40: for lvds "
+ "\n\tor"
+ "\n\t\t0x00: for VGA"
+ "\n\tCurrent Value: %x ",
+ p_ctx->out_type.flags);
+
+ /*attempt default setting*/
+ out_flags.flags = p_ctx->out_type.flags;
+ if(out_flags.out0.lvds){
+ /*clear*/
+ out_flags.flags = 0x0;
+ /*set just lvds*/
+ out_flags.out0.lvds = 1;
+ defaultFound = 1;
+
+ }
+ else if(out_flags.out0.drgb){
+ /*clear*/
+ out_flags.flags = 0x0;
+ /*set just lvds*/
+ out_flags.out0.drgb = 1;
+ defaultFound = 1;
+ }
+ /*Should out1 be allowed a seperate set up? */
+ else if(out_flags.out1.drgb){
+ /*clear*/
+ out_flags.flags = 0x0;
+ /*set just lvds*/
+ out_flags.out1.drgb = 1;
+ defaultFound = 1;
+
+ }
+ else if(out_flags.out1.drgb){
+ /*clear*/
+ out_flags.flags = 0x0;
+ /*set just lvds*/
+ out_flags.out1.drgb = 1;
+ defaultFound = 1;
+
+ }
+
+ if(defaultFound)
+ {
+ printk("\n[EMGD] SDVO: Defaulting To: %x\n", out_flags.flags);
+ p_ctx->out_type.flags = out_flags.flags;
+ }
+ else
+ {
+ printk("\n[EMGD] SDVO: Error ! no appropriate default for p_ctx->out_type.flags!\n");
+ }
+
+ }
+
+ /* ...................................................................... */
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_attributes: sdvo_set_target_output()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+
+ /* Here will try to get the supported power states again. For multiple
+ * displays functionality card, the supported power state will only can get
+ * succesfully after the output display type been seted.
+ */
+ status = sdvo_get_supported_power_states(p_ctx, &p_ctx->supp_pwr_states);
+
+ /* ...................................................................... */
+ /* Create attribute table if not already created */
+ if (p_ctx->p_attr_table == NULL) {
+ sdvo_init_attribute_table(p_ctx);
+ }
+
+ for (i = 0; i < num_attrs; i++) {
+ pd_attr_t *p_attr;
+ unsigned long new_value;
+
+ if ((p_list[i].flags & PD_ATTR_FLAG_VALUE_CHANGED) == 0) {
+ continue;
+ }
+
+ /* Special handling for TVFormat in vbios */
+ if (p_list[i].id == PD_ATTR_ID_TVFORMAT) {
+ set_tvformat = 1;
+ tvformat = (unsigned short) p_list[i].current_value;
+ }
+
+ /* Clear attribute changed flag */
+ p_list[i].flags &= ~PD_ATTR_FLAG_VALUE_CHANGED;
+
+ new_value = p_list[i].current_value;
+
+ p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ p_list[i].id, 0);
+ if (p_attr == NULL) {
+ PD_DEBUG("sdvo: Error ! pd_get_attr() failed for attr "
+ "id=%ld", p_list[i].id);
+ continue;
+ }
+
+ /* .................................................................. */
+ if(!(p_attr->flags & PD_ATTR_FLAG_DYNAMIC)) {
+ status = sdvo_alter_static_attr(p_ctx, p_attr, new_value);
+ } else {
+ if ((p_attr->id >= PD_ATTR_ID_FP_PWR_T1) &&
+ (p_attr->id <= PD_ATTR_ID_FP_PWR_T5)) {
+ status = sdvo_alter_panel_pwr_seq_attr(p_ctx,
+ (pd_range_attr_t *)p_attr, new_value);
+ } else if (p_attr->type == PD_ATTR_TYPE_RANGE) {
+ status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+ new_value);
+ if (p_attr->id == PD_ATTR_ID_VERT_OVERSCAN) {
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ }
+ } else if (p_attr->type == PD_ATTR_TYPE_BOOL) {
+ status = sdvo_alter_bool_attr(p_ctx, (pd_bool_attr_t *)p_attr,
+ new_value);
+ } else if (p_attr->type == PD_ATTR_TYPE_LIST) {
+ status = sdvo_alter_list_attr(p_ctx, (pd_list_attr_t *)p_attr,
+ new_value);
+ if (p_attr->id == PD_ATTR_ID_TVFORMAT) {
+ p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+ }
+ /* Note: Incoming attribute list may or maynot have the
+ * list entries, so don't skip.
+ i += ((pd_list_attr_t *)p_attr)->num_entries;
+ p_attr += ((pd_list_attr_t *)p_attr)->num_entries; */
+
+ } else if (p_attr->type == PD_ATTR_TYPE_LIST_ENTRY) {
+ /* Skip the list entries */
+ } else {
+ PD_ERROR("sdvo: Error ! sdvo_set_attributes: "
+ "Unknown attr='%s', id=%ld, type=%ld",
+ SDVO_GET_ATTR_NAME(p_attr), p_attr->id, p_attr->type);
+ status = SS_UNSUCCESSFUL;
+ }
+ }
+
+ /* .................................................................. */
+ if (status == SS_SUCCESS) {
+ p_attr->current_value = new_value;
+ PD_DEBUG("sdvo: Success ! sdvo_set_attributes: "
+ "attr='%s', id=%ld, current_value=%ld",
+ SDVO_GET_ATTR_NAME(p_attr), p_attr->id, p_attr->current_value);
+
+ } else {
+ PD_ERROR("sdvo: Error ! sdvo_set_attributes: Failed to set "
+ "attr='%s', id=%ld", SDVO_GET_ATTR_NAME(p_attr), p_attr->id);
+ }
+ }
+
+#ifdef CONFIG_MICRO
+ if ((p_ctx->out_type.flags & TV_DISP_MASK) && set_tvformat) {
+ unsigned char params[8] = {0,0,0,0,0,0,0,0};
+ /* Special handling of TVFormat attribute in VBIOS, because
+ * it wasn't enabled in the list attributes. */
+ /* TVFormat Byte Byte
+ * Number Value
+ * -------- ------ -----
+ * 1 0 0x01
+ * 2 0 0x02
+ * 3 0 0x04
+ * 4 0 0x08
+ * 5 0 0x10
+ * 6 0 0x20
+ * 7 0 0x40
+ * 8 0 0x80
+ * 9 1 0x01
+ * 10 1 0x02
+ * 11 1 0x04
+ * 12 1 0x08
+ * 13 1 0x10
+ * ...
+ *
+ * 40 4 0x80
+ * 41 5 0x01
+ * 42 5 0x02
+ * 43 5 0x04
+ * 44 5 0x08
+ * 45 5 0x10
+ */
+ tvformat %= 46; /* TVformat <= 45 */
+ params[tvformat/8] = 1<<((tvformat%8)-1);
+ status = sdvo_execute_command(p_ctx, SET_TV_OUTPUT_FORMAT, 8,
+ params, 0, NULL);
+ PD_DEBUG("sdvo_set_attributes(): Set TVFormat = %u:"
+ "params=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x status=%u",
+ tvformat,
+ params[0], params[1], params[2],
+ params[3], params[4], params[5],
+ params[6], params[7], status);
+ set_tvformat = 0;
+ }
+#endif
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_set_power is called to change the power state of the
+ device
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ state : New power state
+
+ Remarks :
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_set_power(void *p_context, unsigned long state)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_output_flags_t active_outputs;
+ sdvo_status_t status = SS_SUCCESS;
+ unsigned short power_state;
+
+ PD_DEBUG("sdvo: sdvo_set_power(): requested state=%#lx", state);
+
+ /* Bits 7-4 in supp_pwr_states are display power states:
+ * Find next supported low power state if requested state isn't
+ * supported. */
+ power_state = 0x1 << state;
+ for (;power_state<=0x8; power_state<<=1) {
+ if ((p_ctx->supp_pwr_states>>4) & power_state) {
+ break;
+ }
+ }
+
+ /* Set display power state if it is a supported power state */
+ if (power_state <= 0x80) {
+ if (!p_ctx->st_sdvo) {
+ status = sdvo_set_display_power_state(p_ctx, (i2c_reg_t) power_state);
+ }
+ PD_DEBUG("sdvo: sdvo_set_power: "
+ "display_power_state = %#x status = %d",
+ (i2c_reg_t)power_state, status);
+ } else {
+ PD_DEBUG("sdvo: sdvo_set_power: No supported display power state");
+ }
+
+ /* Bits 3-0 in supp_pwr_states are device power states:
+ * Find next supported low power state if requested state isn't
+ * supported. */
+ power_state = 0x1 << state;
+ for (;power_state<=0x8; power_state<<=1) {
+ if (p_ctx->supp_pwr_states & power_state) {
+ break;
+ }
+ }
+
+ /* To avoid LCD flickering avoid setting the current state */
+ if (sdvo_get_power_state(p_ctx, &p_ctx->device_pwr_state) == SS_SUCCESS) {
+ if ((p_ctx->device_pwr_state & 0x0f) == power_state) {
+ PD_DEBUG("sdvo: sdvo_set_power: Device is already"
+ "in %u power state", power_state);
+ return PD_SUCCESS;
+ }
+ }
+
+
+ /* Disable the output if status is not POWER ON */
+ if (state != PD_POWER_MODE_D0) {
+ status = sdvo_get_active_outputs(p_ctx, &active_outputs);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_power: "
+ "sdvo_get_active_outputs() failed with status=%d",
+ status);
+ } else {
+ active_outputs.flags = active_outputs.flags &
+ (~p_ctx->out_type.flags);
+ status = sdvo_set_active_outputs(p_ctx, active_outputs);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error ! sdvo_set_power: "
+ "sdvo_set_active_outputs() failed with status=%d",
+ status);
+ }
+ /* Wait for panel power down sequence to complete */
+ pd_usleep((unsigned long)(p_ctx->t3+p_ctx->t4+p_ctx->t5)*1000 + 10);
+ }
+ }
+
+ /* Set device power state if it is a supported power state */
+ if (power_state <= 0x8) {
+ if (!p_ctx->st_sdvo) {
+ status = sdvo_set_power_state(p_ctx, (i2c_reg_t)power_state);
+ }
+ PD_DEBUG("sdvo: sdvo_set_power: "
+ "device_power_state = %#x status = %d",
+ (i2c_reg_t)power_state, status);
+ if (status == SS_SUCCESS || status == SS_POWER_ON_STATE) {
+ p_ctx->device_pwr_state = (unsigned char) power_state;
+ }
+ } else {
+ PD_DEBUG("sdvo: sdvo_set_power: No supported device power state");
+ }
+
+#ifdef DEBUG
+ {
+ unsigned char pstate;
+ status = sdvo_get_power_state(p_ctx, &pstate);
+ PD_DEBUG("sdvo: sdvo_set_power: new sdvo pwr_state=%#x", power_state);
+ }
+#endif
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_power is called to get the current power state
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ p_state : Returns the current power state
+
+ Remarks :
+
+ Returns : PD_SUCCESS On Success
+ PD_ERR_xxx On Failure
+ ------------------------------------------------------------------------- */
+int sdvo_get_power(void *p_context, unsigned long *p_state)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_status_t status;
+ unsigned char power_state;
+
+ PD_DEBUG("sdvo: sdvo_get_power()");
+
+ status = sdvo_get_power_state(p_ctx, &power_state);
+ if (status != SS_SUCCESS) {
+ PD_ERROR("sdvo: Error! sdvo_get_power_state() failed with status=%d",
+ status);
+ }
+
+ /* ...................................................................... */
+ PD_DEBUG("sdvo: Current Power state=%#x", power_state);
+
+ /*
+ * power_state has both the display and the encoder power state.
+ * The display state is in the upper nybble and the encoder state
+ * is in the lower nybble. Currently we only care about the
+ * encoder state so mask off the upper mybble.
+ */
+ switch ((power_state & 0x0f)) {
+ case 0x1: /* Bit 0 */
+ *p_state = PD_POWER_MODE_D0;
+ break;
+ case 0x2: /* Bit 1 */
+ *p_state = PD_POWER_MODE_D1;
+ break;
+ case 0x4: /* Bit 2 */
+ *p_state = PD_POWER_MODE_D2;
+ break;
+ case 0x8: /* Bit 3 */
+ default:
+ *p_state = PD_POWER_MODE_D3;
+ break;
+ }
+
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_save is called to save the default state of registers
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ pp_state : Returs a pointer to list of SDVO registers
+ terminated with PD_REG_LIST_END.
+ flags : Not used
+
+ Remarks : sdvo_save does not save any registers.
+
+ Returns : PD_SUCCESS
+ ------------------------------------------------------------------------- */
+int sdvo_save(void *p_context, void **pp_state, unsigned long flags)
+{
+#ifndef CONFIG_MICRO
+ sdvo_device_context_t *pd_context = (sdvo_device_context_t *)p_context;
+ sdvo_state_t *reg_state;
+ int ret, status;
+ sdvo_dtd_t p_dtd;
+
+ PD_DEBUG("sdvo: sdvo_save()");
+ /* Allocate memory to save the current regs */
+ reg_state = (sdvo_state_t *) pd_malloc(sizeof(sdvo_state_t));
+ if (!reg_state) {
+ return (PD_ERR_NOMEM);
+ }
+ pd_memset(reg_state, 0, sizeof(sdvo_state_t));
+
+ /* Save the current state */
+ ret = sdvo_get_power(pd_context, &(reg_state->power_state));
+ if (ret) {
+ pd_free(reg_state);
+ return ret;
+ }
+
+ /* Save current timings */
+ ret = sdvo_set_power(p_context, PD_POWER_MODE_D0);
+ if ((status = sdvo_get_input_timings(pd_context, &p_dtd)) != SS_SUCCESS) {
+ if (status != SS_SUCCESS) {
+ /* Standard VGA mode 3+ timings */
+ p_dtd.pixel_clock = 2832;
+ p_dtd.horz_active = 720;
+ p_dtd.horz_blanking = 162;
+ p_dtd.vert_active = 400;
+ p_dtd.vert_blanking = 35;
+ p_dtd.horz_sync_offset = 45;
+ p_dtd.horz_sync_pulse_width = 108;
+ p_dtd.vert_sync_offset = 12;
+ p_dtd.vert_sync_pulse_width = 2;
+ p_dtd.dtd_flags = 0x1c;
+ p_dtd.sdvo_flags = 0;
+ PD_ERROR("sdvo: Failed to save current timings - command not "
+ "supported.");
+ PD_ERROR("sdvo: Standard 720x400 VGA timings will be used.");
+ }
+ }
+ sdvo_convert_dtd_to_pd_timing(&p_dtd, &(reg_state->timing));
+
+ /* In case someone calls save again without restore, free the previous
+ * state */
+ if (NULL != *pp_state) {
+ pd_free(*pp_state);
+ }
+
+ *pp_state = (void *)reg_state;
+
+ /* restore power state, just in case */
+ ret = sdvo_set_power(pd_context, reg_state->power_state);
+#endif
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_restore is called to restore the registers which were
+ save previously via a call to sdvo_save
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ p_state : List of SDVO registers
+ flags : Not used
+
+ Remarks :
+
+ Returns : PD_SUCCESS
+ ------------------------------------------------------------------------- */
+int sdvo_restore(void *p_context, void *p_state, unsigned long flags)
+{
+#ifndef CONFIG_MICRO
+ sdvo_device_context_t *pd_context = (sdvo_device_context_t *)p_context;
+ sdvo_state_t *reg_state = (sdvo_state_t *)p_state;
+ pd_attr_t attr_tmp;
+ int ret;
+ unsigned long i;
+ /*i2c_reg_t reg;*/
+
+
+
+ PD_DEBUG("sdvo: sdvo_restore()");
+ if (!reg_state) {
+ PD_ERROR("restore got a NULL saved state.");
+ return PD_ERR_NULL_STATE;
+ }
+
+ sdvo_reset_encoder(p_context); /* Reset the sdvo device to known state for good
+ * start. */
+ /* Add the code to process the CH7022 card */
+ if ((pd_context->dev_cap.vendor_id == 0x02) &&
+ ((pd_context->dev_cap.device_id == 0xc2) ||
+ (pd_context->dev_cap.device_id == 0x42)) &&
+ ((pd_context->p_attr_table[0].current_value == 0x04) ||
+ (pd_context->p_attr_table[0].current_value == 0x08))) {
+ ret = sdvo_set_target_input(p_context, pd_context->inp_dev);
+ ret = sdvo_set_target_output(p_context, pd_context->out_type);
+ ret = sdvo_set_power(p_context, PD_POWER_MODE_D0);
+ ret = sdvo_set_power(p_context, PD_POWER_MODE_D3);
+
+ /* CH7021: Initialize H/V Overscan */
+ if (pd_context->out_type.flags & TV_DISP_MASK) {
+ sdvo_write_i2c_reg(p_context, 0x38, 0x1F);
+ sdvo_write_i2c_reg(p_context, 0x39, 0x1F);
+ }
+ } else {
+ /*
+ * 0X5Acircuitry enable register for 7308
+ * BIT0=1 triggers power up sequence
+ * BIT0=0 triggers power down sequence
+ * BIT3=1 enable bit for circuitry access
+ */
+ /* removing this as this seems to cause screen corruption after killx */
+ /*if ((pd_context->dev_cap.vendor_id == 2) && (pd_context->dev_cap.device_id == 0x41)){
+ sdvo_read_i2c_reg(pd_context, 0x5A, ®);
+ reg |= 9;
+ sdvo_write_i2c_reg(pd_context, 0x5A, reg);
+ }*/
+#endif
+ /* Restore the saved mode */
+ ret = sdvo_set_power(p_context, PD_POWER_MODE_D0);
+ reg_state->timing.refresh = 70; /* Is refresh needed? */
+ sdvo_set_mode(p_context, &(reg_state->timing), 0);
+ sdvo_post_set_mode(p_context, &(reg_state->timing), 0);
+ if (!(flags & PD_NO_RESTORE_FREE_STATE)) {
+ /* Restore the power state */
+ ret = sdvo_set_power(p_context, reg_state->power_state);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+
+ /* restore the sdvo attributes. */
+ /* The below should be sufficient for general sdvo + ch7308 */
+ /* TODO, add more attributes as neccessary for other cards */
+ for(i=0;i<pd_context->num_attrs;i++) {
+ switch (pd_context->p_attr_table[i].id) {
+ case PD_ATTR_ID_2_CHANNEL_PANEL:
+ case PD_ATTR_ID_LVDS_PANEL_TYPE:
+ case PD_ATTR_ID_DITHER:
+ case PD_ATTR_ID_PANEL_PROTECT_HSYNC:
+ case PD_ATTR_ID_PANEL_PROTECT_VSYNC:
+ case PD_ATTR_ID_TEXT_TUNING:
+ case PD_ATTR_ID_PANEL_DEPTH:
+ case PD_ATTR_ID_SSC:
+ case PD_ATTR_ID_DISPLAY:
+ case PD_ATTR_ID_FP_PWR_T1:
+ case PD_ATTR_ID_FP_PWR_T2:
+ case PD_ATTR_ID_FP_PWR_T3:
+ case PD_ATTR_ID_FP_PWR_T4:
+ case PD_ATTR_ID_FP_PWR_T5:
+ pd_context->p_attr_table[i].flags |= PD_ATTR_FLAG_VALUE_CHANGED;
+ sdvo_set_attributes(p_context, 1, &pd_context->p_attr_table[i]);
+ break;
+
+ /* TV format is a list attribute, need to alter in different way */
+ case PD_ATTR_ID_TVFORMAT:
+ if (pd_context->p_attr_table[i].type == PD_ATTR_TYPE_LIST) {
+ pd_memcpy(&attr_tmp, &pd_context->p_attr_table[i],
+ sizeof(pd_attr_t));
+ attr_tmp.flags |= PD_ATTR_FLAG_VALUE_CHANGED;
+ sdvo_set_attributes(p_context, 1, &attr_tmp);
+ }
+ default:
+ break;
+ }
+ }
+
+ pd_free(p_state);
+ p_state = NULL;
+
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_validate
+
+ Parameters : cookie
+
+ Remarks : sdvo_Valite returns the cookie it received as an argument
+
+ Returns : cookie
+ ------------------------------------------------------------------------- */
+unsigned long sdvo_validate(unsigned long cookie)
+{
+ PD_DEBUG("sdvo: sdvo_validate()");
+ return cookie;
+}
+
+
+/* ============================================================================
+ Function : sdvo_close is the last function to be called in the port
+ driver
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+
+ Remarks :
+
+ Returns : PD_SUCCESS
+ ------------------------------------------------------------------------- */
+int sdvo_close(void *p_context)
+{
+#ifndef CONFIG_MICRO
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ /* Shutdown device if it is tv to avoid flickering */
+ if (p_ctx->out_type.flags & TV_DISP_MASK) {
+ sdvo_set_power(p_context, PD_POWER_MODE_D3);
+ }
+ PD_DEBUG("sdvo: sdvo_close()");
+
+ if (p_ctx->p_attr_table != NULL) {
+
+ pd_free(p_ctx->p_attr_table);
+ p_ctx->p_attr_table = NULL;
+ p_ctx->num_attrs = 0;
+ }
+
+ if (p_ctx->p_mode_table) {
+ pd_free(p_ctx->p_mode_table);
+ p_ctx->p_mode_table = NULL;
+ }
+ pd_free(p_ctx);
+#endif
+ return PD_SUCCESS;
+}
+
+
+/* ============================================================================
+ Function : sdvo_get_port_status is called to get the status of the
+ display
+
+ Parameters : p_context: Pointer to port driver allocated context structure
+ port_status : Returns display type and connection state
+
+ Returns : PD_SUCCESS or PD_ERR_XXX
+ ------------------------------------------------------------------------- */
+int sdvo_get_port_status(void *p_context, pd_port_status_t *port_status)
+{
+ sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+ sdvo_output_flags_t out_flags;
+ sdvo_display_output_t disp_out;
+ sdvo_status_t status;
+ unsigned long pwr_state;
+
+ port_status->display_type = 0;
+ port_status->connected = PD_DISP_STATUS_UNKNOWN;
+
+
+ /* Save the current power state and turn on the port device's power
+ * so we can query it
+ */
+ sdvo_get_power(p_context, &pwr_state);
+ sdvo_set_power(p_context, PD_POWER_MODE_D0);
+
+ status = sdvo_get_attached_displays(p_ctx, &out_flags);
+
+ sdvo_set_power(p_context, pwr_state);
+
+ if (status != SS_SUCCESS) {
+ /* TODO: Certain SDVO cards (CH7022) would return SS_PENDING. Need to
+ * Identify correct setting so the card behaves correctly. For now
+ * we would fallback to out_type kept in the context.
+ */
+ if(status == SS_PENDING){
+ out_flags.flags = p_ctx->out_type.flags;
+ }else{
+ PD_ERROR("sdvo: Error ! sdvo_get_port_status: "
+ "sdvo_get_attached_displays() failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+ }
+
+ if (p_ctx->st_sdvo) {
+ out_flags.flags = p_ctx->out_type.flags;
+
+ if (p_ctx->out_type.flags == 0x40) {
+ out_flags.out0.lvds = 1;
+ out_flags.out0.drgb = 0;
+ out_flags.out1.lvds = 0;
+ out_flags.out1.drgb = 0;
+ } else {
+ out_flags.out0.lvds = 0;
+ out_flags.out0.drgb = 1;
+ out_flags.out1.lvds = 0;
+ out_flags.out1.drgb = 0;
+ }
+ }
+
+ if (p_ctx->inp_dev == SDVO0) {
+ disp_out = out_flags.out0;
+ } else {
+ disp_out = out_flags.out1;
+ }
+
+ port_status->connected = PD_DISP_STATUS_ATTACHED;
+
+ if (disp_out.tmds) {
+ status = SDVO_IS_HDMI_SUPPORTED(p_ctx);
+ if (status == SS_SUCCESS) {
+ PD_DEBUG("sdvo: HDMI transmiter ");
+ g_sdvo_drv.type = PD_DISPLAY_HDMI_EXT;
+ port_status->display_type = PD_DISPLAY_HDMI_EXT;
+ } else{
+ g_sdvo_drv.type = PD_DISPLAY_FP;
+ port_status->display_type = PD_DISPLAY_FP;
+ }
+ } else if (disp_out.lvds) {
+ port_status->display_type = PD_DISPLAY_LVDS_EXT;
+ } else if (disp_out.rgb) {
+ port_status->display_type = PD_DISPLAY_CRT_EXT;
+ } else if (disp_out.drgb) {
+ port_status->display_type = PD_DISPLAY_DRGB;
+ } else if (disp_out.cvbs || disp_out.scart ||
+ disp_out.svid || disp_out.yprpb) {
+ port_status->display_type = PD_DISPLAY_TVOUT;
+ } else {
+ port_status->connected = PD_DISP_STATUS_DETACHED;
+ }
+ return PD_SUCCESS;
+}
+
+char *sdvo_get_output_type(sdvo_display_output_t out, unsigned char byte)
+{
+ static char buff[40] = "";
+ int indx = 0;
+
+ if (out.tmds) {
+
+ pd_strcpy(&buff[indx], " tmds");
+ indx += 5;
+ }
+
+ if (out.rgb) {
+
+ pd_strcpy(&buff[indx], " rgb");
+ indx += 4;
+ }
+
+ if (out.cvbs) {
+
+ pd_strcpy(&buff[indx], " cvbs");
+ indx += 5;
+ }
+
+ if (out.svid) {
+
+ pd_strcpy(&buff[indx], " svid");
+ indx += 5;
+ }
+
+ if (out.yprpb) {
+
+ pd_strcpy(&buff[indx], " yprpb");
+ indx += 6;
+ }
+
+ if (out.scart) {
+
+ pd_strcpy(&buff[indx], " scart");
+ indx += 6;
+ }
+
+ if (out.lvds) {
+
+ pd_strcpy(&buff[indx], " lvds");
+ indx += 5;
+ }
+
+ /* DRGB defined in byte0 of SDVOOutputFlagStructure */
+ if (byte == 0 && out.drgb) {
+ pd_strcpy(&buff[indx], " drgb");
+ indx += 5;
+ }
+
+ if (indx == 0) {
+
+ pd_strcpy(buff, " None");
+ }
+
+ return buff;
+}
+
+
+/* ============================================================================
+ Function : sdvo_convert_pd_timing_to_dtd
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+void sdvo_convert_pd_timing_to_dtd(pd_timing_t *p_mode, sdvo_dtd_t *p_dtd,
+ unsigned long dclk)
+{
+ pd_memset(p_dtd, 0, sizeof(sdvo_dtd_t));
+
+ p_dtd->pixel_clock = (unsigned short)(dclk / 10);
+
+ p_dtd->horz_active = p_mode->width;
+ p_dtd->horz_blanking = p_mode->hblank_end - p_mode->hblank_start;
+ p_dtd->horz_sync_offset = p_mode->hsync_start - p_mode->width + 1;
+ p_dtd->horz_sync_pulse_width= p_mode->hsync_end - p_mode->hsync_start;
+
+ p_dtd->vert_active = p_mode->height;
+ p_dtd->vert_blanking = p_mode->vblank_end - p_mode->vblank_start;
+ p_dtd->vert_sync_offset = p_mode->vsync_start - p_mode->height + 1;
+ p_dtd->vert_sync_pulse_width= p_mode->vsync_end - p_mode->vsync_start;
+
+ /* ...................................................................... */
+ p_dtd->dtd_flags = (BIT(4) | BIT(3)); /* Digital Seperate */
+
+ if (p_mode->mode_info_flags & PD_SCAN_INTERLACE) {
+
+ p_dtd->dtd_flags |= BIT(7);
+ }
+
+ if (p_mode->mode_info_flags & PD_HSYNC_HIGH) { /* HSync + */
+
+ p_dtd->dtd_flags |= BIT(1);
+ }
+
+ if (p_mode->mode_info_flags & PD_VSYNC_HIGH) { /* VSync + */
+
+ p_dtd->dtd_flags |= BIT(2);
+ }
+
+ /* .................................................................... */
+ p_dtd->sdvo_flags = 0;
+}
+
+
+/* ============================================================================
+ Function : sdvo_convert_dtd_to_pd_timing
+
+ Parameters :
+
+ Remarks :
+
+ Returns :
+ ------------------------------------------------------------------------- */
+void sdvo_convert_dtd_to_pd_timing(sdvo_dtd_t *p_dtd, pd_timing_t *p_mode)
+{
+ pd_memset(p_mode, 0, sizeof(pd_timing_t));
+
+ p_mode->dclk = p_dtd->pixel_clock * 10L;
+
+ p_mode->width = p_dtd->horz_active;
+ p_mode->hsync_start = p_dtd->horz_sync_offset + p_dtd->horz_active - 1;
+ p_mode->hsync_end = p_dtd->horz_sync_pulse_width + p_mode->hsync_start;
+ p_mode->hblank_start= p_dtd->horz_active - 1;
+ p_mode->hblank_end = p_dtd->horz_blanking + p_mode->hblank_start;
+ p_mode->htotal = p_dtd->horz_active + p_dtd->horz_blanking - 1;
+
+ p_mode->height = p_dtd->vert_active;
+ p_mode->vsync_start = p_dtd->vert_sync_offset + p_dtd->vert_active - 1;
+ p_mode->vsync_end = p_dtd->vert_sync_pulse_width + p_mode->vsync_start;
+ p_mode->vblank_start= p_dtd->vert_active - 1;
+ p_mode->vblank_end = p_dtd->vert_blanking + p_mode->vblank_start;
+ p_mode->vtotal = p_dtd->vert_active + p_dtd->vert_blanking - 1;
+
+ /* .................................................................... */
+ if (p_dtd->dtd_flags & BIT(7)) {
+ p_mode->mode_info_flags |= PD_SCAN_INTERLACE;
+ }
+
+ if (p_dtd->dtd_flags & BIT(1)) {
+ p_mode->mode_info_flags |= PD_HSYNC_HIGH;
+ }
+
+ if (p_dtd->dtd_flags & BIT(2)) {
+ p_mode->mode_info_flags |= PD_VSYNC_HIGH;
+ }
+}
+
+/* ============================================================================
+ Function : sdvo_init_attribute_table
+
+ Parameters : p_ctx
+
+ Remarks :
+
+ Returns : PD_SUCCESS or PD_ERR_XXX
+ ------------------------------------------------------------------------- */
+int sdvo_init_attribute_table(sdvo_device_context_t *p_ctx)
+{
+ unsigned long num_attrs, num_static_attrs, num_pwr_seq_attrs;
+ unsigned long num_range_attrs, num_bool_attrs, num_list_attrs;
+ unsigned char *p_table;
+ sdvo_status_t status;
+
+ /* .................................................................. */
+ status = sdvo_set_target_input(p_ctx, p_ctx->inp_dev);
+ if (status != SS_SUCCESS) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: sdvo_set_target_input()"
+ "failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+ status = sdvo_set_target_output(p_ctx, p_ctx->out_type);
+ if (status != SS_SUCCESS) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table:"
+ "sdvo_set_target_output()failed with status=%d", status);
+ return PD_ERR_INTERNAL;
+ }
+
+
+ /* .................................................................. */
+ /* Get the number of available attributes from the SDVO interface */
+ num_static_attrs = sdvo_get_static_attrs(p_ctx, NULL);
+ num_pwr_seq_attrs = sdvo_get_panel_pwr_seq_attrs(p_ctx, NULL);
+ num_range_attrs = sdvo_get_range_attrs(p_ctx, NULL);
+ num_bool_attrs = sdvo_get_bool_attrs(p_ctx, NULL);
+ num_list_attrs = sdvo_get_list_attrs(p_ctx, NULL);
+ p_ctx->num_attrs = num_static_attrs + num_pwr_seq_attrs +
+ num_range_attrs + num_bool_attrs + num_list_attrs;
+
+ if (p_ctx->num_attrs == 0) {
+
+ PD_ERROR("sdvo: Warning ! sdvo_init_attribute_table: "
+ "No attributes found");
+
+ return PD_SUCCESS;
+ }
+
+ /* .................................................................. */
+ /* Allocate memory to save all available port attributes. */
+ /* Allocate space for extra attribute so Query_Attr function can be */
+ /* called using that space for the last+1 attribute. */
+ /* Query and save all the available attributes. */
+ p_ctx->p_attr_table = pd_malloc((p_ctx->num_attrs + 1) * sizeof(pd_attr_t));
+ if (p_ctx->p_attr_table == NULL) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "pd_malloc(p_attr_table) failed");
+
+ p_ctx->num_attrs = 0;
+ return PD_ERR_NOMEM;
+ }
+
+ pd_memset(p_ctx->p_attr_table, 0, (p_ctx->num_attrs + 1) *
+ sizeof(pd_attr_t));
+
+ p_table = (unsigned char *)p_ctx->p_attr_table;
+
+ /* .................................................................. */
+ if (num_static_attrs > 0) {
+
+ num_attrs = sdvo_get_static_attrs(p_ctx, (pd_attr_t *)p_table);
+ if (num_attrs != num_static_attrs) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "sdvo_get_static_attrs() returned %ld entries, expected %ld",
+ num_attrs, num_static_attrs);
+
+ } else {
+
+ p_table += (num_static_attrs * sizeof(pd_attr_t));
+ }
+ }
+
+ if (num_pwr_seq_attrs > 0) {
+
+ num_attrs = sdvo_get_panel_pwr_seq_attrs(p_ctx,
+ (pd_range_attr_t *)p_table);
+ if (num_attrs != num_pwr_seq_attrs) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "sdvo_get_panel_pwr_seq_attrs() returned %ld entries,"
+ " expected %ld", num_attrs, num_pwr_seq_attrs);
+
+ } else {
+
+ p_table += (num_pwr_seq_attrs * sizeof(pd_attr_t));
+ }
+ }
+
+ if (num_range_attrs > 0) {
+
+ num_attrs = sdvo_get_range_attrs(p_ctx, (pd_range_attr_t *)p_table);
+ if (num_attrs != num_range_attrs) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "sdvo_get_range_attrs() returned %ld entries,"
+ " expected %ld", num_attrs, num_range_attrs);
+
+ } else {
+
+ p_table += (num_range_attrs * sizeof(pd_attr_t));
+ }
+ }
+
+ if (num_bool_attrs > 0) {
+
+ num_attrs = sdvo_get_bool_attrs(p_ctx, (pd_bool_attr_t *)p_table);
+ if (num_attrs != num_bool_attrs) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "sdvo_get_bool_attrs() returned %ld entries, expected %ld",
+ num_attrs, num_bool_attrs);
+
+ } else {
+
+ p_table += (num_bool_attrs * sizeof(pd_attr_t));
+ }
+ }
+
+ if (num_list_attrs > 0) {
+
+ num_attrs = sdvo_get_list_attrs(p_ctx, (pd_list_attr_t *)p_table);
+ if (num_attrs != num_list_attrs) {
+
+ PD_ERROR("sdvo: Error ! sdvo_init_attribute_table: "
+ "sdvo_get_list_attrs() returned %ld entries, expected %ld",
+ num_attrs, num_list_attrs);
+ } else {
+
+ p_table += (num_list_attrs * sizeof(pd_attr_t));
+ }
+ }
+ return PD_SUCCESS;
+}
+
+int sdvo_is_multi_display_device(sdvo_device_context_t *p_ctx)
+{
+ unsigned short i;
+ int b_multi_display = 0;
+
+ for (i = 0; i < 16; i++) {
+ if (p_ctx->dev_cap.output.flags & (1 << i)) {
+ if (!b_multi_display) {
+ b_multi_display = 1;
+ } else {
+ return TRUE;
+ }
+ }
+ }
+ return 0;
+}
+
+#ifndef CONFIG_MICRO
+static sdvo_status_t sdvo_reset_encoder(sdvo_device_context_t *p_ctx)
+{
+ sdvo_status_t ret_stat;
+ if ((p_ctx->dev_cap.vendor_id == VENDOR_ID_LAPIS)
+ && (p_ctx->dev_cap.device_id == 0x1)){
+
+ pd_attr_t *p_attr_temp =
+ pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+ PD_ATTR_ID_RB_SWAP_MODE, 0 );
+
+ if (!(p_attr_temp->flags & PD_ATTR_FLAG_NEED_RESTORE)){
+ sdvo_query_static_attr(p_ctx, p_attr_temp);
+ p_attr_temp->flags |= PD_ATTR_FLAG_NEED_RESTORE;
+ }
+
+
+
+ sdvo_reset (p_ctx);
+ pd_usleep(10);
+ sdvo_reset (p_ctx);
+
+ ret_stat = sdvo_reset (p_ctx);
+
+ } else {
+ ret_stat = sdvo_reset (p_ctx);
+ }
+
+ return ret_stat;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
new file mode 100644
index 0000000..17a004f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
@@ -0,0 +1,71 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_port.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Main include file for SDVO port driver
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_PORT_H_
+#define _SDVO_PORT_H_
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+/* #define DEBUG 0 */
+
+/* ............................................................................ */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+#include "sdvo_intf.h"
+#include "sdvo_attr.h"
+#include "sdvo_hdmi.h"
+
+/* ............................................................................ */
+#ifndef CONFIG_MICRO
+#define SDVO_GET_ATTR_NAME(p_attr) p_attr->name
+#else
+#define SDVO_GET_ATTR_NAME(p_attr) ""
+#endif
+
+/* ............................................................................ */
+unsigned char sdvo_write_i2c_reg(sdvo_device_context_t *p_Ctx, i2c_reg_t offset,
+ i2c_reg_t value);
+unsigned char sdvo_read_i2c_reg(sdvo_device_context_t *p_Ctx, unsigned char offset,
+ i2c_reg_t *p_Value);
+
+
+int sdvo_is_multi_display_device(sdvo_device_context_t *p_ctx);
+
+/*LAPIS Workaround*/
+#define VENDOR_ID_LAPIS 0x81
+
+
+#endif /* _SDVO_PORT_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
new file mode 100644
index 0000000..3da03e0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
@@ -0,0 +1,56 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _APPCONTEXT_DISPATCH_H
+#define _APPCONTEXT_DISPATCH_H
+
+typedef struct _appcontext_table_t {
+ unsigned long appcontext_id;
+ unsigned long logical_context_offset;
+} appcontext_table_t;
+
+typedef struct _appcontext_dispatch_t {
+ int (*appcontext_init)(igd_context_t *context);
+ void (*appcontext_shutdown)(igd_context_t *context);
+ igd_appcontext_h (*appcontext_alloc)(igd_display_h display_handle,
+ int priority, unsigned int flags);
+ void (*appcontext_free)(igd_display_h display_handle,
+ int priority, igd_appcontext_h context_handle);
+ appcontext_table_t *table;
+} appcontext_dispatch_t;
+
+
+extern appcontext_dispatch_t appcontext_dispatch_plb;
+
+extern appcontext_dispatch_t *appcontext_dispatch;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
new file mode 100755
index 0000000..c5ee392
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
@@ -0,0 +1,148 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_appcontext.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file inplements the IGD interface for the context module. This
+ * includes functions that handle hardware context swapping and state
+ * variable management.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <config.h>
+
+#include <igd_appcontext.h>
+#include <igd_gmm.h>
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <intelpci.h>
+#include <context.h>
+#include <mode.h>
+#include <dispatch.h>
+
+#include <io.h>
+
+#include "appcontext_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static dispatch_table_t appcontext_dispatch_list[] = {
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &appcontext_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &appcontext_dispatch_plb},
+#endif
+ {0, NULL}
+};
+
+/* Not static: cores may need it */
+appcontext_dispatch_t *appcontext_dispatch = NULL;
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param flags
+ *
+ * @return appcontext_h
+ */
+igd_appcontext_h igd_appcontext_alloc(
+ igd_display_h display_handle,
+ int priority,
+ unsigned int flags)
+{
+
+ return appcontext_dispatch->appcontext_alloc(
+ display_handle, priority, flags);
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param appcontext_handle
+ *
+ * @return void
+ */
+void igd_appcontext_free(
+ igd_display_h display_handle,
+ int priority,
+ igd_appcontext_h appcontext_handle)
+{
+ appcontext_dispatch->appcontext_free(
+ display_handle, priority, appcontext_handle);
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void appcontext_shutdown(igd_context_t *context)
+{
+
+ EMGD_DEBUG("appcontext_shutdown Entry");
+
+ if (appcontext_dispatch != NULL)
+ {
+ appcontext_dispatch->appcontext_shutdown(context);
+ }
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+int appcontext_init(igd_context_t *context)
+{
+
+ EMGD_DEBUG("appcontext_init Entry");
+
+ appcontext_dispatch = (appcontext_dispatch_t *)dispatch_acquire(context,
+ appcontext_dispatch_list);
+ if(!appcontext_dispatch) {
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Hook up top level dispatch table */
+ context->dispatch.appcontext_alloc = appcontext_dispatch->appcontext_alloc;
+ context->dispatch.appcontext_free = appcontext_dispatch->appcontext_free;
+
+ /* Hook up optional inter-module functions */
+ context->mod_dispatch.appcontext_shutdown = appcontext_shutdown;
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c b/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
new file mode 100644
index 0000000..568e24f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
@@ -0,0 +1,207 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext_plb.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file inplements the IGD interface for the context module. This
+ * includes functions that handle hardware context swapping and state
+ * variable management.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+
+#include <igd_appcontext.h>
+#include <igd_gmm.h>
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_errno.h>
+
+#include <intelpci.h>
+#include <memory.h>
+#include <mode_access.h>
+#include <context.h>
+#include <state2d.h>
+#include <mode.h>
+#include <dispatch.h>
+#include <utils.h>
+
+#include <plb/appcontext.h>
+#include <plb/instr.h>
+#include <plb/state3d_plb.h>
+
+#include "../cmn/appcontext_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+/*
+ * Prototype these here because they are only needed by appcontext.c
+ * and putting them in state2d.h would cause a circular dependency.
+ */
+
+static igd_appcontext_h igd_appcontext_alloc_plb(
+ igd_display_h display_handle,
+ int priority,
+ unsigned int flags);
+static void igd_appcontext_free_plb(
+ igd_display_h display_h,
+ int priority,
+ igd_appcontext_h appcontext_handle);
+static int appcontext_init_plb(igd_context_t *context);
+static void appcontext_shutdown_plb(igd_context_t *context);
+
+static appcontext_table_t appcontext_table_plb[] = {
+ {0, 0}
+};
+
+appcontext_dispatch_t appcontext_dispatch_plb = {
+ appcontext_init_plb,
+ appcontext_shutdown_plb,
+ igd_appcontext_alloc_plb,
+ igd_appcontext_free_plb,
+ appcontext_table_plb
+};
+
+/*!
+ *
+ * @param appcontext
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_NOMEM on failure
+ */
+static int state2d_init_plb(appcontext_t *appcontext)
+{
+
+ appcontext->state2d = OS_ALLOC(sizeof(state2d_t));
+ if(!appcontext->state2d) {
+ return -IGD_ERROR_NOMEM;
+ }
+
+ STATE2D(appcontext)->clip_status = IGD_CLIP_DISABLED;
+ STATE2D(appcontext)->dest_rect.x1 = 0;
+ STATE2D(appcontext)->dest_rect.y1 = 0;
+ STATE2D(appcontext)->dest_rect.x2 = 0;
+ STATE2D(appcontext)->dest_rect.y2 = 0;
+
+ return 0;
+}
+
+/*!
+ *
+ * @param appcontext
+ *
+ * @return void
+ */
+static int state2d_shutdown_plb(appcontext_t *appcontext)
+{
+ if(appcontext->state2d) {
+ OS_FREE(appcontext->state2d);
+ }
+
+ appcontext->state2d = NULL;
+
+ return 0;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param flags
+ *
+ * @return appcontext_h on success
+ * @return NULL on failure
+ */
+static igd_appcontext_h igd_appcontext_alloc_plb(
+ igd_display_h display_handle,
+ int priority,
+ unsigned int flags)
+{
+ appcontext_t *appcontext;
+
+ /* A proper appcontext is not required for Poulsbo
+ * as a result, we'll allocate it and have it set to NULL
+ */
+ appcontext = OS_ALLOC(sizeof(appcontext_t));
+ if (!appcontext) {
+ EMGD_ERROR ("OS_ALLOC appcontext failed\n");
+ return NULL;
+ }
+
+ OS_MEMSET(appcontext, 0, sizeof(appcontext_t));
+ appcontext->state2d = NULL;
+
+ if (flags & IGD_CONTEXT_STATE_2D) {
+ if (state2d_init_plb(appcontext)) {
+ igd_appcontext_free_plb(display_handle, priority, appcontext);
+ return NULL;
+ }
+ }
+
+ return appcontext;
+
+}
+
+static void igd_appcontext_free_plb(
+ igd_display_h display_h,
+ int priority,
+ igd_appcontext_h appcontext_handle)
+{
+
+ appcontext_t *appcontext = (appcontext_t *)appcontext_handle;
+
+ /* Free the appcontext struct */
+ if (appcontext) {
+ state2d_shutdown_plb(appcontext);
+
+ OS_FREE(appcontext_handle);
+ }
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+static int appcontext_init_plb(igd_context_t *context)
+{
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void appcontext_shutdown_plb(igd_context_t *context)
+{
+ return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c b/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
new file mode 100644
index 0000000..2cfd775
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
@@ -0,0 +1,305 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pwr.c
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.power
+
+#include <config.h>
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_errno.h>
+#include <igd_pwr.h>
+#include <igd_mode.h>
+
+#include <module_init.h>
+#include <mode.h>
+#include <dsp.h>
+#include <intelpci.h>
+#include <dispatch.h>
+#include "pwr_dispatch.h" /* contains the power dispatch functions */
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static dispatch_table_t pwr_dispatch_list[] = {
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &pwr_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &pwr_dispatch_plb},
+#endif
+ {0, NULL}
+};
+
+typedef struct _power_context {
+ pwr_dispatch_t *dispatch;
+ void *power_state;
+} power_context_t;
+
+static power_context_t power_context;
+
+static int igd_pwr_query(igd_driver_h driver_handle, unsigned int power_state)
+{ /* igd_pwr_query */
+ return power_context.dispatch->pwr_query(power_state);
+} /* igd_pwr_query */
+
+/*!
+ * This function alters the power state of the graphics device. This
+ * function saves and restores registers as necessary and changes the
+ * power states of the mode and overlay module.
+ *
+ * This function will convert a request for D2 to a request for D1.
+ *
+ * @param driver_handle driver context
+ * @param dwPowerState power state to set the device to.
+ *
+ * @return < 0 on Error
+ * @return 0 on Success
+ */
+static int igd_pwr_alter(igd_driver_h driver_handle, unsigned int dwPowerState)
+{ /* igd_pwr_alter */
+ unsigned char *mmio;
+ int retval = 0;
+ igd_context_t *context = (igd_context_t *) driver_handle;
+
+ EMGD_DEBUG("in igd_pwr_alter");
+
+ EMGD_DEBUG("Power State requested: 0x%x", dwPowerState);
+
+ if(context == NULL) {
+ EMGD_ERROR("In igd_pwr_alter:-Device context is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ if(power_context.power_state == NULL) {
+ EMGD_DEBUG("In igd_pwr_alter:- Memory not allocated yet."
+ " Power Module Not Initialised");
+ return -IGD_ERROR_INVAL;
+ }
+
+ mmio = context->device_context.virt_mmadr;
+
+ if(context->device_context.power_state == dwPowerState ) {
+ EMGD_DEBUG("Already in the present state");
+ return -IGD_ERROR_INVAL;
+ }
+
+ switch(dwPowerState) {
+ case IGD_POWERSTATE_D0:
+ /* Do any chipset specific power management */
+ retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+ /* restore the registers */
+ retval = context->mod_dispatch.reg_restore(context,
+ power_context.power_state);
+ if (retval) {
+ return retval;
+ }
+
+ /* Officially change the power state after registers are restored */
+ context->device_context.power_state = IGD_POWERSTATE_D0;
+
+ /* Power up mode module */
+ if(context->mod_dispatch.mode_pwr) {
+ retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+ if (retval) {
+ return retval;
+ }
+ }
+
+ /* enable overlay */
+ if(context->mod_dispatch.overlay_pwr) {
+ context->mod_dispatch.overlay_pwr(context, IGD_POWERSTATE_D0);
+ }
+
+ /* enable msvdx */
+ if(context->mod_dispatch.msvdx_pwr) {
+ context->mod_dispatch.msvdx_pwr(context, IGD_POWERSTATE_D0);
+ }
+ break;
+
+ case IGD_POWERSTATE_D1:
+ case IGD_POWERSTATE_D2:
+ /* Standby - ACPI S1 */
+
+ if (IGD_POWERSTATE_D2 == dwPowerState) {
+ dwPowerState = IGD_POWERSTATE_D1;
+ }
+
+
+ /* Turn off the msvdx */
+ if(context->mod_dispatch.msvdx_pwr) {
+ context->mod_dispatch.msvdx_pwr(context, dwPowerState);
+ }
+
+ /* Turn off the overlay */
+ if(context->mod_dispatch.overlay_pwr) {
+ context->mod_dispatch.overlay_pwr(context, dwPowerState);
+ }
+
+ /* save registers */
+ retval = context->mod_dispatch.reg_save(context,
+ power_context.power_state);
+ if (retval) {
+ return retval;
+ }
+
+ /* Change the state of the device to Dx. This is required so the
+ * plane/pipe/port all use this. This needs to happen after "reg_save"
+ * because igd_sync will timeout if power state is not D0
+ */
+ context->device_context.power_state = dwPowerState;
+
+ if(context->mod_dispatch.mode_pwr) {
+ retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+ if (retval) {
+ return retval;
+ }
+ }
+
+ /* Do any chipset specific power management */
+ retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+ break;
+
+ case IGD_POWERSTATE_D3:
+ /* Suspend to memory - ACPI S3 */
+
+ /* diable msvdx */
+ if(context->mod_dispatch.msvdx_pwr) {
+ context->mod_dispatch.msvdx_pwr(context, dwPowerState);
+ }
+
+ /* disable overlay */
+ if(context->mod_dispatch.overlay_pwr) {
+ context->mod_dispatch.overlay_pwr(context, dwPowerState);
+ }
+
+ /* save registers */
+ retval= context->mod_dispatch.reg_save(context,
+ power_context.power_state);
+ if (retval) {
+ return retval;
+ }
+
+ /* Change the state of the device to Dx. This is required so the
+ * plane/pipe/port all use this. This needs to happen after "reg_save"
+ * because igd_sync will timeout if power state is not D0
+ */
+ context->device_context.power_state = dwPowerState;
+
+ /* Mode module Power */
+ if(context->mod_dispatch.mode_pwr) {
+ retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+ if (retval) {
+ return retval;
+ }
+ }
+
+
+ /* Do any chipset specific power management */
+ retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+ break;
+
+ default:
+ /* state undefined */
+ EMGD_ERROR("In igd_pwr_alter:-Undefined Power State");
+ break;
+
+ }
+
+ return retval;
+} /* igd_pwr_alter */
+
+/*!
+ * This function should be called from context manager.
+ * To delete the memory allocated ealier.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void _pwr_shutdown(igd_context_t *context)
+{
+
+ if(power_context.power_state) {
+ context->mod_dispatch.reg_free(context, power_context.power_state);
+ }
+ power_context.power_state = NULL;
+ context->device_context.power_state = IGD_POWERSTATE_UNDEFINED;
+ return;
+}
+
+/*!
+ * This function should only be called only once from context manager .
+ * It initializes the power module.
+ *
+ * @param context
+ *
+ * @return < 0 on Error
+ * @return 0 on Success
+ */
+int _pwr_init(igd_context_t *context)
+{ /* _pwr_init */
+ EMGD_ASSERT(context, "Null Context", -IGD_ERROR_INVAL);
+
+ /* Hook up the IGD dispatch table entires for power */
+ context->dispatch.pwr_alter = igd_pwr_alter;
+ context->dispatch.pwr_query = igd_pwr_query;
+
+ /* Inter-module dispatch */
+ context->mod_dispatch.pwr_shutdown = _pwr_shutdown;
+
+ power_context.dispatch = (pwr_dispatch_t *)dispatch_acquire(context,
+ pwr_dispatch_list);
+
+ if(!power_context.dispatch) {
+ return -IGD_ERROR_NODEV;
+ }
+
+ /* Initialize chipset specific default power behavior */
+ power_context.dispatch->pwr_init(context);
+
+ power_context.power_state = context->mod_dispatch.reg_alloc(context,
+ IGD_REG_SAVE_VGA |
+ IGD_REG_SAVE_DAC | IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB |
+ IGD_REG_SAVE_MODE | IGD_REG_SAVE_3D );
+
+ if(!power_context.power_state) {
+ return -IGD_ERROR_NOMEM;
+ }
+
+ return 0;
+} /* _pwr_init */
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
new file mode 100644
index 0000000..34043ba
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pwr_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the protocols for the plaform-specific dispatch
+ * functions that the power module uses.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PWR_DISPATCH_H
+#define _PWR_DISPATCH_H
+
+#include <context.h>
+
+typedef struct _pwr_dispatch {
+ /* Queries support for power_state
+ * ret: 0 if power_state is supported, <0 otherwise
+ */
+ int (*pwr_query)(unsigned int power_state);
+ /* Dispatch function to set device dependent part of set power */
+ int (*pwr_set)(igd_context_t *context, unsigned int power_state);
+ /* Dispatch function to set init time device dependent power settings */
+ int (*pwr_init)(igd_context_t *context);
+} pwr_dispatch_t;
+
+extern pwr_dispatch_t pwr_dispatch_plb;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c b/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
new file mode 100644
index 0000000..22d3280
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
@@ -0,0 +1,123 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pwr_plb.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/* copied from napa */
+
+#include <io.h>
+#include "igd_pwr.h"
+#include "../cmn/pwr_dispatch.h"
+#include <plb/regs.h>
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static int pwr_query_full_plb(unsigned int power_state);
+static int pwr_set_plb(igd_context_t *context, unsigned int power_state);
+static int pwr_init_plb(igd_context_t *context);
+
+pwr_dispatch_t pwr_dispatch_plb = {
+ pwr_query_full_plb,
+ pwr_set_plb,
+ pwr_init_plb,
+};
+
+/*!
+ * This function returns "0" for all ACPI system states.
+ *
+ * @param power_state the requested power state
+ *
+ * @return 0
+ */
+static int pwr_query_full_plb(unsigned int power_state)
+{ /* pwr_query_full */
+ switch( power_state ) {
+
+ case IGD_ADAPTERPOWERSTATE_ON:
+ case IGD_ADAPTERPOWERSTATE_STANDBY:
+ case IGD_ADAPTERPOWERSTATE_OFF:
+ case IGD_ADAPTERPOWERSTATE_SUSPEND:
+ case IGD_ADAPTERPOWERSTATE_HIBERNATE:
+ default:
+ return 0;
+ break;
+ }
+} /* pwr_query_full */
+
+/*!
+ *
+ * @patam context
+ * @param power_state the requested power state
+ *
+ * @return 0
+ */
+static int pwr_set_plb(igd_context_t *context, unsigned int power_state)
+{
+ unsigned char *mmio;
+
+ mmio = context->device_context.virt_mmadr;
+
+ switch (power_state) {
+ case IGD_POWERSTATE_D0:
+ break;
+ case IGD_POWERSTATE_D1:
+ break;
+ case IGD_POWERSTATE_D2:
+ break;
+ case IGD_POWERSTATE_D3:
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+static int pwr_init_plb(igd_context_t *context)
+{
+ unsigned char *mmio;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Reset CLKGATECTL and CLKGATECTLOVR */
+ EMGD_WRITE32(0x1111111, mmio + PSB_CR_CLKGATECTL);
+ EMGD_WRITE32(0, mmio + PSB_CR_CLKGATECTL + 8);
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
new file mode 100644
index 0000000..e030f0d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
@@ -0,0 +1,451 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg.c
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the implementation file for the register module's main API's called
+ * by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <utils.h>
+#include <dsp.h>
+#include <mode.h>
+#include <memory.h>
+#include <utils.h>
+
+#include <intelpci.h>
+#include <dispatch.h>
+
+#include "reg_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+typedef struct _reg_context {
+ unsigned long flags; /* IGD_DRIVER_SAVE_RESTORE */
+ reg_dispatch_t *dispatch;
+ reg_buffer_t *device_state;
+ void *gmm_state;
+} reg_context_t;
+
+extern emgd_drm_config_t config_drm;
+static reg_context_t reg_ctx[1];
+static reg_buffer_t *console_state;
+void *console_gmm_state;
+static reg_buffer_t *misc_state;
+void *misc_gmm_state;
+
+static dispatch_table_t reg_dispatch_list[] = {
+
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, ®_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, ®_dispatch_tnc},
+#endif
+ {0, NULL}
+};
+
+void *reg_alloc(igd_context_t *context,
+ unsigned long flags)
+{
+ return (void *)reg_ctx->dispatch->reg_alloc(context, flags,
+ reg_ctx->dispatch->platform_context);
+}
+
+void reg_free(igd_context_t *context,
+ void *reg_set)
+{
+ reg_ctx->dispatch->reg_free(context, (reg_buffer_t *)reg_set,
+ reg_ctx->dispatch->platform_context);
+}
+
+int reg_save(igd_context_t *context,
+ void *reg_set)
+{
+ return reg_ctx->dispatch->reg_save(context, (reg_buffer_t *)reg_set,
+ reg_ctx->dispatch->platform_context);
+}
+
+int reg_restore(igd_context_t *context,
+ void *reg_set)
+{
+ return reg_ctx->dispatch->reg_restore(context, (reg_buffer_t *)reg_set,
+ reg_ctx->dispatch->platform_context);
+}
+
+void reg_crtc_lut_get(igd_context_t *context,
+ void *emgd_crtc)
+{
+ reg_ctx->dispatch->reg_crtc_lut_get(context, (emgd_crtc_t *)emgd_crtc);
+}
+
+void reg_crtc_lut_set(igd_context_t *context,
+ void *emgd_crtc)
+{
+ reg_ctx->dispatch->reg_crtc_lut_set(context, (emgd_crtc_t *)emgd_crtc);
+}
+
+/*!
+ * This function calls reg_save() to save the state of the graphics engine
+ * and then reg_restore to restore the previous state.
+ *
+ * @param driver_handle our driver context
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_driver_save_restore(igd_driver_h driver_handle,
+ unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ reg_buffer_t *reg_state;
+ short restored = 0;
+
+ EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
+
+ /*
+ * If the gmm_state exists, the registers are not setup, so we should not
+ * try to save the GTT, the ring buffer and appcontext, or it will cause a
+ * sync which will not be fulfilled, so it will wait forever. We can
+ * however save everything else. If the gmm_state is null, then everything
+ * is still setup and we can save everything including the GTT, ring buffer
+ * and appcontext.
+ */
+ if (reg_ctx->gmm_state) {
+ flags = flags & ~IGD_REG_SAVE_GTT & ~IGD_REG_SAVE_RB;
+ }
+
+ /* Save current state. We have to save the current state first before
+ * restoring the GART bindings. Otherwise we will end up restoring wrong
+ * pages when return back to the graphic mode console */
+ reg_state = reg_ctx->dispatch->reg_alloc(context, flags,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_save(context, reg_state,
+ reg_ctx->dispatch->platform_context);
+
+ /* Restore GART bindings, if saved */
+ if (reg_ctx->gmm_state && context->mod_dispatch.gmm_restore) {
+ context->mod_dispatch.gmm_restore(context, reg_ctx->gmm_state);
+ reg_ctx->gmm_state = NULL;
+ restored = 1;
+ }
+
+ /* restore previously saved state */
+
+ /*
+ * NAPA class seems to work much better all the display stuff is
+ * turned off prior to restoring the registers.
+ */
+ context->mod_dispatch.mode_reset_plane_pipe_ports(context);
+
+
+ reg_ctx->dispatch->reg_restore(context, reg_ctx->device_state,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_free(context, reg_ctx->device_state,
+ reg_ctx->dispatch->platform_context);
+
+ reg_ctx->device_state = reg_state;
+
+ /* Free GART bindings, if not already saved */
+ if (!restored && !reg_ctx->gmm_state &&
+ context->mod_dispatch.gmm_save) {
+ context->mod_dispatch.gmm_save(context, &(reg_ctx->gmm_state));
+ }
+
+ return 0;
+}
+
+/*!
+ * This function calls reg_save() to save the state of the register
+ *
+ * @param driver_handle our driver context
+ * @param flags specifies which states to save
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_driver_save(igd_driver_h driver_handle,
+ const unsigned long flags)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ reg_buffer_t *reg_state;
+ reg_buffer_t **reg_location = NULL;
+
+ EMGD_ASSERT(context, "Null driver_handle!\n", -IGD_ERROR_INVAL);
+
+ switch (flags & IGD_REG_SAVE_TYPE_MASK) {
+ case IGD_REG_SAVE_TYPE_REG:
+ reg_location = ®_ctx->device_state;
+ break;
+ case IGD_REG_SAVE_TYPE_CON:
+ reg_location = &console_state;
+ break;
+ case IGD_REG_SAVE_TYPE_MISC:
+ reg_location = &misc_state;
+ break;
+ default:
+ EMGD_ERROR("Called igd_driver_save without a valid save flag.");
+ return 0;
+ }
+
+ if (*reg_location) {
+ reg_ctx->dispatch->reg_free(context, *reg_location,
+ reg_ctx->dispatch->platform_context);
+ }
+
+ /* Save current state */
+ reg_state = reg_ctx->dispatch->reg_alloc(context, flags,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_save(context, reg_state,
+ reg_ctx->dispatch->platform_context);
+
+ *reg_location = reg_state;
+
+ /* Free GART bindings, if not already saved */
+ if ((flags & IGD_REG_SAVE_TYPE_REG) &&
+ !reg_ctx->gmm_state &&
+ context->mod_dispatch.gmm_save) {
+ context->mod_dispatch.gmm_save(context, &(reg_ctx->gmm_state));
+ }
+ return 0;
+}
+/* igd_driver_save */
+
+/*!
+ * This function calls reg_restore() to restore previously saved
+ *
+ * @param driver_handle our driver context
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+static int igd_driver_restore(igd_driver_h driver_handle,
+ const unsigned long flags)
+{
+ igd_context_t *context;
+ reg_buffer_t *reg_state = NULL;
+
+ EMGD_ASSERT(driver_handle, "Null driver_handle!\n", -IGD_ERROR_INVAL);
+
+ context = (igd_context_t *)driver_handle;
+ switch (flags & IGD_REG_SAVE_TYPE_MASK) {
+ case IGD_REG_SAVE_TYPE_REG:
+ reg_state = reg_ctx->device_state;
+ break;
+ case IGD_REG_SAVE_TYPE_CON:
+ reg_state = console_state;
+ break;
+ case IGD_REG_SAVE_TYPE_MISC:
+ reg_state = misc_state;
+ break;
+ default:
+ EMGD_ERROR("Not a valida restore flag specified.");
+ return 0;
+ }
+
+ /*
+ * NAPA class seems to work much better all the display stuff is
+ * turned off prior to restoring the registers.
+ * context->mod_dispatch.mode_reset_plane_pipe_ports(context);
+ */
+ context->mod_dispatch.mode_reset_plane_pipe_ports(context);
+
+ /* restore previously saved state */
+ if (reg_state) {
+ reg_ctx->dispatch->reg_restore(context, reg_state,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_free(context, reg_state,
+ reg_ctx->dispatch->platform_context);
+
+ /* Restore GART bindings, if saved */
+ if ((flags & IGD_REG_SAVE_TYPE_REG) &&
+ reg_ctx->gmm_state &&
+ context->mod_dispatch.gmm_restore) {
+ context->mod_dispatch.gmm_restore(context, reg_ctx->gmm_state);
+ reg_ctx->gmm_state = NULL;
+ }
+ } else {
+ EMGD_ERROR("Previous state was not saved, so can't restore.");
+ }
+
+ return 0;
+}
+
+/*!
+ *
+ * @param id
+ * @param state
+ * @param flags
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int reg_get_mod_state(reg_state_id_t id, module_state_h **state,
+ unsigned long **flags)
+{
+ if(!reg_ctx->device_state && !console_state) {
+ return 0;
+ }
+
+ switch(id) {
+ case REG_MODE_STATE_REG:
+ *flags = ®_ctx->device_state->flags;
+ if((**flags & IGD_REG_SAVE_MODE)){
+ *state = ®_ctx->device_state->mode_buffer;
+ } else {
+ state = NULL;
+ }
+ break;
+ case REG_MODE_STATE_CON:
+ *flags = &console_state->flags;
+ if((**flags & IGD_REG_SAVE_MODE)){
+ *state = &console_state->mode_buffer;
+ } else {
+ state = NULL;
+ }
+ break;
+ default:
+ state = NULL;
+ return -IGD_ERROR_INVAL;
+ }
+
+ return 0;
+}
+
+/*!
+ * Free any memory allocated for registry state info.
+ *
+ * @param context
+ *
+ * @return void
+ */
+void _reg_shutdown(igd_context_t *context)
+{
+ reg_buffer_t *restore_state;
+ EMGD_TRACE_ENTER;
+
+ if (!config_drm.init) {
+ restore_state = reg_ctx[0].device_state;
+ } else {
+ if (config_drm.kms) {
+ restore_state = console_state;
+ } else {
+ restore_state = console_state;
+ //restore_state = reg_ctx[0].device_state;
+ }
+ }
+
+ if(restore_state) {
+ context->mod_dispatch.mode_reset_plane_pipe_ports(context);
+
+ EMGD_DEBUG("Restoring register values prior to exit...");
+ reg_ctx->dispatch->reg_restore(context, restore_state,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_free(context, restore_state,
+ reg_ctx->dispatch->platform_context);
+
+ }
+ OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
+
+ EMGD_TRACE_EXIT;
+}
+
+/*!
+ * Initialize the registry state context for registry save
+ * /restore operations.
+ *
+ * @param context
+ * @param flags
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int _reg_init(igd_context_t *context, unsigned long flags)
+{
+ reg_dispatch_t *dispatch;
+
+ EMGD_TRACE_ENTER;
+
+ dispatch = (reg_dispatch_t *)dispatch_acquire(context, reg_dispatch_list);
+ if(!dispatch) {
+ return -IGD_ERROR_NODEV;
+ }
+
+ OS_MEMSET(reg_ctx, 0, sizeof(reg_context_t));
+
+ reg_ctx->dispatch = dispatch;
+
+ /*
+ * Hook up functions in dispatch table.
+ */
+ context->dispatch.driver_save_restore = igd_driver_save_restore;
+ context->dispatch.driver_save = igd_driver_save;
+ context->dispatch.driver_restore = igd_driver_restore;
+ context->mod_dispatch.reg_get_mod_state = reg_get_mod_state;
+ context->mod_dispatch.reg_alloc = reg_alloc;
+ context->mod_dispatch.reg_free = reg_free;
+ context->mod_dispatch.reg_save = reg_save;
+ context->mod_dispatch.reg_restore = reg_restore;
+ context->mod_dispatch.reg_shutdown = _reg_shutdown;
+ context->mod_dispatch.reg_crtc_lut_get = reg_crtc_lut_get;
+ context->mod_dispatch.reg_crtc_lut_set = reg_crtc_lut_set;
+
+ if(flags & IGD_DRIVER_SAVE_RESTORE) {
+ reg_ctx->flags |= IGD_DRIVER_SAVE_RESTORE;
+ EMGD_DEBUG("Saving Device State");
+
+ reg_ctx->device_state = reg_ctx->dispatch->reg_alloc(context,
+ IGD_REG_SAVE_STATE|IGD_REG_SAVE_MODE|IGD_REG_SAVE_TYPE_REG,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_save(context, reg_ctx->device_state,
+ reg_ctx->dispatch->platform_context);
+ }
+
+ if (config_drm.init) {
+ console_state = reg_ctx->dispatch->reg_alloc(context,
+ IGD_REG_SAVE_STATE|IGD_REG_SAVE_MODE|IGD_REG_SAVE_TYPE_CON,
+ reg_ctx->dispatch->platform_context);
+ reg_ctx->dispatch->reg_save(context, console_state,
+ reg_ctx->dispatch->platform_context);
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
new file mode 100644
index 0000000..985fa44
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
@@ -0,0 +1,73 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the implementation file for the register module's main API's called
+ * by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _REG_DISPATCH_H
+#define _REG_DISPATCH_H
+
+#include <context.h>
+#include <drm_emgd_private.h>
+
+typedef struct _reg_buffer {
+ unsigned long flags;
+ module_state_h mode_buffer;
+ void *platform_buffer;
+}reg_buffer_t;
+
+/*
+ * This needs to be available for inter-module use so that the
+ * mode module can save state during it's init which happens after
+ * the reg module init.
+ */
+typedef struct _reg_dispatch {
+ reg_buffer_t *(*reg_alloc)(igd_context_t *context, unsigned long flags,
+ void *_platform_context);
+ void (*reg_free)(igd_context_t *context, reg_buffer_t *reg_set,
+ void *_platform_context);
+ int (*reg_save)(igd_context_t *context, reg_buffer_t *reg_set,
+ void *_platform_context);
+ int (*reg_restore)(igd_context_t *context, reg_buffer_t *reg_set,
+ void *_platform_context);
+ void (*reg_crtc_lut_get)(igd_context_t *context, emgd_crtc_t *emgd_crtc);
+ void (*reg_crtc_lut_set)(igd_context_t *context, emgd_crtc_t *emgd_crtc);
+ void *platform_context;
+} reg_dispatch_t;
+
+/*
+ * Reg dispatch data structure is in reg.h because it and the reg context
+ * needs to be available for initial reg save during mode module init.
+ */
+
+
+extern reg_dispatch_t reg_dispatch_plb;
+extern reg_dispatch_t reg_dispatch_tnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c b/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
new file mode 100644
index 0000000..c865c36
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
@@ -0,0 +1,1157 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_plb.c
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the implementation file for the register module's main API's called
+ * by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+#include <pci.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <utils.h>
+#include <dsp.h>
+#include <mode.h>
+#include <utils.h>
+#include <vga.h>
+#include <intelpci.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/reg_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+#define PLANE_LATCH_COUNT 4
+
+#define RING_BUFFER 0
+#define MMIO_MISC 1
+
+static reg_buffer_t *reg_alloc_plb(igd_context_t *context,
+ unsigned long flags, void *_platform_context);
+static void reg_free_plb(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static int reg_save_plb(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static int reg_restore_plb(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static void reg_crtc_lut_get_plb(igd_context_t *context,
+ emgd_crtc_t *emgd_crtc);
+static void reg_crtc_lut_set_plb(igd_context_t *context,
+ emgd_crtc_t *emgd_crtc);
+
+/* GR registers being saved */
+static unsigned char gr_regs_plb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08,
+ 0x10, 0x11,
+ 0x18,
+ 0xff
+};
+#define GR_REG_COUNT sizeof(gr_regs_plb)
+
+/* SR registers being saved */
+static unsigned char sr_regs_plb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x07,
+ 0xff
+};
+#define SR_REG_COUNT sizeof(sr_regs_plb)
+
+/* AR registers being saved */
+static unsigned char ar_regs_plb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14,
+ 0xff,
+};
+#define AR_REG_COUNT sizeof(ar_regs_plb)
+
+/* CR registers being saved */
+static unsigned char cr_regs_plb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0xff
+};
+#define CR_REG_COUNT sizeof(cr_regs_plb)
+
+
+/* MMIO states register to be saved */
+static unsigned long mmio_regs_plb[] = {
+#if MMIO_MISC
+ /* Fence Registers */
+ FENCE0, FENCE1, FENCE2, FENCE3, FENCE4, FENCE5, FENCE6, FENCE7, // Fence
+ FENCE8, FENCE9, FENCE10, FENCE11, FENCE12, FENCE13, FENCE14, FENCE15,
+
+ /* GTT Control */
+ PGTBL_CTL,
+#endif
+
+ /* Memory Arbitration */
+ FW_BLC1, FW_BLC2, FW_BLC_SELF, MI_ARB_STATE, FW_BLC3, G_DEBUG,
+
+ /* Program Clocks */
+ VGA0_DIVISOR, VGA1_DIVISOR, VGA_PD,
+
+ FPA0, FPA1, FPB0, FPB1, P2D_CG_DIS, P3D_CG_DIS,
+
+ DPLLACNTR, DPLLBCNTR,
+
+ /* Enable Ports */
+ /* SDVO Port Enable */
+ SDVOCCNTR,
+ SDVOBCNTR,
+
+ /* Panel Power */
+ LVDS_PNL_PWR_CTL, PP_ON_DELAYS, PP_OFF_DELAYS, PP_DIVISOR,
+
+ /* Panel Fitting */
+ PFIT_CONTROL, PFIT_PGM_RATIOS, PFIT_AUTO_RATIOS, PFIT_INIT_PHASE,
+
+ /* Backlight Control */
+ BLC_PWM_CTL, BLM_HIST_CTL,
+
+ /* LVDS Port Enable */
+ LVDSCNTR,
+
+
+ /* Program Pipe A */
+ PIPEA_STAT, PIPEA_DISP_ARB_CTRL, HTOTAL_A, HBLANK_A, HSYNC_A, VTOTAL_A,
+ VBLANK_A, VSYNC_A, PIPEASRC, BCLRPAT_A,
+
+ /* Program Pipe B */
+ PIPEB_STAT, HTOTAL_B, HBLANK_B, HSYNC_B, VTOTAL_B,
+ VBLANK_B, VSYNC_B, PIPEBSRC, BCLRPAT_B,
+
+
+ /* Enable Pipes */
+ PIPEA_CONF, PIPEB_CONF,
+
+ /* Plane A */
+ DSPASTRIDE, DSPAKEYVAL, DSPAKEYMASK,
+
+ /* Plane B */
+ DSPBSTRIDE, DSPBPOS, DSPBSIZE, DSPBKEYVAL, DSPBKEYMASK,
+
+ /* Plane C */
+ DSPCSTRIDE, DSPCPOS, DSPCSIZE, DSPCKEYMASK,
+ DSPCKEYMINVAL, DSPCKEYMAXVAL, DCLRC0, DCLRC1, DPYC_GAMC5,
+ DPYC_GAMC4, DPYC_GAMC3, DPYC_GAMC2, DPYC_GAMC1, DPYC_GAMC0,
+
+ /* Enable Plane C */
+ DSPCCNTR, DSPCADDR,
+
+ /* Enable Plane B */
+ DSPBCNTR, DSPBADDR,
+
+ /* Enable Plane A */
+ DSPACNTR, DSPAADDR,
+
+ /* Enable VGA Plane */
+ VGACNTRL,
+
+ /* Software Flags A */
+ SWF00, SWF01, SWF02, SWF03, SWF04, SWF05, SWF06, SWF07,
+ SWF08, SWF09, SWF0A, SWF0B, SWF0C, SWF0D, SWF0E, SWF0F,
+
+ /* Software Flags B */
+ SWF10, SWF11, SWF12, SWF13, SWF14, SWF15, SWF16, SWF17,
+ SWF18, SWF19, SWF1A, SWF1B, SWF1C, SWF1D, SWF1E, SWF1F,
+
+ /* Cursor A */
+ CURSOR_A_BASE, CURSOR_A_POS, CURSOR_A_PAL0, CURSOR_A_PAL1,
+ CURSOR_A_PAL2, CURSOR_A_PAL3,
+
+ /* Cursor B */
+ CURSOR_B_BASE, CURSOR_B_POS, CURSOR_B_PAL0, CURSOR_B_PAL1,
+ CURSOR_B_PAL2, CURSOR_B_PAL3,
+
+ /* Interrupt and hardware status */
+ HWS_PGA, HWSTAM, SCPD0, IER, IMR, EIR, EMR,
+
+ 0xffffffff
+};
+#define MMIO_REG_COUNT(x) (sizeof(mmio_regs_plb)/4)
+
+typedef struct _reg_platform_context_plb {
+ unsigned long *mmio_regs;
+ unsigned char *ar;
+ unsigned char *cr;
+ unsigned char *sr;
+ unsigned char *gr;
+ unsigned long pipes;
+} reg_platform_context_plb_t;
+
+typedef struct _vga_state_plb {
+ unsigned char fcr; // Feature Control register
+ unsigned char msr; // Miscellaneous Output register
+ unsigned char sr_index; // Sequencer index register
+ unsigned char cr_index; // CRT Controller index register
+ unsigned char ar_index; // Attribute Controller index register
+ unsigned char gr_index; // Graphics Controller index register
+ unsigned char ar[AR_REG_COUNT]; // Attribute Contr regs (AR00-AR14)
+ unsigned char sr[SR_REG_COUNT]; // Sequencer registers (SR01-SR04)
+ unsigned char cr[CR_REG_COUNT]; // CRT Controller regs (CR00-CR18)
+ unsigned char gr[GR_REG_COUNT]; // Graphics Contr regs
+ unsigned char plane_latches[PLANE_LATCH_COUNT];
+} vga_state_plb_t;
+
+#define DAC_DATA_COUNT 256 /* 256 sets of (R, G, B) data */
+typedef struct _dac_state_plb {
+ unsigned long palette_a[DAC_DATA_COUNT]; /* Pipe A palette data */
+ unsigned long palette_b[DAC_DATA_COUNT]; /* Pipe B palette data */
+ unsigned char mode; // DAC state register
+ unsigned char index; // DAC index register
+ unsigned char mask; // 0x3C6, Palette Pixel Mask Register
+} dac_state_plb_t;
+
+/* Structure to store the 3D registers during power management
+ * These are 3D specific registers, but named as D3D because
+ * variabl names cannot start with a number*/
+typedef struct _d3d_state_plb {
+ unsigned long cin_ctl;
+ unsigned long bin_scene;
+ unsigned long bmp_buffer;
+ unsigned long bmp_get;
+ unsigned long bmp_put;
+} d3d_state_plb_t;
+
+typedef struct _reg_buffer_plb {
+ unsigned long *mmio_state;
+ //unsigned long mem_mode; /* Reg 0x20CC */
+ //unsigned long instpm; /* Reg 0x20C0 */
+ unsigned long gtt[128*1024]; /* PLB is 128 */
+ unsigned long sgx_phyaddr;
+ void *vga_mem;
+ vga_state_plb_t vga_state;
+ dac_state_plb_t dac_state;
+ d3d_state_plb_t d3d_state;
+ void *rb_state;
+ unsigned long clk_gating_ctl;
+ unsigned long pci_lbb;
+} reg_buffer_plb_t;
+
+static reg_platform_context_plb_t reg_platform_context_plb = {
+ mmio_regs_plb,
+ ar_regs_plb,
+ cr_regs_plb,
+ sr_regs_plb,
+ gr_regs_plb,
+ 2
+};
+
+reg_dispatch_t reg_dispatch_plb = {
+ reg_alloc_plb,
+ reg_free_plb,
+ reg_save_plb,
+ reg_restore_plb,
+ reg_crtc_lut_get_plb,
+ reg_crtc_lut_set_plb,
+ ®_platform_context_plb
+};
+
+/******************************************************************************
+ * Local Functions
+ *****************************************************************************/
+static int reg_save_gtt_plb(igd_context_t *context, unsigned char *mmio,
+ reg_buffer_plb_t *reg_args);
+static int reg_restore_gtt_plb(igd_context_t *context,
+ reg_buffer_plb_t *reg_args);
+
+/*!
+ * This procedure simply waits for the next vertical syncing (vertical retrace)
+ * period. If the display is already in a vertical syncing period, this
+ * procedure exits unlike "util_Wait_VSync_Start()" function that waits for
+ * the beginning of the next vertical sync period.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param context
+ *
+ * @return FALSE if timed out
+ * @return TRUE otherwise
+ */
+int reg_wait_vsync_plb(igd_context_t *context)
+{
+ unsigned long i = 0;
+ unsigned char *mmio;
+
+ mmio = context->device_context.virt_mmadr;
+
+ if ((EMGD_READ32(mmio + VP00) & BIT31)) {
+ return 1;
+ }
+
+ while ((i++ < 0x100000) && /* Check for timeout */
+ ((EMGD_READ8(mmio + STATUS_REG_01) & BIT3) == 0x00)) {
+ ;
+ }
+
+ if (i >= 0x100000) {
+ return 0;
+ }
+ return 1;
+}
+
+/*!
+ * Saves the current VGA register state of the video chipset into the
+ * given state buffer.
+ *
+ * This function first saves the 4 plane latches, and then it saves
+ * the SR, GR, AR, CR registers.
+ *
+ * @param context the current device context
+ * @param vga_buffer this is where the VGA register state is saved
+ * @param ar_regs AR registers to save
+ * @param cr_regs CR registers to save
+ * @param sr_regs SR registers to save
+ * @param gr_regs GR registers to save
+ *
+ * @return 0
+ */
+static int reg_save_vga_plb(
+ igd_context_t *context,
+ vga_state_plb_t *vga_buffer,
+ unsigned char *ar_regs,
+ unsigned char *cr_regs,
+ unsigned char *sr_regs,
+ unsigned char *gr_regs)
+{
+ unsigned char *mmio;
+ int i;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* First, save a few registers that will be modified to read the latches.
+ * We need to use GR04 to go through all the latches. Therefore, we must
+ * first save GR04 before continuing. However, GR04 will only behave the
+ * way we want it to if we are not in Odd/Even mode and not in Chain 4
+ * mode. Therefore, we have to make sure GR05 (GFX mode reg),
+ * and SR04 (Mem Mode reg) are set properly.
+ * According to B-spec, we are not supposed to program GR06 via MMIO.
+ */
+ READ_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]);
+ READ_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]); /* Memory Mode */
+ READ_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]); /* GFX Mode Reg */
+ READ_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]); /* Misc Reg */
+
+ WRITE_VGA(mmio, SR_PORT, SR04, 0x06);
+ WRITE_VGA(mmio, GR_PORT, GR05, 0x00);
+ WRITE_VGA(mmio, GR_PORT, GR06, 0x05);
+
+ /* Save Memory Latch Data latches */
+ for (i=0; i<PLANE_LATCH_COUNT; i++) {
+ WRITE_VGA(mmio, GR_PORT, GR04, (unsigned char)i);
+ READ_VGA(mmio, CR_PORT, CR22, vga_buffer->plane_latches[i]);
+ }
+
+ /* Restore the modified regs */
+ WRITE_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]);
+ WRITE_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]);
+ WRITE_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]);
+ WRITE_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]);
+
+
+ /* Save Feature Controller register. */
+ vga_buffer->fcr = EMGD_READ8(mmio + FEATURE_CONT_REG_READ);
+
+ /* Save Miscellaneous Output Register. */
+ vga_buffer->msr = EMGD_READ8(mmio + MSR_READ_PORT);
+
+ /* Save index registers. */
+ vga_buffer->sr_index = EMGD_READ8(mmio + SR_PORT);
+ vga_buffer->cr_index = EMGD_READ8(mmio + CR_PORT);
+ vga_buffer->gr_index = EMGD_READ8(mmio + GR_PORT);
+
+#if 0
+ /*
+ * Save the AR index register and last write status. Not sure that
+ * this is really necessary so skip it for now.
+ */
+ READ_VGA(mmio, CR_PORT, CR24, isARData); // Next write to AR index reg
+ isARData &= 0x80;
+
+ // Save AR index and last write status
+ vga_buffer->ar_index = EMGD_READ8(mmio + AR_PORT) | isARData;
+#endif
+
+ /* Save CRT Controller registers. */
+ for (i=0; cr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]);
+ }
+
+ /* Save Attribute Controller registers. */
+ for (i=0; ar_regs[i] != 0xff; i++) {
+ READ_AR(mmio, (unsigned char)i, vga_buffer->ar[i]);
+ }
+
+ /* Save Graphics Controller registers. */
+ for (i=0; gr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]);
+ }
+
+ /* Save Sequencer registers. */
+ for (i=0; sr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]);
+ }
+
+ return 0;
+}
+
+/*!
+ * Restore the VGA Register state from the specifed state buffer.
+ *
+ * @param context the current device context
+ * @param vga_buffer this is where the VGA register state is saved
+ * @param ar_regs AR registers to save
+ * @param cr_regs CR registers to save
+ * @param sr_regs SR registers to save
+ * @param gr_regs GR registers to save
+ *
+ * @return 0
+ */
+static int reg_restore_vga_plb(
+ igd_context_t *context,
+ vga_state_plb_t *vga_buffer,
+ unsigned char *ar_regs,
+ unsigned char *cr_regs,
+ unsigned char *sr_regs,
+ unsigned char *gr_regs)
+{
+ unsigned long i;
+ unsigned char *mmio;
+ unsigned long bit_mask;
+ mmio = context->device_context.virt_mmadr;
+
+ /* Restore the plane latches.
+ *
+ * BP: I don't understand what this block is doing and it doesn't
+ * seem necessary. Should check this against the spec and figure
+ * out what it really does.
+ */
+
+ /* Memory Mode Register */
+ WRITE_VGA(mmio, SR_PORT, SR04, 0x06);
+ /* GR05, Graphics Mode Register */
+ WRITE_VGA(mmio, GR_PORT, GR05, 0x00);
+ /* GR06, Micsellaneous Register */
+ WRITE_VGA(mmio, GR_PORT, GR06, 0x05);
+ /* GR08, Bit Mask Register */
+ WRITE_VGA(mmio, GR_PORT, GR08, 0xFF);
+
+ for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) {
+ /* Set plane select register */
+ WRITE_VGA(mmio, GR_PORT, GR04, i);
+ /* Plane/Map mask register */
+ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
+ }
+
+ for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) {
+ /* Plane/Map mask register again?? */
+ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
+ }
+
+ /* Restore standard VGA registers.
+ * 2) Sequence registers
+ * 1) MSR register
+ * 3) CRTC registers
+ * 4) Graphics registers
+ * 5) Attribute registers
+ * 6) VGA Feature register
+ * 7) Index restisters
+ */
+
+
+ WRITE_VGA(mmio, SR_PORT, SR00, 01); /* Do sync reset */
+
+ for (i=0; sr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]);
+ }
+
+
+ EMGD_WRITE8(vga_buffer->msr, mmio + MSR_PORT);
+ WRITE_VGA(mmio, SR_PORT, SR00, 0x03); /* Set to normal operation */
+
+ /* Unlock CRTC */
+ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] & 0x7F);
+ for (i=0; cr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]);
+ }
+
+ for (i=0; gr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]);
+ }
+
+ for (i=0; ar_regs[i] != 0xff; i++) {
+ WRITE_AR(mmio, ar_regs[i], vga_buffer->ar[i]);
+ }
+
+ EMGD_WRITE8(vga_buffer->fcr, mmio + FEATURE_CONT_REG);
+
+ /* Restore index registers. Is this necessary? */
+ EMGD_WRITE8(vga_buffer->sr_index, mmio + SR_PORT);
+ EMGD_WRITE8(vga_buffer->cr_index, mmio + CR_PORT);
+ EMGD_WRITE8(vga_buffer->gr_index, mmio + GR_PORT);
+
+ /* Lock CRTC */
+ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] | 0x80);
+
+ return 0;
+}
+
+/*!
+ * Saves the DAC registers and lookup table.
+ *
+ * @param context
+ * @param dac_state
+ * @param platform_context
+ *
+ * @return 0
+ */
+static int reg_save_dac_plb(
+ igd_context_t *context,
+ dac_state_plb_t *dac_state,
+ reg_platform_context_plb_t *platform_context)
+{
+ unsigned char *mmio;
+ int i;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Save DACMASK register */
+ dac_state->mask = EMGD_READ8(mmio + DAC_PEL_MASK);
+
+ /* Save DAC State register */
+ dac_state->mode = EMGD_READ8(mmio + DAC_STATE);
+
+ /* Save DAC Index register */
+ dac_state->index = EMGD_READ8(mmio + DAC_WRITE_INDEX);
+
+ /*
+ * Save DAC data
+ * Start from first DAC location
+ */
+ EMGD_WRITE8(0, mmio + DAC_WRITE_INDEX);
+
+ /* Save Pipe A Palette */
+ /* Or if Pipe A is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC))) ||
+ ((!(EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ (!(EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ dac_state->palette_a[i] = EMGD_READ32(mmio + i*4 + DPALETTE_A);
+ }
+ }
+
+ if (platform_context->pipes == 2) {
+ /* If Pipe B is enabled, save Pipe B Palette */
+ /* Or if Pipe B is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ ((EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ dac_state->palette_b[i] = EMGD_READ32(mmio + i*4 + DPALETTE_B);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void reg_crtc_lut_set_plb(
+ igd_context_t *context,
+ emgd_crtc_t *emgd_crtc)
+{
+ int i;
+ unsigned long pal_reg;
+ unsigned char *mmio;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = context->device_context.virt_mmadr;
+
+ if (emgd_crtc->crtc_id == 0) {
+ /* If Pipe is enabled, restore Palette */
+ if ((emgd_crtc->crtc_id == 0 &&
+ ((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC)))) ||
+ (emgd_crtc->crtc_id == 1 &&
+ ((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))))) {
+
+ pal_reg = (unsigned long)(mmio + DPALETTE_A +
+ (emgd_crtc->crtc_id * (DPALETTE_B - DPALETTE_A)));
+
+ /* Restore Pipe A Palette */
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32((emgd_crtc->lut_r[i] << 16) |
+ (emgd_crtc->lut_g[i] << 8) |
+ emgd_crtc->lut_b[i],
+ pal_reg + i*4);
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+static void reg_crtc_lut_get_plb(
+ igd_context_t *context,
+ emgd_crtc_t *emgd_crtc)
+{
+ int i;
+ unsigned long pal_reg;
+ unsigned char *mmio;
+ unsigned long lut_value;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = context->device_context.virt_mmadr;
+
+ if (emgd_crtc->crtc_id == 0) {
+ /* If Pipe is enabled, restore Palette */
+ if ((emgd_crtc->crtc_id == 0 &&
+ ((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC)))) ||
+ (emgd_crtc->crtc_id == 1 &&
+ ((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))))) {
+
+ pal_reg = (unsigned long)(mmio + DPALETTE_A +
+ (emgd_crtc->crtc_id * (DPALETTE_B - DPALETTE_A)));
+
+ /* Restore Pipe A Palette */
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ lut_value = EMGD_READ32(pal_reg + i*4);
+ emgd_crtc->lut_r[i] = (lut_value & 0xFF0000) >> 16;
+ emgd_crtc->lut_g[i] = (lut_value & 0x00FF00) >> 8;
+ emgd_crtc->lut_b[i] = (lut_value & 0x0000FF);
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/*!
+ * Restore previously saved DAC palette from the specifed state buffer.
+ *
+ * @param context
+ * @param dac_state
+ * @param platform_context
+ *
+ * @return 0
+ */
+static int reg_restore_dac_plb(
+ igd_context_t *context,
+ dac_state_plb_t *dac_state,
+ reg_platform_context_plb_t *platform_context)
+{
+ int i;
+ unsigned char *mmio;
+ unsigned char temp;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* If Pipe A is enabled, restore Palette */
+ /* Or if Pipe A is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ (! (EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ /*
+ * Restore DAC data
+ * Start from first DAC location
+ */
+ EMGD_WRITE8(0, mmio + DAC_WRITE_INDEX);
+
+ /* Restore Pipe A Palette */
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32(dac_state->palette_a[i], mmio + i*4 + DPALETTE_A);
+ }
+ }
+
+ /* If this is a single pipe device. */
+ if (platform_context->pipes == 2) {
+ /* If Pipe B is enabled, restore Palette */
+ /* Or if Pipe B is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ ((EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32(dac_state->palette_b[i], mmio + i*4 + DPALETTE_B);
+ }
+ }
+ }
+
+ /* Restore DACMASK register */
+ EMGD_WRITE8(dac_state->mask, mmio + DAC_PEL_MASK);
+
+ /* Restore DAC Index register */
+ if (dac_state->mode & 1) { /* Last write was to "write index register" */
+ EMGD_WRITE8(dac_state->index, mmio + DAC_WRITE_INDEX);
+ } else { /* Last index write was to "read index register" */
+ EMGD_WRITE8(dac_state->index - 1, mmio + DAC_READ_INDEX);
+
+ /* Dummy read to set DACSTATE register and to increment read index to
+ * last saved.
+ */
+ temp = EMGD_READ8(mmio + DAC_DATA_REG);
+ }
+
+ return 0;
+}
+
+/*!
+ * Initializes memory to store register values
+ *
+ * @param context pointer to igd_context
+ * @param flags indicate which register type to save
+ * @param _platform_context
+ *
+ * @return pointer to structure which will eventually be saved data defining
+ * register state
+ * @return NULL on failure
+ */
+static reg_buffer_t *reg_alloc_plb(igd_context_t *context,
+ unsigned long flags,
+ void *_platform_context)
+{
+ reg_buffer_plb_t* reg_args;
+ reg_buffer_t *reg_buffer;
+
+ EMGD_DEBUG("Entry - reg_alloc");
+
+ reg_buffer = (reg_buffer_t*)OS_ALLOC(sizeof(reg_buffer_t));
+ if (reg_buffer == NULL) {
+ return NULL;
+ }
+
+ reg_args = (reg_buffer_plb_t*)OS_ALLOC(sizeof(reg_buffer_plb_t));
+ if (reg_args == NULL) {
+ OS_FREE(reg_buffer);
+ return NULL;
+ }
+ reg_buffer->mode_buffer = NULL;
+ reg_buffer->platform_buffer = reg_args;
+
+ OS_MEMSET(reg_args, 0, sizeof(reg_buffer_plb_t));
+ reg_buffer->flags = flags;
+
+ reg_args->mmio_state = (void *)OS_ALLOC(sizeof(mmio_regs_plb));
+
+ if (!reg_args->mmio_state) {
+ EMGD_DEBUG("Failed Allocating mmio memory");
+ OS_FREE(reg_buffer);
+ OS_FREE(reg_args);
+ return NULL;
+ }
+
+ return reg_buffer;
+}
+
+/*!
+ * This function calculates the size of memory to store data
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0
+ */
+static void reg_free_plb(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_plb_t* reg_args;
+
+ EMGD_DEBUG("Entry - reg_free");
+
+ if (reg_buffer) {
+ reg_args = (reg_buffer_plb_t*)reg_buffer->platform_buffer;
+
+ if (reg_args) {
+ if (NULL != reg_args->mmio_state) {
+ OS_FREE(reg_args->mmio_state);
+ }
+
+ if (NULL != reg_args->vga_mem) {
+ OS_FREE(reg_args->vga_mem);
+ }
+
+ if (NULL != reg_args->rb_state) {
+ OS_FREE(reg_args->rb_state);
+ }
+ OS_FREE(reg_args);
+ }
+ OS_FREE(reg_buffer);
+ }
+
+ return;
+}
+
+/*!
+ * This functions save the regs
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_save_plb(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_plb_t *reg_args;
+ unsigned long *buffer;
+ reg_platform_context_plb_t *reg_platform_context =
+ (reg_platform_context_plb_t *)_platform_context;
+ int i;
+ unsigned char *mmio;
+ platform_context_plb_t *platform_context;
+ platform_context = (platform_context_plb_t *)context->platform_context;
+
+
+ EMGD_TRACE_ENTER;
+
+ if (reg_buffer == NULL) {
+ return 0;
+ }
+
+ /* Before save need to idle the ring buffer */
+ context->dispatch.idle((igd_driver_h)context);
+
+ reg_args = (reg_buffer_plb_t *)reg_buffer->platform_buffer;
+ if (reg_args == NULL) {
+ return 0;
+ }
+
+ mmio = context->device_context.virt_mmadr;
+
+
+ /* Save vga registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+ EMGD_DEBUG("Saving VGA registers");
+ reg_save_vga_plb(context, ®_args->vga_state,
+ reg_platform_context->ar, reg_platform_context->cr, reg_platform_context->sr,
+ reg_platform_context->gr);
+ }
+
+ /* Save VGA memory */
+#if 0
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA_MEM) {
+ EMGD_DEBUG("Saving VGA memory");
+ if (!reg_args->vga_mem) {
+ reg_args->vga_mem = (void *)OS_ALLOC_LARGE(64 * 1024);
+ if (reg_args->vga_mem != NULL) {
+ OS_MEMCPY(reg_args->vga_mem,
+ (void *)context->device_context.virt_fb_adr, 64*1024);
+ } else {
+ EMGD_ERROR("Unable to allocate memory for vga memory");
+ }
+ } else {
+ OS_MEMCPY(reg_args->vga_mem,
+ (void *)context->device_context.virt_fb_adr, 64*1024);
+ }
+ }
+#endif
+
+ /* Save mmio registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_MMIO) {
+ EMGD_DEBUG("Saving MMIO registers");
+ buffer = reg_args->mmio_state;
+ for (i=0; reg_platform_context->mmio_regs[i] != 0xffffffff; i++) {
+ *buffer++ = EMGD_READ32(mmio + reg_platform_context->mmio_regs[i]);
+ }
+
+ if (reg_buffer->flags & IGD_REG_SAVE_GTT) {
+ reg_save_gtt_plb(context, mmio, reg_args);
+ }
+ }
+
+ /* Save DAC registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_DAC) {
+ EMGD_DEBUG("Saving DAC registers");
+ reg_save_dac_plb(context, ®_args->dac_state, reg_platform_context);
+ }
+
+ /* Save Mode state */
+ if(reg_buffer->flags & IGD_REG_SAVE_MODE) {
+ EMGD_DEBUG("Saving mode state");
+ /* At driver initialization though mode_save is requested, mode isn't
+ * initialized. So skip the mode_save if dispatch function isn't
+ * available. In this case, mode_save() will be done as part of
+ * mode_init(). */
+ if (context->mod_dispatch.mode_save && !reg_buffer->mode_buffer) {
+ context->mod_dispatch.mode_save(context,
+ ®_buffer->mode_buffer,
+ ®_buffer->flags);
+ } else {
+ EMGD_DEBUG("mode_save() is skipped as mode_init() isn't done.");
+ }
+ }
+
+ /* Save the SGX clock gating settings */
+ reg_args->clk_gating_ctl = EMGD_READ32(mmio + PSB_CR_CLKGATECTL);
+
+ /* Save the PCI Config Legacy Backlight Brightness Register */
+ if(OS_PCI_READ_CONFIG_32(
+ platform_context->pcidev0, 0xF4, ®_args->pci_lbb)) {
+ EMGD_DEBUG("Reading Legacy Backlight Brightness");
+ }
+
+ return 0;
+} /* reg_save */
+
+/*!
+ * This function restores the regs states
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+int reg_restore_plb(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_plb_t* reg_args;
+ reg_platform_context_plb_t *reg_platform_context =
+ (reg_platform_context_plb_t *)_platform_context;
+ unsigned char *mmio;
+ unsigned long *buffer;
+ int i;
+ unsigned long lbb;
+ platform_context_plb_t *platform_context;
+ platform_context = (platform_context_plb_t *)context->platform_context;
+
+ EMGD_DEBUG("Entry - reg_restore");
+
+ if (reg_buffer == NULL) {
+ return 0;
+ }
+
+ reg_args = (reg_buffer_plb_t *)reg_buffer->platform_buffer;
+ if (reg_args == NULL) {
+ return 0;
+ }
+
+ EMGD_DEBUG(" flags = 0x%lx", reg_buffer->flags);
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Restore Mode state */
+ if (reg_buffer->flags & IGD_REG_SAVE_MODE) {
+ if (reg_buffer->mode_buffer) {
+ context->mod_dispatch.mode_restore(context,
+ ®_buffer->mode_buffer,
+ ®_buffer->flags);
+ } else {
+ EMGD_DEBUG("mode_restore() already happened in mode_shutdown().");
+ }
+ }
+
+ /* Restore MMIO registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_MMIO) {
+ EMGD_DEBUG("Restoring MMIO registers");
+ buffer = reg_args->mmio_state;
+ for (i=0; reg_platform_context->mmio_regs[i] != 0xffffffff; i++) {
+ if (reg_platform_context->mmio_regs[i] == MI_ARB_STATE) {
+ EMGD_DEBUG("Handle special masked register case");
+ EMGD_WRITE32(0x04100000 | *buffer++, mmio +
+ reg_platform_context->mmio_regs[i]);
+ } else if (reg_platform_context->mmio_regs[i] == DPLLACNTR ||
+ reg_platform_context->mmio_regs[i] == DPLLBCNTR) {
+
+ EMGD_DEBUG("Handle special DPLL settling");
+ EMGD_WRITE32(*buffer++,
+ mmio + reg_platform_context->mmio_regs[i]);
+ OS_SLEEP(150);
+ } else {
+ EMGD_WRITE32(*buffer++, mmio + reg_platform_context->mmio_regs[i]);
+ }
+ }
+
+ if (reg_buffer->flags & IGD_REG_SAVE_GTT) {
+ reg_restore_gtt_plb(context, reg_args);
+ }
+ }
+
+#if 0
+ /* Restore VGA memory */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA_MEM) {
+ if (reg_args->vga_mem) {
+ OS_MEMCPY((void *)context->device_context.virt_fb_adr,
+ reg_args->vga_mem, 64*1024);
+ } else {
+ EMGD_ERROR("Trying to restore NULL VGA memory");
+ }
+ }
+#endif
+
+ /* Restore DAC registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_DAC) {
+ reg_restore_dac_plb(context, ®_args->dac_state, reg_platform_context);
+ }
+
+ /* Restore VGA registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+ reg_restore_vga_plb(context, ®_args->vga_state,
+ reg_platform_context->ar, reg_platform_context->cr, reg_platform_context->sr,
+ reg_platform_context->gr);
+ }
+
+ /* Restore the SGX clock gating settings */
+ EMGD_WRITE32(reg_args->clk_gating_ctl, mmio + PSB_CR_CLKGATECTL);
+
+ /* restore the Legacy Backlight Brightness register. This register
+ * will be 0 when returning from power management causing backlight to be
+ * off if the register is not saved and restored during power management
+ */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0, 0xF4, &lbb)) {
+ EMGD_ERROR("Reading Legacy Backlight Brightness");
+ }
+
+ /* only of the LBB has no value, causing the backlight to be off, we restore
+ * the saved LBB value. This is just in case there are user applications
+ * or firmware setting this register before the driver restores */
+ if(!(lbb & 0xFF)){
+ if(OS_PCI_WRITE_CONFIG_32(platform_context->pcidev0,
+ 0xF4, (lbb | reg_args->pci_lbb))){
+ EMGD_ERROR("Writing into Legacy Backlight Brightness");
+ }
+ }
+ return 0;
+}
+
+/*!
+ * This function saves the GTT table entries into a buffer so that the GTT
+ * can be restored later.
+ *
+ * @param context needs this to get the GTT table size and to get the
+ * virtual address to the GTT table
+ * @param mmio virtual address to MMIO
+ * @param reg_args a pre-allocated context where GTT entries are saved
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_save_gtt_plb(igd_context_t *context, unsigned char *mmio,
+ reg_buffer_plb_t *reg_args)
+{
+ unsigned int i;
+
+ /* Read the GTT entries from GTT ADR and save it in the array. */
+ for (i = 0; i < (context->device_context.gatt_pages); i++) {
+ reg_args->gtt[i] = EMGD_READ32(
+ context->device_context.virt_gttadr + i);
+ }
+
+ reg_args->sgx_phyaddr = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+
+ return 0;
+}
+
+/*!
+ * This function restores the GTT table entries.
+ *
+ * @param context the context contains the GTT size and address
+ * @param reg_args this has the saved GTT entries
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_restore_gtt_plb(igd_context_t *context,
+ reg_buffer_plb_t *reg_args)
+{
+ unsigned int i;
+ unsigned char *mmio;
+ unsigned long sgx_mmu;
+
+ /* If the first element is 0, then nothing was saved */
+ if (0 == reg_args->gtt[0]) {
+ return 0;
+ }
+
+ /* Restore the GTT entries */
+ for (i=0; i < context->device_context.gatt_pages; i++) {
+ EMGD_WRITE32(reg_args->gtt[i],
+ context->device_context.virt_gttadr + i);
+ }
+
+ mmio = context->device_context.virt_mmadr;
+
+ /*
+ * FIXME: This is probably not necessary and may be incorrect
+ */
+ /* Invalidate directory cache */
+ sgx_mmu = EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+ sgx_mmu |= 0x1E;
+ EMGD_WRITE32(sgx_mmu, mmio + PSB_CR_BIF_CTRL);
+ EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+
+ EMGD_WRITE32(reg_args->sgx_phyaddr, mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+ EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+
+ /* Turn on host access to aperture via the MMU */
+ sgx_mmu = EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+ sgx_mmu &= 0xFFFF0000;
+ EMGD_WRITE32(sgx_mmu, mmio + PSB_CR_BIF_CTRL);
+ EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c b/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
new file mode 100644
index 0000000..10028ed
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
@@ -0,0 +1,1206 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_tnc.c
+ * $Revision: 1.19 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the implementation file for the register module's main API's called
+ * by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+#include <pci.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <utils.h>
+#include <dsp.h>
+#include <mode.h>
+#include <utils.h>
+#include <vga.h>
+#include <intelpci.h>
+
+#include <tnc/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/reg_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+#define PLANE_LATCH_COUNT 4
+
+#define RING_BUFFER 0
+#define MMIO_MISC 1
+
+static reg_buffer_t *reg_alloc_tnc(igd_context_t *context,
+ unsigned long flags, void *_platform_context);
+static void reg_free_tnc(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static int reg_save_tnc(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static int reg_restore_tnc(igd_context_t *context, reg_buffer_t *reg_buffer,
+ void *_platform_context);
+static void reg_crtc_lut_get_tnc(igd_context_t *context,
+ emgd_crtc_t *emgd_crtc);
+static void reg_crtc_lut_set_tnc(igd_context_t *context,
+ emgd_crtc_t *emgd_crtc);
+
+/* GR registers being saved */
+static unsigned char gr_regs_tnc[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08,
+ 0x10, 0x11,
+ 0x18,
+ 0xff
+};
+#define GR_REG_COUNT sizeof(gr_regs_tnc)
+
+/* SR registers being saved */
+static unsigned char sr_regs_tnc[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x07,
+ 0xff
+};
+#define SR_REG_COUNT sizeof(sr_regs_tnc)
+
+/* AR registers being saved */
+static unsigned char ar_regs_tnc[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14,
+ 0xff,
+};
+#define AR_REG_COUNT sizeof(ar_regs_tnc)
+
+/* CR registers being saved */
+static unsigned char cr_regs_tnc[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0xff
+};
+#define CR_REG_COUNT sizeof(cr_regs_tnc)
+
+
+/* MMIO states register to be saved */
+static unsigned long mmio_regs_tnc[] = {
+#if MMIO_MISC
+ /* Fence Registers */
+ FENCE0, FENCE1, FENCE2, FENCE3, FENCE4, FENCE5, FENCE6, FENCE7, // Fence
+ FENCE8, FENCE9, FENCE10, FENCE11, FENCE12, FENCE13, FENCE14, FENCE15,
+
+ /* GTT Control */
+ PGTBL_CTL,
+#endif
+
+ /* Memory Arbitration */
+ FW_BLC_SELF, MI_ARB_STATE, G_DEBUG,
+
+ /* Program Clocks */
+ VGA0_DIVISOR, VGA1_DIVISOR, VGA_PD,
+
+ FPA0, FPA1, FPB0, FPB1, P2D_CG_DIS,
+
+ DPLLACNTR, DPLLBCNTR,
+
+ /* Enable Ports */
+ /* SDVO Port Enable */
+ SDVOBCNTR,
+
+ /* Panel Power */
+ LVDS_PNL_PWR_CTL, PP_ON_DELAYS, PP_OFF_DELAYS, PP_DIVISOR,
+
+ /* Panel Fitting */
+ PFIT_CONTROL, PFIT_PGM_RATIOS,
+
+ /* Backlight Control */
+ BLC_PWM_CTL2, BLC_PWM_CTL, BLM_HIST_CTL,
+
+ /* LVDS Port Enable */
+ LVDSCNTR,
+
+ /* Program Pipe A */
+ PIPEA_STAT, PIPEA_DISP_ARB_CTRL, HTOTAL_A, HBLANK_A, HSYNC_A, VTOTAL_A,
+ VBLANK_A, VSYNC_A, PIPEASRC, BCLRPAT_A,
+
+ /* Program Pipe B */
+ PIPEB_STAT, HTOTAL_B, HBLANK_B, HSYNC_B, VTOTAL_B,
+ VBLANK_B, VSYNC_B, PIPEBSRC, BCLRPAT_B,
+
+
+ /* Enable Pipes */
+ PIPEA_CONF, PIPEB_CONF,
+
+ /* Plane A */
+ DSPASTRIDE, DSPAKEYVAL, DSPAKEYMASK,
+
+ /* Plane B */
+ DSPBSTRIDE, DSPBKEYVAL, DSPBKEYMASK,
+
+ /* Plane C */
+ DSPCSTRIDE, DSPCPOS, DSPCSIZE, DSPCKEYMASK,
+ DSPCKEYMINVAL, DSPCKEYMAXVAL, DCLRC0, DCLRC1, DPYC_GAMC5,
+ DPYC_GAMC4, DPYC_GAMC3, DPYC_GAMC2, DPYC_GAMC1, DPYC_GAMC0,
+
+ /* Enable Plane C */
+ DSPCCNTR, DSPCLINOFF, DSPCSURF,
+
+ /* Enable Plane B */
+ DSPBCNTR, DSPBLINOFF, DSPBSURF,
+
+ /* Enable Plane A */
+ DSPACNTR, DSPALINOFF, DSPASURF,
+
+ /* Enable VGA Plane */
+ VGACNTRL,
+
+ /* Software Flags A */
+ SWF00, SWF01, SWF02, SWF03, SWF04, SWF05, SWF06, SWF07,
+ SWF08, SWF09, SWF0A, SWF0B, SWF0C, SWF0D, SWF0E, SWF0F,
+
+ /* Software Flags B */
+ SWF10, SWF11, SWF12, SWF13, SWF14, SWF15, SWF16, SWF17,
+ SWF18, SWF19, SWF1A, SWF1B, SWF1C, SWF1D, SWF1E, SWF1F,
+
+ /* Cursor A */
+ CURSOR_A_BASE, CURSOR_A_POS, CURSOR_A_PAL0, CURSOR_A_PAL1,
+ CURSOR_A_PAL2, CURSOR_A_PAL3,
+
+ /* Cursor B */
+ CURSOR_B_BASE, CURSOR_B_POS, CURSOR_B_PAL0, CURSOR_B_PAL1,
+ CURSOR_B_PAL2, CURSOR_B_PAL3,
+
+ /* Interrupt and hardware status */
+ HWS_PGA, HWSTAM, SCPD0, IER, IMR, EIR, EMR,
+
+ 0xffffffff
+};
+#define MMIO_REG_COUNT(x) (sizeof(mmio_regs_tnc)/4)
+
+/* MMIO states register to be saved */
+static unsigned long mmio_regs_sdvo_tnc[] = {
+
+ /* Program Clocks */
+ VGA0_DIVISOR,
+
+ SDVO_BUFF_CTRL_REG,
+
+ FPB0, P2D_CG_DIS,
+
+ DPLLBCNTR,
+
+ /* Enable Ports */
+ /* SDVO Port Enable */
+ SDVOBCNTR,
+
+ /* Program Pipe B */
+ PIPEB_STAT, HTOTAL_B, HBLANK_B, HSYNC_B, VTOTAL_B,
+ VBLANK_B, VSYNC_B, PIPEBSRC, BCLRPAT_B, PROG_STALL,
+
+ /* CDVO */
+ /* CDVO_CTRL,*/
+ CDVO_SLEW_RATE, CDVO_STRENGTH, CDVO_RCOMP_UPDATE,
+
+ /* TNC_SDVORAM */
+ DPLL_ANACORE_CTRL, DPLL_MISC, DPLL_MONITOR, DPLL_MONITOR2,
+ DPLL_TEST_COMPARATOR,
+
+ /* Enable Pipes */
+ PIPEB_CONF,
+
+ /* Interrupt and hardware status */
+ IER, IMR,
+
+ 0xffffffff
+};
+#define MMIO_REG_SDVO_COUNT(x) (sizeof(mmio_regs_sdvo_tnc)/4)
+
+typedef struct _reg_platform_context_tnc {
+ unsigned long *mmio_regs;
+ unsigned long *mmio_regs_sdvo;
+ unsigned char *ar;
+ unsigned char *cr;
+ unsigned char *sr;
+ unsigned char *gr;
+ unsigned long pipes;
+} reg_platform_context_tnc_t;
+
+typedef struct _vga_state_tnc {
+ unsigned char fcr; // Feature Control register
+ unsigned char msr; // Miscellaneous Output register
+ unsigned char sr_index; // Sequencer index register
+ unsigned char cr_index; // CRT Controller index register
+ unsigned char ar_index; // Attribute Controller index register
+ unsigned char gr_index; // Graphics Controller index register
+ unsigned char ar[AR_REG_COUNT]; // Attribute Contr regs (AR00-AR14)
+ unsigned char sr[SR_REG_COUNT]; // Sequencer registers (SR01-SR04)
+ unsigned char cr[CR_REG_COUNT]; // CRT Controller regs (CR00-CR18)
+ unsigned char gr[GR_REG_COUNT]; // Graphics Contr regs
+ unsigned char plane_latches[PLANE_LATCH_COUNT];
+} vga_state_tnc_t;
+
+#define DAC_DATA_COUNT 256 /* 256 sets of (R, G, B) data */
+typedef struct _dac_state_tnc {
+ unsigned long palette_a[DAC_DATA_COUNT]; /* Pipe A palette data */
+ unsigned long palette_b[DAC_DATA_COUNT]; /* Pipe B palette data */
+ unsigned char mode; // DAC state register
+ unsigned char index; // DAC index register
+ unsigned char mask; // 0x3C6, Palette Pixel Mask Register
+} dac_state_tnc_t;
+
+/* Structure to store the 3D registers during power management
+ * These are 3D specific registers, but named as D3D because
+ * variabl names cannot start with a number*/
+typedef struct _d3d_state_tnc {
+ unsigned long cin_ctl;
+ unsigned long bin_scene;
+ unsigned long bmp_buffer;
+ unsigned long bmp_get;
+ unsigned long bmp_put;
+} d3d_state_tnc_t;
+
+typedef struct _reg_buffer_tnc {
+ unsigned long *mmio_state;
+ unsigned long *mmio_state_sdvo;
+ //unsigned long mem_mode; /* Reg 0x20CC */
+ //unsigned long instpm; /* Reg 0x20C0 */
+ unsigned long gtt[128*1024]; /* PLB is 128 */
+ void *vga_mem;
+ vga_state_tnc_t vga_state;
+ dac_state_tnc_t dac_state;
+ d3d_state_tnc_t d3d_state;
+ void *rb_state;
+ unsigned long pci_lbb;
+} reg_buffer_tnc_t;
+
+static reg_platform_context_tnc_t reg_platform_context_tnc = {
+ mmio_regs_tnc,
+ mmio_regs_sdvo_tnc,
+ ar_regs_tnc,
+ cr_regs_tnc,
+ sr_regs_tnc,
+ gr_regs_tnc,
+ 2
+};
+
+reg_dispatch_t reg_dispatch_tnc = {
+ reg_alloc_tnc,
+ reg_free_tnc,
+ reg_save_tnc,
+ reg_restore_tnc,
+ reg_crtc_lut_get_tnc,
+ reg_crtc_lut_set_tnc,
+ ®_platform_context_tnc
+};
+
+/******************************************************************************
+ * Local Functions
+ *****************************************************************************/
+static int reg_save_gtt_tnc(igd_context_t *context, unsigned char *mmio,
+ reg_buffer_tnc_t *reg_args);
+static int reg_restore_gtt_tnc(igd_context_t *context,
+ reg_buffer_tnc_t *reg_args);
+
+/*!
+ * This procedure simply waits for the next vertical syncing (vertical retrace)
+ * period. If the display is already in a vertical syncing period, this
+ * procedure exits unlike "util_Wait_VSync_Start()" function that waits for
+ * the beginning of the next vertical sync period.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param context
+ *
+ * @return FALSE if timed out
+ * @return TRUE otherwise
+ */
+int reg_wait_vsync_tnc(igd_context_t *context)
+{
+ unsigned long i = 0;
+ unsigned char *mmio;
+
+ mmio = context->device_context.virt_mmadr;
+
+ if ((EMGD_READ32(mmio + VP00) & BIT31)) {
+ return 1;
+ }
+
+ while ((i++ < 0x100000) && /* Check for timeout */
+ ((EMGD_READ8(mmio + STATUS_REG_01) & BIT3) == 0x00)) {
+ ;
+ }
+
+ if (i >= 0x100000) {
+ return 0;
+ }
+ return 1;
+}
+
+/*!
+ * Saves the current VGA register state of the video chipset into the
+ * given state buffer.
+ *
+ * This function first saves the 4 plane latches, and then it saves
+ * the SR, GR, AR, CR registers.
+ *
+ * @param context the current device context
+ * @param vga_buffer this is where the VGA register state is saved
+ * @param ar_regs AR registers to save
+ * @param cr_regs CR registers to save
+ * @param sr_regs SR registers to save
+ * @param gr_regs GR registers to save
+ *
+ * @return 0
+ */
+static int reg_save_vga_tnc(
+ igd_context_t *context,
+ vga_state_tnc_t *vga_buffer,
+ unsigned char *ar_regs,
+ unsigned char *cr_regs,
+ unsigned char *sr_regs,
+ unsigned char *gr_regs)
+{
+ unsigned char *mmio;
+ int i;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* First, save a few registers that will be modified to read the latches.
+ * We need to use GR04 to go through all the latches. Therefore, we must
+ * first save GR04 before continuing. However, GR04 will only behave the
+ * way we want it to if we are not in Odd/Even mode and not in Chain 4
+ * mode. Therefore, we have to make sure GR05 (GFX mode reg),
+ * and SR04 (Mem Mode reg) are set properly.
+ * According to B-spec, we are not supposed to program GR06 via MMIO.
+ */
+ READ_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]);
+ READ_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]); /* Memory Mode */
+ READ_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]); /* GFX Mode Reg */
+ READ_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]); /* Misc Reg */
+
+ WRITE_VGA(mmio, SR_PORT, SR04, 0x06);
+ WRITE_VGA(mmio, GR_PORT, GR05, 0x00);
+ WRITE_VGA(mmio, GR_PORT, GR06, 0x05);
+
+ /* Save Memory Latch Data latches */
+ for (i=0; i<PLANE_LATCH_COUNT; i++) {
+ WRITE_VGA(mmio, GR_PORT, GR04, (unsigned char)i);
+ READ_VGA(mmio, CR_PORT, CR22, vga_buffer->plane_latches[i]);
+ }
+
+ /* Restore the modified regs */
+ WRITE_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]);
+ WRITE_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]);
+ WRITE_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]);
+ WRITE_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]);
+
+
+ /* Save Feature Controller register. */
+ vga_buffer->fcr = EMGD_READ8(mmio + FEATURE_CONT_REG_READ);
+
+ /* Save Miscellaneous Output Register. */
+ vga_buffer->msr = EMGD_READ8(mmio + MSR_READ_PORT);
+
+ /* Save index registers. */
+ vga_buffer->sr_index = EMGD_READ8(mmio + SR_PORT);
+ vga_buffer->cr_index = EMGD_READ8(mmio + CR_PORT);
+ vga_buffer->gr_index = EMGD_READ8(mmio + GR_PORT);
+
+#if 0
+ /*
+ * Save the AR index register and last write status. Not sure that
+ * this is really necessary so skip it for now.
+ */
+ READ_VGA(mmio, CR_PORT, CR24, isARData); // Next write to AR index reg
+ isARData &= 0x80;
+
+ // Save AR index and last write status
+ vga_buffer->ar_index = EMGD_READ8(mmio + AR_PORT) | isARData;
+#endif
+
+ /* Save CRT Controller registers. */
+ for (i=0; cr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]);
+ }
+
+ /* Save Attribute Controller registers. */
+ for (i=0; ar_regs[i] != 0xff; i++) {
+ reg_wait_vsync_tnc(context);
+ READ_AR(mmio, (unsigned char)i, vga_buffer->ar[i]);
+ }
+
+ /* Save Graphics Controller registers. */
+ for (i=0; gr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]);
+ }
+
+ /* Save Sequencer registers. */
+ for (i=0; sr_regs[i] != 0xff; i++) {
+ READ_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]);
+ }
+
+ return 0;
+}
+
+/*!
+ * Restore the VGA Register state from the specifed state buffer.
+ *
+ * @param context the current device context
+ * @param vga_buffer this is where the VGA register state is saved
+ * @param ar_regs AR registers to save
+ * @param cr_regs CR registers to save
+ * @param sr_regs SR registers to save
+ * @param gr_regs GR registers to save
+ *
+ * @return 0
+ */
+static int reg_restore_vga_tnc(
+ igd_context_t *context,
+ vga_state_tnc_t *vga_buffer,
+ unsigned char *ar_regs,
+ unsigned char *cr_regs,
+ unsigned char *sr_regs,
+ unsigned char *gr_regs)
+{
+ unsigned long i;
+ unsigned char *mmio;
+ unsigned long bit_mask;
+ mmio = context->device_context.virt_mmadr;
+
+ /* Restore the plane latches.
+ *
+ * BP: I don't understand what this block is doing and it doesn't
+ * seem necessary. Should check this against the spec and figure
+ * out what it really does.
+ */
+
+ /* Memory Mode Register */
+ WRITE_VGA(mmio, SR_PORT, SR04, 0x06);
+ /* GR05, Graphics Mode Register */
+ WRITE_VGA(mmio, GR_PORT, GR05, 0x00);
+ /* GR06, Micsellaneous Register */
+ WRITE_VGA(mmio, GR_PORT, GR06, 0x05);
+ /* GR08, Bit Mask Register */
+ WRITE_VGA(mmio, GR_PORT, GR08, 0xFF);
+
+ for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) {
+ /* Set plane select register */
+ WRITE_VGA(mmio, GR_PORT, GR04, i);
+ /* Plane/Map mask register */
+ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
+ }
+
+ for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) {
+ /* Plane/Map mask register again?? */
+ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask);
+ }
+
+ /* Restore standard VGA registers.
+ * 2) Sequence registers
+ * 1) MSR register
+ * 3) CRTC registers
+ * 4) Graphics registers
+ * 5) Attribute registers
+ * 6) VGA Feature register
+ * 7) Index restisters
+ */
+
+
+ WRITE_VGA(mmio, SR_PORT, SR00, 01); /* Do sync reset */
+
+ for (i=0; sr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]);
+ }
+
+
+ EMGD_WRITE8(vga_buffer->msr, mmio + MSR_PORT);
+ WRITE_VGA(mmio, SR_PORT, SR00, 0x03); /* Set to normal operation */
+
+ /* Unlock CRTC */
+ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] & 0x7F);
+ for (i=0; cr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]);
+ }
+
+ for (i=0; gr_regs[i] != 0xff; i++) {
+ WRITE_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]);
+ }
+
+ for (i=0; ar_regs[i] != 0xff; i++) {
+ WRITE_AR(mmio, ar_regs[i], vga_buffer->ar[i]);
+ }
+
+ EMGD_WRITE8(vga_buffer->fcr, mmio + FEATURE_CONT_REG);
+
+ /* Restore index registers. Is this necessary? */
+ EMGD_WRITE8(vga_buffer->sr_index, mmio + SR_PORT);
+ EMGD_WRITE8(vga_buffer->cr_index, mmio + CR_PORT);
+ EMGD_WRITE8(vga_buffer->gr_index, mmio + GR_PORT);
+
+ /* Lock CRTC */
+ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] | 0x80);
+
+ return 0;
+}
+
+/*!
+ * Saves the DAC registers and lookup table.
+ *
+ * @param context
+ * @param dac_state
+ * @param platform_context
+ *
+ * @return 0
+ */
+static int reg_save_dac_tnc(
+ igd_context_t *context,
+ dac_state_tnc_t *dac_state,
+ reg_platform_context_tnc_t *platform_context)
+{
+ unsigned char *mmio;
+ int i;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Save DACMASK register */
+ dac_state->mask = EMGD_READ8(mmio + DAC_PEL_MASK);
+
+ /* Save DAC State register */
+ dac_state->mode = EMGD_READ8(mmio + DAC_STATE);
+
+ /* Save DAC Index register */
+ dac_state->index = EMGD_READ8(mmio + DAC_WRITE_INDEX);
+
+ /*
+ * Save DAC data
+ * Start from first DAC location
+ */
+ EMGD_WRITE8(0, mmio + DAC_WRITE_INDEX);
+
+ /* Save Pipe A Palette */
+ /* Or if Pipe A is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC))) ||
+ ((!(EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ (!(EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ dac_state->palette_a[i] = EMGD_READ32(mmio + i*4 + DPALETTE_A);
+ }
+ }
+
+ if (platform_context->pipes == 2) {
+ /* If Pipe B is enabled, save Pipe B Palette */
+ /* Or if Pipe B is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ ((EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ dac_state->palette_b[i] = EMGD_READ32(mmio + i*4 + DPALETTE_B);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void reg_crtc_lut_set_tnc(
+ igd_context_t *context,
+ emgd_crtc_t *emgd_crtc)
+{
+ int i;
+ unsigned long pal_reg;
+ unsigned char *mmio;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Check if the pipe is enabled */
+ if ((emgd_crtc->crtc_id == IGD_KMS_PIPEA &&
+ ((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC)))) ||
+ (emgd_crtc->crtc_id == IGD_KMS_PIPEB &&
+ ((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))))) {
+
+ pal_reg = (unsigned long)(mmio + DPALETTE_A +
+ (emgd_crtc->crtc_id * (DPALETTE_B - DPALETTE_A)));
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32((emgd_crtc->lut_r[i] << 16) |
+ (emgd_crtc->lut_g[i] << 8) |
+ emgd_crtc->lut_b[i],
+ pal_reg + i*4);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+static void reg_crtc_lut_get_tnc(
+ igd_context_t *context,
+ emgd_crtc_t *emgd_crtc)
+{
+ int i;
+ unsigned long pal_reg;
+ unsigned char *mmio;
+ unsigned long lut_value;
+
+ EMGD_TRACE_ENTER;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* Check if the pipe is enabled, is this necessary? */
+ if ((emgd_crtc->crtc_id == IGD_KMS_PIPEA &&
+ ((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC)))) ||
+ (emgd_crtc->crtc_id == IGD_KMS_PIPEB &&
+ ((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))))) {
+
+ pal_reg = (unsigned long)(mmio + DPALETTE_A +
+ (emgd_crtc->crtc_id * (DPALETTE_B - DPALETTE_A)));
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ lut_value = EMGD_READ32(pal_reg + i*4);
+ emgd_crtc->lut_r[i] = (lut_value & 0xFF0000) >> 16;
+ emgd_crtc->lut_g[i] = (lut_value & 0x00FF00) >> 8;
+ emgd_crtc->lut_b[i] = (lut_value & 0x0000FF);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/*!
+ * Restore previously saved DAC palette from the specifed state buffer.
+ *
+ * @param context
+ * @param dac_state
+ * @param platform_context
+ *
+ * @return 0
+ */
+static int reg_restore_dac_tnc(
+ igd_context_t *context,
+ dac_state_tnc_t *dac_state,
+ reg_platform_context_tnc_t *platform_context)
+{
+ int i;
+ unsigned char *mmio;
+ unsigned char temp;
+
+ mmio = context->device_context.virt_mmadr;
+
+ /* If Pipe A is enabled, restore Palette */
+ /* Or if Pipe A is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEASRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ (! (EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ /*
+ * Restore DAC data
+ * Start from first DAC location
+ */
+ EMGD_WRITE8(0, mmio + DAC_WRITE_INDEX);
+
+ /* Restore Pipe A Palette */
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32(dac_state->palette_a[i], mmio + i*4 + DPALETTE_A);
+ }
+ }
+
+ /* If this is a single pipe device. */
+ if (platform_context->pipes == 2) {
+ /* If Pipe B is enabled, restore Palette */
+ /* Or if Pipe B is used for VGA */
+ if (((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) &&
+ (EMGD_READ32(mmio + PIPEBSRC))) ||
+ ((! (EMGD_READ32(mmio + 0x71400) & 0x80000000)) &&
+ ((EMGD_READ32(mmio + 0x71400) & 0x20000000)))) {
+
+ for (i=0; i<DAC_DATA_COUNT; i++) {
+ EMGD_WRITE32(dac_state->palette_b[i], mmio + i*4 + DPALETTE_B);
+ }
+ }
+ }
+
+ /* Restore DACMASK register */
+ EMGD_WRITE8(dac_state->mask, mmio + DAC_PEL_MASK);
+
+ /* Restore DAC Index register */
+ if (dac_state->mode & 1) { /* Last write was to "write index register" */
+ EMGD_WRITE8(dac_state->index, mmio + DAC_WRITE_INDEX);
+ } else { /* Last index write was to "read index register" */
+ EMGD_WRITE8(dac_state->index - 1, mmio + DAC_READ_INDEX);
+
+ /* Dummy read to set DACSTATE register and to increment read index to
+ * last saved.
+ */
+ temp = EMGD_READ8(mmio + DAC_DATA_REG);
+ }
+
+ return 0;
+}
+
+/*!
+ * Initializes memory to store register values
+ *
+ * @param context pointer to igd_context
+ * @param flags indicate which register type to save
+ * @param _platform_context
+ *
+ * @return pointer to structure which will eventually be saved data defining
+ * register state
+ * @return NULL on failure
+ */
+static reg_buffer_t *reg_alloc_tnc(igd_context_t *context,
+ unsigned long flags,
+ void *_platform_context)
+{
+ reg_buffer_tnc_t* reg_args;
+ reg_buffer_t *reg_buffer;
+
+ EMGD_DEBUG("Entry - reg_alloc");
+
+ reg_buffer = (reg_buffer_t*)OS_ALLOC(sizeof(reg_buffer_t));
+ if (reg_buffer == NULL) {
+ return NULL;
+ }
+
+ reg_args = (reg_buffer_tnc_t*)OS_ALLOC(sizeof(reg_buffer_tnc_t));
+ if (reg_args == NULL) {
+ OS_FREE(reg_buffer);
+ return NULL;
+ }
+ reg_buffer->mode_buffer = NULL;
+ reg_buffer->platform_buffer = reg_args;
+
+ OS_MEMSET(reg_args, 0, sizeof(reg_buffer_tnc_t));
+ reg_buffer->flags = flags;
+
+ reg_args->mmio_state = (void *)OS_ALLOC(sizeof(mmio_regs_tnc));
+ reg_args->mmio_state_sdvo = (void *)OS_ALLOC(sizeof(mmio_regs_sdvo_tnc));
+
+ if (!reg_args->mmio_state) {
+ EMGD_DEBUG("Failed Allocating mmio memory");
+ /* free the "parent" memory*/
+ OS_FREE(reg_args);
+ return NULL;
+ }
+
+ if (!reg_args->mmio_state_sdvo) {
+ EMGD_DEBUG("Failed Allocating sdvo mmio memory");
+ /*Free other dependaant memory*/
+ OS_FREE(reg_args->mmio_state);
+ OS_FREE(reg_args);
+ return NULL;
+ }
+
+ return reg_buffer;
+}
+
+/*!
+ * This function calculates the size of memory to store data
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0
+ */
+static void reg_free_tnc(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_tnc_t* reg_args;
+
+ EMGD_DEBUG("Entry - reg_free");
+
+ if (reg_buffer) {
+ reg_args = (reg_buffer_tnc_t*)reg_buffer->platform_buffer;
+
+ if (reg_args) {
+ if (NULL != reg_args->mmio_state) {
+ OS_FREE(reg_args->mmio_state);
+ }
+
+ if (NULL != reg_args->mmio_state_sdvo) {
+ OS_FREE(reg_args->mmio_state_sdvo);
+ }
+
+ if (NULL != reg_args->vga_mem) {
+ OS_FREE(reg_args->vga_mem);
+ }
+
+ if (NULL != reg_args->rb_state) {
+ OS_FREE(reg_args->rb_state);
+ }
+ OS_FREE(reg_args);
+ }
+ OS_FREE(reg_buffer);
+ }
+
+ return;
+}
+
+/*!
+ * This functions save the regs
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_save_tnc(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_tnc_t *reg_args;
+ unsigned long *buffer, *buffer_sdvo;
+ reg_platform_context_tnc_t *reg_platform_context =
+ (reg_platform_context_tnc_t *)_platform_context;
+ int i;
+ unsigned char *mmio, *mmio_sdvo, *mmio_sdvo_st, *mmio_sdvo_st_gpio;
+ platform_context_tnc_t *platform_context;
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+
+
+ EMGD_TRACE_ENTER;
+
+ if (reg_buffer == NULL) {
+ return 0;
+ }
+
+ /* Before save need to idle the ring buffer */
+ context->dispatch.idle((igd_driver_h)context);
+
+ reg_args = (reg_buffer_tnc_t *)reg_buffer->platform_buffer;
+ if (reg_args == NULL) {
+ return 0;
+ }
+
+ mmio = context->device_context.virt_mmadr;
+ mmio_sdvo = context->device_context.virt_mmadr_sdvo;
+ mmio_sdvo_st = context->device_context.virt_mmadr_sdvo_st;
+ mmio_sdvo_st_gpio = context->device_context.virt_mmadr_sdvo_st_gpio;
+
+
+ /* Save vga registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+ EMGD_DEBUG("Saving VGA registers");
+ reg_save_vga_tnc(context, ®_args->vga_state,
+ reg_platform_context->ar, reg_platform_context->cr, reg_platform_context->sr,
+ reg_platform_context->gr);
+ }
+
+ /* Save VGA memory */
+#if 0
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA_MEM) {
+ EMGD_DEBUG("Saving VGA memory");
+ if (!reg_args->vga_mem) {
+ reg_args->vga_mem = (void *)OS_ALLOC_LARGE(64 * 1024);
+ if (reg_args->vga_mem != NULL) {
+ OS_MEMCPY(reg_args->vga_mem,
+ (void *)context->device_context.virt_fb_adr, 64*1024);
+ } else {
+ EMGD_ERROR("Unable to allocate memory for vga memory");
+ }
+ } else {
+ OS_MEMCPY(reg_args->vga_mem,
+ (void *)context->device_context.virt_fb_adr, 64*1024);
+ }
+ }
+#endif
+
+ /* Save mmio registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_MMIO) {
+ EMGD_DEBUG("Saving MMIO registers");
+ buffer = reg_args->mmio_state;
+ for (i=0; reg_platform_context->mmio_regs[i] != 0xffffffff; i++) {
+ *buffer++ = EMGD_READ32(mmio + reg_platform_context->mmio_regs[i]);
+ }
+
+ buffer_sdvo = reg_args->mmio_state_sdvo;
+ for (i=0; reg_platform_context->mmio_regs_sdvo[i] != 0xffffffff; i++) {
+ *buffer_sdvo++ = EMGD_READ32(mmio_sdvo + reg_platform_context->mmio_regs_sdvo[i]);
+ }
+
+ if (reg_buffer->flags & IGD_REG_SAVE_GTT) {
+ reg_save_gtt_tnc(context, mmio, reg_args);
+ }
+ }
+
+ /* Save DAC registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_DAC) {
+ EMGD_DEBUG("Saving DAC registers");
+ reg_save_dac_tnc(context, ®_args->dac_state, reg_platform_context);
+ }
+
+ /* Save Mode state */
+ if(reg_buffer->flags & IGD_REG_SAVE_MODE) {
+ EMGD_DEBUG("Saving mode state");
+ /* At driver initialization though mode_save is requested, mode isn't
+ * initialized. So skip the mode_save if dispatch function isn't
+ * available. In this case, mode_save() will be done as part of
+ * mode_init(). */
+ if (context->mod_dispatch.mode_save && !reg_buffer->mode_buffer) {
+ context->mod_dispatch.mode_save(context,
+ ®_buffer->mode_buffer,
+ ®_buffer->flags);
+ } else {
+ EMGD_DEBUG("mode_save() is skipped as mode_init() isn't done.");
+ }
+ }
+
+
+ /* Save the PCI Config Legacy Backlight Brightness Register */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+ 0xF4, ®_args->pci_lbb)) {
+ EMGD_DEBUG("Reading Legacy Backlight Brightness");
+ }
+
+ return 0;
+} /* reg_save */
+
+/*!
+ * This function restores the regs states
+ *
+ * @param context void pointer to main igd context
+ * @param reg_buffer pointer to register structure returned from a reg_alloc
+ * @param _platform_context
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+int reg_restore_tnc(igd_context_t *context,
+ reg_buffer_t *reg_buffer,
+ void *_platform_context)
+{
+ reg_buffer_tnc_t* reg_args;
+ reg_platform_context_tnc_t *reg_platform_context =
+ (reg_platform_context_tnc_t *)_platform_context;
+ unsigned char *mmio, *mmio_sdvo, *mmio_sdvo_st, *mmio_sdvo_st_gpio;
+ unsigned long *buffer, *buffer_sdvo;
+ unsigned long lbb;
+ int i;
+
+ platform_context_tnc_t *platform_context;
+ platform_context = (platform_context_tnc_t *)context->platform_context;
+
+ EMGD_DEBUG("Entry - reg_restore");
+
+ if (reg_buffer == NULL) {
+ return 0;
+ }
+
+ reg_args = (reg_buffer_tnc_t *)reg_buffer->platform_buffer;
+ if (reg_args == NULL) {
+ return 0;
+ }
+
+ EMGD_DEBUG(" flags = 0x%lx", reg_buffer->flags);
+
+ mmio = context->device_context.virt_mmadr;
+ mmio_sdvo = context->device_context.virt_mmadr_sdvo;
+ mmio_sdvo_st = context->device_context.virt_mmadr_sdvo_st;
+ mmio_sdvo_st_gpio = context->device_context.virt_mmadr_sdvo_st_gpio;
+
+ /* Restore Mode state */
+ if (reg_buffer->flags & IGD_REG_SAVE_MODE) {
+ if (reg_buffer->mode_buffer) {
+ context->mod_dispatch.mode_restore(context,
+ ®_buffer->mode_buffer,
+ ®_buffer->flags);
+ } else {
+ EMGD_DEBUG("mode_restore() already happened in mode_shutdown().");
+ }
+ }
+
+ /* Restore MMIO registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_MMIO) {
+ EMGD_DEBUG("Restoring MMIO registers");
+ buffer = reg_args->mmio_state;
+ for (i=0; reg_platform_context->mmio_regs[i] != 0xffffffff; i++) {
+ if (reg_platform_context->mmio_regs[i] == MI_ARB_STATE) {
+ EMGD_DEBUG("Handle special masked register case");
+ EMGD_WRITE32(0x04100000 | *buffer++, mmio +
+ reg_platform_context->mmio_regs[i]);
+ } else if (reg_platform_context->mmio_regs[i] == DPLLACNTR ||
+ reg_platform_context->mmio_regs[i] == DPLLBCNTR) {
+
+ EMGD_DEBUG("Handle special DPLL settling");
+ EMGD_WRITE32(*buffer++,
+ mmio + reg_platform_context->mmio_regs[i]);
+ OS_SLEEP(150);
+ } else {
+ EMGD_WRITE32(*buffer++, mmio + reg_platform_context->mmio_regs[i]);
+ }
+ }
+// reg_restore_gtt_tnc(context, reg_args);
+
+ buffer_sdvo = reg_args->mmio_state_sdvo;
+ for (i=0; reg_platform_context->mmio_regs_sdvo[i] != 0xffffffff; i++) {
+ if (reg_platform_context->mmio_regs_sdvo[i] == MI_ARB_STATE) {
+ EMGD_DEBUG("Handle special masked register case");
+ EMGD_WRITE32(0x04100000 | *buffer_sdvo++, mmio_sdvo +
+ reg_platform_context->mmio_regs_sdvo[i]);
+ } else if (reg_platform_context->mmio_regs_sdvo[i] == DPLLACNTR ||
+ reg_platform_context->mmio_regs_sdvo[i] == DPLLBCNTR) {
+
+ EMGD_DEBUG("Handle special DPLL settling");
+ EMGD_WRITE32(*buffer_sdvo++,
+ mmio_sdvo + reg_platform_context->mmio_regs_sdvo[i]);
+ OS_SLEEP(150);
+ } else {
+ EMGD_WRITE32(*buffer_sdvo++, mmio_sdvo + reg_platform_context->mmio_regs_sdvo[i]);
+ }
+ }
+
+ if (reg_buffer->flags & IGD_REG_SAVE_GTT) {
+ reg_restore_gtt_tnc(context, reg_args);
+ }
+ }
+
+#if 0
+ /* Restore VGA memory */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA_MEM) {
+ if (reg_args->vga_mem) {
+ OS_MEMCPY((void *)context->device_context.virt_fb_adr,
+ reg_args->vga_mem, 64*1024);
+ } else {
+ EMGD_ERROR("Trying to restore NULL VGA memory");
+ }
+ }
+#endif
+
+ /* Restore DAC registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_DAC) {
+ reg_restore_dac_tnc(context, ®_args->dac_state, reg_platform_context);
+ }
+
+ /* Restore VGA registers */
+ if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+ reg_restore_vga_tnc(context, ®_args->vga_state,
+ reg_platform_context->ar, reg_platform_context->cr, reg_platform_context->sr,
+ reg_platform_context->gr);
+ }
+
+ /* restore the Legacy Backlight Brightness register. This register
+ * will be 0 when returning from power management causing backlight to be
+ * off if the register is not saved and restored during power management
+ */
+ if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0, 0xF4, &lbb)) {
+ EMGD_DEBUG("Reading Legacy Backlight Brightness");
+
+ }
+
+ /* only of the LBB has no value, causing the backlight to be off, we restore
+ * the saved LBB value. This is just in case there are user applications
+ * or firmware setting this register before the driver restores */
+ if(!(lbb & 0xFF)){
+ if(OS_PCI_WRITE_CONFIG_32(platform_context->pcidev0,
+ 0xF4, (lbb | reg_args->pci_lbb))){
+ EMGD_DEBUG("Writing into Legacy Backlight Brightness");
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * This function saves the GTT table entries into a buffer so that the GTT
+ * can be restored later.
+ *
+ * @param context needs this to get the GTT table size and to get the
+ * virtual address to the GTT table
+ * @param mmio virtual address to MMIO
+ * @param reg_args a pre-allocated context where GTT entries are saved
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_save_gtt_tnc(igd_context_t *context, unsigned char *mmio,
+ reg_buffer_tnc_t *reg_args)
+{
+ unsigned int i;
+
+ /* Read the GTT entries from GTT ADR and save it in the array. */
+ for (i = 0; i < (context->device_context.gatt_pages); i++) {
+ reg_args->gtt[i] = EMGD_READ32(
+ context->device_context.virt_gttadr + i);
+ }
+
+ return 0;
+}
+
+/*!
+ * This function restores the GTT table entries.
+ *
+ * @param context the context contains the GTT size and address
+ * @param reg_args this has the saved GTT entries
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_restore_gtt_tnc(igd_context_t *context,
+ reg_buffer_tnc_t *reg_args)
+{
+ unsigned int i;
+
+ /* If the first element is 0, then nothing was saved */
+ if (0 == reg_args->gtt[0]) {
+ return 0;
+ }
+
+ /* Restore the GTT tablep */
+ for (i=0; i < context->device_context.gatt_pages; i++) {
+ EMGD_WRITE32(reg_args->gtt[i],
+ context->device_context.virt_gttadr + i);
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/utils/math_fix.c b/drivers/gpu/drm/emgd/emgd/utils/math_fix.c
new file mode 100644
index 0000000..84e5811
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/math_fix.c
@@ -0,0 +1,138 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains fixed point implementations of math functions
+ *-----------------------------------------------------------------------------
+ */
+
+
+/******************************************************************************
+ * This is a look-up table for natural log for integer values 1 - 255 in
+ * 24i.8f fixed point format.
+ *
+ * This table returns 0 or ln(0), but it is technically undefined.
+ *****************************************************************************/
+static const int ln_table[] =
+ {
+ 0, 0, 177, 281, 355, 412, 459, 498, 532, 562, 589, 614,
+ 636, 657, 676, 693, 710, 725, 740, 754, 767, 779, 791, 803,
+ 814, 824, 834, 844, 853, 862, 871, 879, 887, 895, 903, 910,
+ 917, 924, 931, 938, 944, 951, 957, 963, 969, 975, 980, 986,
+ 991, 996, 1001, 1007, 1012, 1016, 1021, 1026, 1030, 1035, 1039, 1044,
+ 1048, 1052, 1057, 1061, 1065, 1069, 1073, 1076, 1080, 1084, 1088, 1091,
+ 1095, 1098, 1102, 1105, 1109, 1112, 1115, 1119, 1122, 1125, 1128, 1131,
+ 1134, 1137, 1140, 1143, 1146, 1149, 1152, 1155, 1158, 1160, 1163, 1166,
+ 1168, 1171, 1174, 1176, 1179, 1181, 1184, 1186, 1189, 1191, 1194, 1196,
+ 1199, 1201, 1203, 1206, 1208, 1210, 1212, 1215, 1217, 1219, 1221, 1223,
+ 1226, 1228, 1230, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248,
+ 1250, 1252, 1254, 1256, 1258, 1260, 1261, 1263, 1265, 1267, 1269, 1270,
+ 1272, 1274, 1276, 1278, 1279, 1281, 1283, 1284, 1286, 1288, 1289, 1291,
+ 1293, 1294, 1296, 1298, 1299, 1301, 1302, 1304, 1306, 1307, 1309, 1310,
+ 1312, 1313, 1315, 1316, 1318, 1319, 1321, 1322, 1324, 1325, 1327, 1328,
+ 1329, 1331, 1332, 1334, 1335, 1336, 1338, 1339, 1341, 1342, 1343, 1345,
+ 1346, 1347, 1349, 1350, 1351, 1353, 1354, 1355, 1356, 1358, 1359, 1360,
+ 1361, 1363, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1372, 1374, 1375,
+ 1376, 1377, 1378, 1380, 1381, 1382, 1383, 1384, 1385, 1387, 1388, 1389,
+ 1390, 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1402,
+ 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1415,
+ 1416, 1417, 1418, 1419
+ };
+
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: os_pow_fix()
+ *
+ * Parameters:
+ * [IN] base: the base, should be between 0 and 255.
+ * [IN] power: this must be in 24i.8f format.
+ *
+ * Description:
+ * This function uses the Taylor Series to approximate the power function
+ * using fixed-point math. See this website for the math background
+ * http://www.efunda.com/math/taylor_series/exponential.cfm
+ *
+ * This function was originally designed for gamma correction. When the
+ * base value is between 1 - 255 and the power is between 0.1 and 2, this
+ * function will produce an approximation that is within 2% of the "real"
+ * function.
+ *
+ * Returns:
+ * The result in 24i.8f format
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned int os_pow_fix( const int base, const int power )
+{
+ /* For some reason using "const unsigned int" causes a compiler error
+ * when I use it below when I declare "result[APPROXIMATE_TERMS]". So
+ * switched these from "const unsigned .." to #define
+ */
+ #define APPROXIMATE_TERMS 40
+#define FRACTION_BITS 8 /* num of bits for fraction */
+
+ unsigned int result[APPROXIMATE_TERMS];
+ unsigned int i, power_loop;
+ unsigned int total = 0;
+ int ln_x = ln_table[base]; /* ln_x is in 24i.8f format */
+
+
+ /* nothing to do if we get 0 */
+ if (0 == base) {
+ return 0;
+ } else {
+ ln_x = ln_table[base];
+ }
+
+ /* We approximate the result using APPROXIMATE_TERMS terms */
+ for (i = 0; i < APPROXIMATE_TERMS; i++) {
+
+ result[i] = 1 << FRACTION_BITS;
+
+ /* Need to be very careful about the order in which we are multiplying
+ * multiplying and dividing because we don't want any overflow. In
+ * addition, every time we multiply 2 fixed point numbers, we need to
+ * shift the result by FRACTION_BITS to maintain the radix point.
+ */
+ for( power_loop = 0; power_loop < i; power_loop++ ) {
+ result[i] *= ln_x;
+ result[i] /= (power_loop + 1);
+ result[i] >>=FRACTION_BITS;
+ result[i] *= power;
+ result[i] >>=FRACTION_BITS;
+
+ }
+
+ total += result[i];
+
+ }
+
+ return total;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/utils/memmap.c b/drivers/gpu/drm/emgd/emgd/utils/memmap.c
new file mode 100644
index 0000000..2ee0812
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/memmap.c
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the XFree86 implementations of the OAL
+ * memory.h abstractions.
+ *-----------------------------------------------------------------------------
+ */
+#include <io.h>
+
+#ifndef _OAL_LINUX_KERNEL_IO_MEMMAP_H
+#define _OAL_LINUX_KERNEL_IO_MEMMAP_H
+
+
+void * os_map_io_to_mem_nocache(
+ unsigned long base_address,
+ unsigned long size
+ )
+{
+ return ioremap(base_address, size);
+}
+
+void os_unmap_io_from_mem(
+ void * virt_addr,
+ unsigned long size
+ )
+{
+ iounmap(virt_addr);
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/utils/pci.c b/drivers/gpu/drm/emgd/emgd/utils/pci.c
new file mode 100644
index 0000000..969fc6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/pci.c
@@ -0,0 +1,277 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains Linux kernel space PCI API for the OAL abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <memory.h>
+#include <pci.h>
+#include <linux/pci.h>
+#include <io.h>
+
+#if defined(CONFIG_VGA_ARB)
+#include <linux/vgaarb.h>
+#endif
+
+
+//
+// This is our local representation of a PCI device.
+// This struct is private to this file, and exposed to calling functions
+// only through an opaque "os_pci_dev_t" handle.
+//
+typedef struct _linuxkernel_pci {
+ struct pci_dev *dev;
+ unsigned int bus;
+ unsigned int slot;
+ unsigned int func;
+}linuxkernel_pci_t;
+
+/*----------------------------------------------------------------------
+ * Function:
+ *pci_find_device_generic
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *os_pci_dev_t os_pci_dev
+ * Description:
+ *This function finds a PCI device by going through 255 buses, 32 devices
+ *and 8 functions and tries to match each ones vendor and device ids with
+ *the ones given to it as parameters. Stops for the first device it finds
+ *with a matching vendor and device, so it will not find multiple devices.
+ *This is _NOT_ an exported OAL
+ *function.
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+static os_pci_dev_t pci_find_device_generic(
+ unsigned short vendor_id,
+ unsigned short device_id,
+ os_pci_dev_t pci_dev_handle
+ )
+{
+ struct pci_dev *our_device; // Kernel struct for a PCI device
+ linuxkernel_pci_t *pdev; // Our struct for a PCI device.
+
+ // Locate the device, and lock it. Start search at the start of the list.
+ our_device = pci_get_device(vendor_id, device_id, NULL);
+ // If we didn't find it, return an error.
+ if (!our_device){
+ return (os_pci_dev_t)NULL;
+ }
+
+ // Get the pointer to the destination for the data.
+ // pci_dev_handle is an opaque pointer to a linuxkernel_pci_t struct
+ // If there isn't one, allocate it.
+ pdev = (linuxkernel_pci_t *)pci_dev_handle;
+ if(!pdev) {
+
+ // Caller did not supply a handle to a PCI device struct.
+ // Allocate one.
+ pdev = (linuxkernel_pci_t *)OS_ALLOC(sizeof(linuxkernel_pci_t));
+ if(!pdev) {
+ return (os_pci_dev_t)NULL;
+ }
+ // Zero the destination memory
+ memset(pdev, 0, sizeof(linuxkernel_pci_t));
+ }
+
+ // Copy over from the kernel struct to our struct.
+ // It is safe to copy a pointer to the pci_dev, since we
+ // have a lock on it.
+ pdev->dev = our_device;
+ pdev->bus = our_device->bus->number;
+ pdev->slot = PCI_SLOT(our_device->devfn);
+ pdev->func = PCI_FUNC(our_device->devfn);
+
+ return (os_pci_dev_t)pdev;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *os_pci_find_device
+ *
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *unsigned short bus,
+ *unsigned short dev,
+ *unsigned short func,
+ *os_pci_dev_t os_pci_dev
+ *
+ * Description:
+ * This function finds a PCI device by scanning the specified bus, dev, func
+ *and tries to match vendor and device ids with the ones given to it as
+ *parameters.
+ *
+ * Notes: If the bus number is 0xFFFF, then the function searches for that
+ * vendor_id, device_id pair in the whole PCI topology of the system i.e
+ * it goes through all the buses, devices, functions in the system
+ *
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+os_pci_dev_t os_pci_find_device(
+ unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short bus,
+ unsigned short dev,
+ unsigned short func,
+ os_pci_dev_t pci_dev)
+{
+ /* TODO: Right now, Just fallback to pci_find_device_generic
+ * But we need to implement this
+ */
+ return pci_find_device_generic(vendor_id, device_id, pci_dev);
+}
+
+int os_pci_get_slot_address(
+ os_pci_dev_t pci_dev,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *func)
+{
+
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+ if(bus) {
+ *bus = pdev->bus;
+ }
+ if(slot) {
+ *slot = pdev->slot;
+ }
+ if(func) {
+ *func = pdev->func;
+ }
+ return 0;
+}
+
+int os_pci_read_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_read_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_word(pdev->dev, offset,val);
+}
+
+int os_pci_read_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long* val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ EMGD_ASSERT(val, "Invalid pointer", 0);
+ return pci_read_config_dword(pdev->dev, offset, (u32*)val);
+}
+
+int os_pci_write_config_8(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned char val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_16(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned short val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_word(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_32(
+ os_pci_dev_t pci_dev,
+ unsigned long offset,
+ unsigned long val
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+ return pci_write_config_dword(pdev->dev, offset, val);
+}
+
+int os_pci_disable_legacy_vga_decoding(
+ os_pci_dev_t pci_dev
+ )
+{
+#if defined(CONFIG_VGA_ARB)
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+ EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+ vga_set_legacy_decoding(pdev->dev, VGA_RSRC_NONE);
+#else
+ /* Noop if the VGA arbiter isn't compiled into the kernel */
+#endif
+
+ return 0;
+}
+
+
+void os_pci_free_device(
+ os_pci_dev_t pci_dev
+ )
+{
+ linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+
+ // Release the lock on our PCI device struct
+ pci_dev_put(pdev->dev);
+
+ // Free our local structure.
+ OS_FREE(pdev);
+
+ return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
new file mode 100644
index 0000000..c8db86c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
@@ -0,0 +1,928 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx.c
+ * $Revision: 1.28 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Send commands to the MSVDX video decode engine.
+ * The host communicates with the firmware via messages. The following
+ * messages are supported:
+ * RENDER -> MTX
+ * DEBLOCK -> MTX
+ * OOLD -> MTX
+ * MSG_PADDING -> MTX
+ * CMD_COMPLETED <- MTX
+ * DEBLOCK_REQUIRED <- MTX
+ * CMD_FAILED <- MTX
+ * HW_PANIC <- MTX
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+#include <msvdx.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+#include "services_headers.h"
+#include <drm_emgd_private.h>
+
+
+
+//extern int msvdx_init_plb(void);
+extern void msvdx_reset_plb(igd_context_t *context);
+
+int send_to_mtx(igd_context_t *context, unsigned long *msg);
+int msvdx_poll_mtx_irq(igd_context_t *context);
+void msvdx_mtx_interrupt_plb(igd_context_t *context);
+unsigned long populate_fence_id(igd_context_t *context, unsigned long *mtx_msgs,
+ unsigned long mtx_msg_cnt);
+int process_mtx_messages(igd_context_t *context,
+ unsigned long *mtx_msgs, unsigned long mtx_msg_cnt,
+ unsigned long fence);
+#ifdef DEBUG_BUILD_TYPE
+static void debug_mesg_info(igd_context_t *context,
+ unsigned long *msg,
+ unsigned long num_words);
+/* To eliminate warnings, am temporarily #ifdef'ing this function. Please
+ * remove the #ifdef when this function is to be used.
+ */
+#ifdef USE_DEBUG_DUMP
+static void debug_dump(igd_context_t *context);
+#endif
+static void lldma_dump(unsigned long *cmd_base, unsigned long offset);
+static void dump_all_messages(igd_context_t *context);
+#define DEBUG_MESG_INFO(a, b, c) debug_mesg_info(a, b, c)
+#define DEBUG_DUMP(a) debug_dump(a)
+#define LLDMA_DUMP(a, b) lldma_dump(a, b)
+#define DUMP_ALL_MESSAGES(a) dump_all_messages(a)
+#else
+#define DEBUG_MESG_INFO(a, b, c)
+#define DEBUG_DUMP(a)
+#define LLDMA_DUMP(a, b)
+#define DUMP_ALL_MESSAGES(a)
+#endif
+
+/* These are used to debug the message buffer */
+unsigned long *save_msg;
+unsigned long save_msg_cnt;
+
+/* This is used to discover when MSVDX gets in a bad state and stops generating
+ * interrupts. By keeping track of when the last time a cmd was dequeued, when
+ * cmds continue to be queued, but never dequeued, this bad hardware state can
+ * be detected.
+ */
+unsigned long jiffies_at_last_dequeue = 0;
+
+int msvdx_dequeue_send(igd_context_t *context)
+{
+ platform_context_plb_t *platform;
+ struct msvdx_cmd_queue *msvdx_cmd = NULL;
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ if (list_empty(&platform->msvdx_queue)) {
+ //printk(KERN_ERR "MSVDXQUE: msvdx list empty\n");
+ platform->msvdx_busy = 0;
+ return -EINVAL;
+ }
+
+ //printk(KERN_INFO "MSVDXQUE: get from the msvdx list\n");
+ msvdx_cmd = list_first_entry(&platform->msvdx_queue,
+ struct msvdx_cmd_queue, head);
+
+ ret = process_mtx_messages(context, msvdx_cmd->cmd, msvdx_cmd->cmd_size, platform->msvdx_fence);
+
+ jiffies_at_last_dequeue = jiffies;
+
+ if (ret) {
+ printk(KERN_ERR "MSVDXQUE: process_mtx_messages failed\n");
+ ret = -EINVAL;
+ }
+
+ list_del(&msvdx_cmd->head);
+ msvdx_cmd->cmd = NULL;
+ kfree(msvdx_cmd);
+
+ return ret;
+}
+
+unsigned long populate_fence_id(igd_context_t *context, unsigned long *mtx_msgs,
+ unsigned long mtx_msg_cnt)
+{
+ platform_context_plb_t *platform;
+ unsigned long submit_size = 0;
+ unsigned long submit_id = 0;
+ unsigned long context_id = 0;
+ unsigned int msg;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ for (msg = 0; msg < mtx_msg_cnt; msg++) {
+ submit_size = (mtx_msgs[0] & 0x000000ff);
+ submit_id = (mtx_msgs[0] & 0x0000ff00) >> 8;
+
+ if (submit_id == IGD_MSGID_RENDER) {
+ mtx_msgs[4] = ++platform->msvdx_fence;
+ //printk(KERN_INFO "Update fence id %lx\n", mtx_msgs[4]);
+ }
+
+ context_id = mtx_msgs[3];
+ mtx_msgs += (submit_size / sizeof(unsigned long));
+ }
+
+ return context_id;
+}
+
+/*
+ * The incoming command buffer holds MTX firmware messages, register pairs,
+ * and the LLDMA linked lists. There is a simple header at the beginning of
+ * the buffer that has the MTX message offset and the number of MTX messages.
+ *
+ * To process this buffer, find the MTX firmware messages and send each
+ * one to the MTX firmware.
+ */
+int process_mtx_messages(igd_context_t *context,
+ unsigned long *mtx_msgs, unsigned long mtx_msg_cnt,
+ unsigned long fence)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ platform_context_plb_t *platform;
+ unsigned long submit_size;
+ unsigned long submit_id;
+ unsigned int msg;
+ unsigned long skipped_msg_cnt;
+ unsigned long msvdx_status;
+
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ // message processing is about to start .. set the flag=bit 2
+ spin_lock(&platform->msvdx_init_plb);
+ platform->msvdx_status = platform->msvdx_status | 2;
+ msvdx_status = platform->msvdx_status;
+ spin_unlock(&platform->msvdx_init_plb);
+
+ if (msvdx_status & 1)
+ {
+ // OOPS: reset/fw load in progress ... return from here
+ spin_lock(&platform->msvdx_init_plb);
+ platform->msvdx_status = platform->msvdx_status & ~2; // unset message processing status.
+ spin_unlock(&platform->msvdx_init_plb);
+
+ return 0;
+ }
+
+ save_msg = mtx_msgs;
+ save_msg_cnt = mtx_msg_cnt;
+ skipped_msg_cnt = 0;
+
+ for (msg = 0; msg < mtx_msg_cnt; msg++) {
+
+ if(!mtx_msgs) {
+ printk(KERN_ERR "Invalid message");
+ return -IGD_ERROR_INVAL;
+ }
+
+ submit_size = (mtx_msgs[0] & 0x000000ff);
+ submit_id = (mtx_msgs[0] & 0x0000ff00) >> 8;
+
+ if (submit_id != IGD_MSGID_RENDER) {
+ /* Error, unknown message id, skip it */
+ EMGD_ERROR("Unknown MTX message id 0x%lx", submit_id);
+ skipped_msg_cnt++;
+ continue;
+ }
+
+ if(!(mtx_msgs + sizeof(unsigned long))) {
+ printk(KERN_ERR "Invalid message");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* reuse the sgx phy PD */
+ mtx_msgs[1] = platform->psb_cr_bif_dir_list_base1 | 1;
+
+ /*
+ * If the send returns busy, then retry sending the message, otherwise
+ * move to next message in buffer.
+ */
+ if (send_to_mtx(context, (unsigned long *)mtx_msgs) != -IGD_ERROR_BUSY) {
+ mtx_msgs += (submit_size / sizeof(unsigned long));
+ /*
+ * msvdx_mtx_interrupt_plb checks the firmware-to-host buffer
+ * and if there are messages there, processes them.
+ */
+ //msvdx_mtx_interrupt_plb(context);
+ } else {
+ msg--; /* Reset count back to unsent message */
+ /* Should this wait a bit? */
+ }
+ }
+
+ // We are done processing messages .. unset the flag
+ spin_lock(&platform->msvdx_init_plb);
+ platform->msvdx_status = platform->msvdx_status & ~2;
+ spin_unlock(&platform->msvdx_init_plb);
+
+ EMGD_TRACE_EXIT;
+ if (skipped_msg_cnt == mtx_msg_cnt) {
+ /* We failed to submit anything; the entire buffer was bad.
+ * Just return a failure code so we can unmark the video engine
+ * busy bit. */
+ return -IGD_ERROR_INVAL;
+ } else {
+ return 0;
+ }
+}
+
+
+
+
+/*
+ * This is the function that actually passes the message to the MTX
+ * firmware. The contents of the message are opaque to this function.
+ *
+ * Currently, the only supported message type is RENDER.
+ */
+int send_to_mtx(igd_context_t *context, unsigned long *msg)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long pad_msg;
+ unsigned long num_words;
+ unsigned long words_free;
+ unsigned long read_idx, write_idx;
+ platform_context_plb_t *platform =
+ (platform_context_plb_t *)context->platform_context;
+ int padding_flag = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Enable all clocks before touching VEC local ram */
+ EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ /* The first two longs in the msg have the message ID and size */
+ num_words = ((msg[0] & 0xff) + 3) / 4;
+
+ /* Is message too big? */
+ if (num_words > platform->mtx_buf_size) {
+ /* TODO: Error ? */
+ EMGD_ERROR("Message is too large (size=%ld, max=%ld).", num_words,
+ platform->mtx_buf_size);
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*
+ * Safely increment the "number of messages in flight" counter, but only
+ * if this isn't a "padding" message.
+ */
+ /*
+ if (((msg[0] & 0xff00) >> 8) != FWRK_MSGID_PADDING) {
+ platform->mtx_submitted++;
+ }
+ */
+
+ /*
+ * Make sure the MTX is enabled
+ */
+ EMGD_WRITE32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, mmio + PSB_MSVDX_MTX_ENABLE);
+
+
+ read_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_MTX_RD_INDEX);
+ write_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+ EMGD_DEBUG("MTX read = 0x%08lx write = 0x%08lx", read_idx, write_idx);
+
+ /*
+ * Check to see if there is room for this message, if not send
+ * a pad message to use up all the space and wait for the next
+ * slot.
+ */
+ if ((write_idx + num_words) > platform->mtx_buf_size) {
+ /*
+ * if the read pointer is at zero, then the engine is probably
+ * hung and not processing the message. This is bad.
+ */
+ if (read_idx == 0) {
+ platform->msvdx_needs_reset = 1;
+ EMGD_ERROR("MSVDX Engine is hung? Aborting send.");
+ DUMP_ALL_MESSAGES(context);
+ return -IGD_ERROR_BUSY;
+ }
+
+ /*
+ * The message id and size are encoded into the first word of
+ * the message.
+ * bits 0:7 size (in long words?)
+ * bits 8:15 message id
+ */
+ pad_msg = (platform->mtx_buf_size - write_idx) << 2; /* size */
+ pad_msg |= (FWRK_MSGID_PADDING << 8); /* message id */
+ EMGD_DEBUG("Sending a pad_mesg: 0x%x, size = %ld", FWRK_MSGID_PADDING,
+ (pad_msg & 0xff));
+
+ /*
+ * Maybe just try writing the message directly here, instead of calling
+ * this fuction recursivly??
+ */
+ EMGD_WRITE32(pad_msg,
+ mmio + platform->mtx_buf_offset + (write_idx << 2));
+ write_idx = 0;
+
+ /* Update the write index to the next free location */
+ EMGD_WRITE32(write_idx, mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+ EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+ padding_flag = 1;
+ }
+
+ /* Verify free space available */
+ words_free = (write_idx >= read_idx) ?
+ platform->mtx_buf_size - (write_idx - read_idx) : read_idx - write_idx;
+
+ if (num_words > (words_free - 1)) {
+ /* There is no space available, this isn't an error */
+
+ if (padding_flag) {
+ /* Make sure clocks are enabled before we kick */
+ EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ /* Send an interrupt to the MTX to let it know about the message */
+ EMGD_WRITE32(1, mmio + PSB_MSVDX_MTX_KICK);
+ }
+
+ return - IGD_ERROR_BUSY;
+ }
+
+ /*
+ * DEBUGGING info:
+ * Call a function to try and output some debugging info about the message
+ */
+ /* DEBUG_MESG_INFO(context, msg, num_words); */
+
+ /* Write the message to the firmware */
+ while (num_words > 0) {
+ EMGD_WRITE32(*msg++,
+ mmio + platform->mtx_buf_offset + (write_idx << 2));
+ num_words--;
+ write_idx++;
+ }
+
+ /* Check for wrap in the buffer */
+ if (write_idx == platform->mtx_buf_size) {
+ write_idx = 0;
+ }
+
+ /* Update the write index to the next free location */
+ EMGD_WRITE32(write_idx, mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+ /* Check for overwrite */
+ if (write_idx == read_idx) {
+ EMGD_ERROR("Overwrite detected, resetting MSVDX.");
+ platform->msvdx_needs_reset = 1;
+ }
+
+ /* Send an interrupt to the MTX to let it know about the message */
+ EMGD_WRITE32(1, mmio + PSB_MSVDX_MTX_KICK);
+
+ /* Read MSVDX Register several times in case idle signal assert */
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+
+
+#if 0
+ DEBUG_DUMP(context); /* For lots of additional debugging info */
+#endif
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+/*
+ * This function will look at messages sent from the MTX Firmware
+ * and decode them.
+ */
+
+void msvdx_mtx_interrupt_plb(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long msg[128];
+ unsigned long read_idx, write_idx;
+ unsigned long num_words;
+ unsigned long msg_offset;
+ unsigned long fence = 0;
+ unsigned long flags = 0;
+ unsigned long status;
+ platform_context_plb_t *platform =
+ (platform_context_plb_t *)context->platform_context;
+
+ /* Check that the clocks are enabled before trying to read message */
+ EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ do {
+ read_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_HOST_RD_INDEX);
+ write_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_HOST_WRT_INDEX);
+ EMGD_DEBUG("HOST read=0x%lx write=0x%lx", read_idx, write_idx);
+
+ if (read_idx != write_idx) {
+ /* Read the first waiting message from the buffer */
+ msg_offset = 0;
+ msg[msg_offset] = EMGD_READ32(mmio + (platform->host_buf_offset +
+ (read_idx << 2)));
+
+ /* Size of message rounded to nearest number of words */
+ num_words = ((msg[0] & 0x000000ff) + 3) / 4;
+
+ if (++read_idx >= platform->host_buf_size) {
+ read_idx = 0;
+ }
+
+ for (msg_offset++; msg_offset < num_words; msg_offset++) {
+ msg[msg_offset] = EMGD_READ32(mmio + platform->host_buf_offset +
+ (read_idx << 2));
+
+ if (++read_idx >= platform->host_buf_size) {
+ read_idx = 0;
+ }
+ }
+
+ EMGD_WRITE32(read_idx, mmio + PSB_MSVDX_COMMS_TO_HOST_RD_INDEX);
+
+ /* Check message ID */
+ switch ((msg[0] & 0x0000ff00) >> 8) {
+ case IGD_MSGID_CMD_FAILED:
+ fence = msg[1]; /* Fence value */
+ status = msg[2]; /* Failed IRQ Status */
+ printk(KERN_ERR "MSGID_CMD, status = 0x%lx, "
+ "fence = 0x%lx\n", status, fence);
+
+ /* This message from MTX is for informational purposes and
+ firmware does not expect hardware to be reset */
+ platform->msvdx_needs_reset = 1;
+
+ if (msg[1] != 0) {
+ platform->mtx_completed = fence;
+ }
+ DUMP_ALL_MESSAGES(context);
+ goto done;
+ break;
+ case IGD_MSGID_CMD_COMPLETED:
+ fence = msg[1];
+ flags = msg[2];
+
+ //printk(KERN_INFO "MSGID_CMD_COMPLETED: fence 0x%lx\n", fence);
+ platform->mtx_completed = fence;
+ jiffies_at_last_dequeue = 0;
+
+ if (flags & FW_VA_RENDER_HOST_INT) {
+ spin_lock(&platform->msvdx_lock);
+ msvdx_dequeue_send(context);
+ spin_unlock(&platform->msvdx_lock);
+ }
+
+ break;
+ case IGD_MSGID_CMD_HW_PANIC:
+ fence = msg[1]; /* Fence value */
+ status = msg[2]; /* Failed IRQ Status */
+ printk(KERN_ERR "MSGID_CMD_HW_PANIC: fence 0x%08lx, "
+ "Irq 0x%08lx\n", msg[1], msg[2]);
+ platform->msvdx_needs_reset = 1;
+ platform->mtx_completed = fence;
+ DUMP_ALL_MESSAGES(context);
+ goto done;
+ break;
+ default:
+ EMGD_ERROR("Unknown message ID 0x%lx response from firmware.", (msg[0] & 0x0000ff00) >> 8);
+ break;
+ }
+
+ }
+ } while (read_idx != write_idx);
+
+done:
+ return;
+}
+
+
+/*
+ * Simple function to check for a MSVDX interrupt. Clear the interrupt status
+ * if one occured. Mostly just ignore them for now.
+ */
+
+#define MSVDX_MMU_FAULT_IRQ_MASK 0x00000F00
+#define MSVDX_MTX_IRQ_MASK 0x00004000
+#define MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK 0x00000002
+
+int msvdx_poll_mtx_irq(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long status;
+ platform_context_plb_t *platform =
+ (platform_context_plb_t *)context->platform_context;
+ int poll_cnt = 100;
+
+ EMGD_TRACE_ENTER;
+
+ while (poll_cnt) {
+ status = EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+ if (status & MSVDX_MMU_FAULT_IRQ_MASK) {
+ EMGD_DEBUG("MMU FAULT Interrupt");
+ /* Pause the MMU */
+ EMGD_WRITE32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
+ mmio + PSB_MSVDX_MMU_CONTROL0);
+
+ /* Clear interrupt bit */
+ EMGD_WRITE32(MSVDX_MMU_FAULT_IRQ_MASK,
+ mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ platform->msvdx_needs_reset = 1;
+ DUMP_ALL_MESSAGES(context);
+ return 0;
+ } else if (status & MSVDX_MTX_IRQ_MASK) {
+ /* Clear all interrupt bits */
+ EMGD_WRITE32(0xffffffff, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ msvdx_mtx_interrupt_plb(context);
+ return 0;
+ } else if (status) {
+ /* Might want to make this debug only. */
+ if (status & 0x00000001) EMGD_DEBUG("IRQ - VEC_END_OF_SLICE");
+ if (status & 0x00000002) EMGD_DEBUG("IRQ - VEC_ERROR_DETECTETED_SR");
+ if (status & 0x00000004) EMGD_DEBUG("IRQ - VEC_ERROR_DETECTETED_ENTDEC");
+ if (status & 0x00000008) EMGD_DEBUG("IRQ - VEC_RENDEC_ERROR");
+ if (status & 0x00000010) EMGD_DEBUG("IRQ - VEC_RENDEC_OVERFLOW");
+ if (status & 0x00000020) EMGD_DEBUG("IRQ - VEC_RENDEC_UNDERFLOW");
+ if (status & 0x00000040) EMGD_DEBUG("IRQ - VEC_RENDEC_MTXBLOCK");
+ if (status & 0x00000080) EMGD_DEBUG("IRQ - VEC_RENDEC_END_OF_SLICE");
+ if (status & 0x00000100) EMGD_DEBUG("IRQ - MMU_FAULT_IRQ");
+ if (status & 0x00000200) EMGD_DEBUG("IRQ - MMU_FAULT_IRQ");
+ if (status & 0x00000400) EMGD_DEBUG("IRQ - MMU_FAULT_IRQ");
+ if (status & 0x00000800) EMGD_DEBUG("IRQ - MMU_FAULT_IRQ");
+ if (status & 0x00001000) EMGD_DEBUG("IRQ - FE_WDT_CM0");
+ if (status & 0x00002000) EMGD_DEBUG("IRQ - FE_WDT_CM1");
+ if (status & 0x00004000) EMGD_DEBUG("IRQ - MTX_IRQ");
+ if (status & 0x00008000) EMGD_DEBUG("IRQ - MTX_GPIO_IRQ");
+ if (status & 0x00010000) EMGD_DEBUG("IRQ - VDMC_IRQ");
+ if (status & 0x00020000) EMGD_DEBUG("IRQ - VDEB_PICTURE_DONE_IRQ");
+ if (status & 0x00040000) EMGD_DEBUG("IRQ - VDEB_SLICE_DONE_IRQ");
+ if (status & 0x00080000) EMGD_DEBUG("IRQ - VDEB_FLUSH_DONE_IRQ");
+ if (status & 0x00100000) EMGD_DEBUG("IRQ - DMAC_IRQ");
+ if (status & 0x00200000) EMGD_DEBUG("IRQ - DMAC_IRQ");
+ if (status & 0x00400000) EMGD_DEBUG("IRQ - DMAC_IRQ");
+ if (status & 0x00800000) EMGD_DEBUG("IRQ - VDEB_FAULT_IRQ");
+ if (status & 0x01000000) EMGD_DEBUG("IRQ - SYS_COMMAND_TIMEOUT_IRQ");
+ if (status & 0x02000000) EMGD_DEBUG("IRQ - SYS_READ_TIMEOUT_IRQ");
+ if (status & 0x04000000) EMGD_DEBUG("IRQ - MTX_COMMAND_TIMEOUT_IRQ");
+ if (status & 0x08000000) EMGD_DEBUG("IRQ - MTX_READ_TIMEOUT_IRQ");
+ if (status & 0x10000000) EMGD_DEBUG("IRQ - SYS_WDT");
+ if (status & 0x20000000) EMGD_DEBUG("IRQ - BE_WDT_CM0");
+ if (status & 0x40000000) EMGD_DEBUG("IRQ - BE_WDT_CM1");
+ if (status & 0x80000000) EMGD_DEBUG("IRQ - VEC_RENDEC_SLICE_SKIPPED");
+
+ EMGD_DEBUG(" Watchdog Control = 0x%x 0x%x 0x%x",
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0670),
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0674),
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0678));
+
+ /* Clear the interrupt */
+ EMGD_WRITE32(status, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ return 0;
+ }
+
+ poll_cnt--;
+ OS_SLEEP(10);
+ }
+
+ EMGD_ERROR("Timout polling interrupt status.");
+ return 1;
+}
+
+
+/*
+ * msvdx_mtx_irq
+ *
+ * Process a MTX interrupt. Look at the interrupt status bits
+ * and do the processing dictated by the bits. Currently only
+ * two interrupts are really handled:
+ * MMU Fault, which pauses the MMU
+ * MTX IRQ, which then processes any firmware to hosts messages
+ * Other interrupts will output a debugging message. These are fault
+ * conditions that are not handled.
+ *
+ * return 0 if the IRQ was handled
+ * return 1 if it wasn't
+ */
+//static void msvdx_mtx_irq(struct drm_device *dev)
+IMG_BOOL msvdx_mtx_isr(IMG_VOID *pvData)
+{
+ struct drm_device *dev;
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ unsigned char *mmio;
+ platform_context_plb_t *platform;
+ unsigned long msvdx_stat,temp;
+
+ //EMGD_TRACE_ENTER;
+ dev = (struct drm_device *)pvData;
+ priv = dev->dev_private;
+ context = priv->context;
+ mmio = context->device_context.virt_mmadr;
+ platform = context->platform_context;
+
+ msvdx_stat = EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_STATUS);
+
+ //printk(KERN_ALERT "MSVDX_IRQ\n");
+
+ if (msvdx_stat & MSVDX_MMU_FAULT_IRQ_MASK) {
+ EMGD_DEBUG(KERN_ERR "MMU FAULT Interrupt\n");
+ EMGD_DEBUG(KERN_ERR "INTERRUPT_STATUS Register=0x%x\n",msvdx_stat);
+ temp = EMGD_READ32(mmio + PSB_MSVDX_MMU_DIR_LIST_BASE0);
+ EMGD_DEBUG(KERN_ERR "MMU_DIR_LIST_BASE0 = 0x%x\n", temp);
+ temp = EMGD_READ32(mmio + PSB_MSVDX_MMU_DIR_LIST_BASE1);
+ EMGD_DEBUG(KERN_ERR "MMU_DIR_LIST_BASE1 = 0x%x\n", temp);
+ temp = EMGD_READ32(mmio + PSB_MSVDX_MMU_DIR_LIST_BASE2);
+ EMGD_DEBUG(KERN_ERR "MMU_DIR_LIST_BASE2 = 0x%x\n", temp);
+ temp = EMGD_READ32(mmio + PSB_MSVDX_MMU_DIR_LIST_BASE3);
+ EMGD_DEBUG(KERN_ERR "MMU_DIR_LIST_BASE3 = 0x%x\n", temp);
+ /* Pause the MMU */
+ EMGD_WRITE32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
+ mmio + PSB_MSVDX_MMU_CONTROL0);
+
+
+ EMGD_WRITE32(MSVDX_MMU_FAULT_IRQ_MASK,
+ mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ //printk(KERN_INFO "FAULT ADDR=%x\n", EMGD_READ32(mmio + PSB_MSVDX_MMU_STATUS));
+ platform->msvdx_needs_reset = 1;
+ DUMP_ALL_MESSAGES(context);
+ //return 0;
+ } else if (msvdx_stat & MSVDX_MTX_IRQ_MASK) {
+ /* Read the firmware to host messages */
+
+ EMGD_WRITE32(0xffffffff, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ EMGD_READ32(mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+ msvdx_mtx_interrupt_plb(context);
+ //return 0;
+ } else if (msvdx_stat) {
+ /*
+ * Print a debug message for any other interrupt cases.
+ */
+ if (msvdx_stat & 0x00000001) printk(KERN_INFO "IRQ - VEC_END_OF_SLICE\n");
+ if (msvdx_stat & 0x00000002) printk(KERN_INFO "IRQ - VEC_ERROR_DETECTETED_SR\n");
+ if (msvdx_stat & 0x00000004) printk(KERN_INFO "IRQ - VEC_ERROR_DETECTETED_ENTDEC\n");
+ if (msvdx_stat & 0x00000008) printk(KERN_INFO "IRQ - VEC_RENDEC_ERROR\n");
+ if (msvdx_stat & 0x00000010) printk(KERN_INFO "IRQ - VEC_RENDEC_OVERFLOW\n");
+ if (msvdx_stat & 0x00000020) printk(KERN_INFO "IRQ - VEC_RENDEC_UNDERFLOW\n");
+ if (msvdx_stat & 0x00000040) printk(KERN_INFO "IRQ - VEC_RENDEC_MTXBLOCK\n");
+ if (msvdx_stat & 0x00000080) printk(KERN_INFO "IRQ - VEC_RENDEC_END_OF_SLICE\n");
+ if (msvdx_stat & 0x00000100) printk(KERN_INFO "IRQ - MMU_FAULT_IRQ\n");
+ if (msvdx_stat & 0x00000200) printk(KERN_INFO "IRQ - MMU_FAULT_IRQ\n");
+ if (msvdx_stat & 0x00000400) printk(KERN_INFO "IRQ - MMU_FAULT_IRQ\n");
+ if (msvdx_stat & 0x00000800) printk(KERN_INFO "IRQ - MMU_FAULT_IRQ\n");
+ if (msvdx_stat & 0x00001000) printk(KERN_INFO "IRQ - FE_WDT_CM0\n");
+ if (msvdx_stat & 0x00002000) printk(KERN_INFO "IRQ - FE_WDT_CM1\n");
+ if (msvdx_stat & 0x00004000) printk(KERN_INFO "IRQ - MTX_IRQ\n");
+ if (msvdx_stat & 0x00008000) printk(KERN_INFO "IRQ - MTX_GPIO_IRQ\n");
+ if (msvdx_stat & 0x00010000) printk(KERN_INFO "IRQ - VDMC_IRQ\n");
+ if (msvdx_stat & 0x00020000) printk(KERN_INFO "IRQ - VDEB_PICTURE_DONE_IRQ\n");
+ if (msvdx_stat & 0x00040000) printk(KERN_INFO "IRQ - VDEB_SLICE_DONE_IRQ\n");
+ if (msvdx_stat & 0x00080000) printk(KERN_INFO "IRQ - VDEB_FLUSH_DONE_IRQ\n");
+ if (msvdx_stat & 0x00100000) printk(KERN_INFO "IRQ - DMAC_IRQ\n");
+ if (msvdx_stat & 0x00200000) printk(KERN_INFO "IRQ - DMAC_IRQ\n");
+ if (msvdx_stat & 0x00400000) printk(KERN_INFO "IRQ - DMAC_IRQ\n");
+ if (msvdx_stat & 0x00800000) printk(KERN_INFO "IRQ - VDEB_FAULT_IRQ\n");
+ if (msvdx_stat & 0x01000000) printk(KERN_INFO "IRQ - SYS_COMMAND_TIMEOUT_IRQ\n");
+ if (msvdx_stat & 0x02000000) printk(KERN_INFO "IRQ - SYS_READ_TIMEOUT_IRQ\n");
+ if (msvdx_stat & 0x04000000) printk(KERN_INFO "IRQ - MTX_COMMAND_TIMEOUT_IRQ\n");
+ if (msvdx_stat & 0x08000000) printk(KERN_INFO "IRQ - MTX_READ_TIMEOUT_IRQ\n");
+ if (msvdx_stat & 0x10000000) printk(KERN_INFO "IRQ - SYS_WDT\n");
+ if (msvdx_stat & 0x20000000) printk(KERN_INFO "IRQ - BE_WDT_CM0\n");
+ if (msvdx_stat & 0x40000000) printk(KERN_INFO "IRQ - BE_WDT_CM1\n");
+ if (msvdx_stat & 0x80000000) printk(KERN_INFO "IRQ - VEC_RENDEC_SLICE_SKIPPED\n");
+
+ printk(KERN_INFO " Watchdog Control = 0x%x 0x%x 0x%x\n",
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0670),
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0674),
+ EMGD_READ32(mmio + MSVDX_BASE + 0x0678));
+
+ return 0;
+ }
+ /*
+ else {
+ return ;
+ } */
+ return IMG_TRUE;
+}
+
+
+#ifdef DEBUG_BUILD_TYPE
+
+static void dump_all_messages(igd_context_t *context)
+{
+ unsigned long msg;
+ unsigned long submit_size;
+ unsigned long num_words;
+
+ if (save_msg) {
+ for (msg = 0; msg < save_msg_cnt; msg++) {
+ submit_size = (save_msg[0] & 0x000000ff);
+ num_words = ((save_msg[0] & 0xff) + 3) / 4;
+
+ DEBUG_MESG_INFO(context, save_msg, num_words);
+
+ save_msg += (submit_size / sizeof(unsigned long));
+ }
+
+ save_msg = NULL;
+ save_msg_cnt = 0;
+ }
+}
+
+/*
+ * This function is for debugging firmware messages. It should not be part of the
+ * production code. Make sure it is removed (if def'ed out) before building a
+ * production version.
+ */
+
+static void debug_mesg_info(igd_context_t *context,
+ unsigned long *msg,
+ unsigned long num_words)
+{
+ unsigned long msg_size;
+ unsigned char msg_id;
+ unsigned short buffer_size;
+ unsigned long buffer_address;
+ unsigned short last_mb;
+ unsigned short first_mb;
+ unsigned long *cmd_base;
+
+ msg_size = (msg[0] & 0xff);
+ msg_id = (unsigned char)((msg[0] & 0xff00) >> 8);
+ buffer_size = (unsigned short)((msg[0] & 0xffff0000) >> 16);
+
+ EMGD_DEBUG("MSG: size = %ld, id = 0x%x, buffer_size = %d",
+ msg_size, msg_id, buffer_size);
+ if (msg_size > 4) {
+ EMGD_DEBUG("MSG: MMUPTD = 0x%08lx", msg[1]);
+ }
+ if (msg_size > 8) {
+ buffer_address = msg[2];
+ /* FIXME - The following line of code is wrong. The buffer_address is
+ * not an offset to GMM-allocated memory, and so cmd_base is always
+ * NULL (see fixme in lldma_dump()). The buffer_address is an offset
+ * within a larger buffer allocated through the user-space PVR2D code
+ * (and thus, allocated by PVRSRV). Unless the PVRSRV mapping between
+ * buffer_address and a kernel-visible address can be found, this
+ * buffer cannot be accessed, as this code is being called from a
+ * kernel interrupt handler, which has no access to a user-space
+ * process's memory.
+ */
+ cmd_base = (unsigned long *)context->dispatch.gmm_map(buffer_address);
+ EMGD_DEBUG("MSG: Buffer Offset = 0x%08lx", buffer_address);
+ EMGD_DEBUG("MSG: Context id = 0x%lx", msg[3]);
+ EMGD_DEBUG("MSG: Fence value = 0x%lx", msg[4]);
+ EMGD_DEBUG("MSG: Operating Mode = 0x%lx", msg[5]);
+ last_mb = (unsigned short)((msg[6] & 0xffff0000) >> 16);
+ first_mb = (unsigned short)(msg[6] & 0x0000ffff);
+ EMGD_DEBUG("MSG: First MB = %d, last mb = %d", first_mb, last_mb);
+ EMGD_DEBUG("MSG: Flags = 0x%lx", msg[7]);
+
+ /* Dump some of the lldma contents here */
+ LLDMA_DUMP(cmd_base, buffer_address);
+ }
+}
+
+
+/* To eliminate warnings, am temporarily #ifdef'ing this function. Please
+ * remove the #ifdef when this function is to be used.
+ */
+#ifdef USE_DEBUG_DUMP
+/*
+ * This function dumps the to firmware message buffer.
+ */
+static void debug_dump(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long read_idx, write_idx;
+ unsigned long i;
+ platform_context_plb_t *platform;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+ read_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_HOST_RD_INDEX);
+ write_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_HOST_WRT_INDEX);
+ EMGD_DEBUG("HOST buffer: RDIDX 0x%08lx WRIDX 0x%08lx, %lu",
+ read_idx, write_idx, platform->host_buf_size);
+ for (i = 0; (i < read_idx || i < write_idx); i++) {
+ unsigned long value =
+ EMGD_READ32(mmio + platform->host_buf_offset + (i <<2));
+ EMGD_DEBUG(" %02lx: 0x%08lx", i, value);
+ }
+
+ read_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_MTX_RD_INDEX);
+ write_idx = EMGD_READ32(mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+ EMGD_DEBUG("MTX buffer: RDIDX 0x%08lx WRIDX 0x%08lx, %lu",
+ read_idx, write_idx, platform->mtx_buf_size);
+ for (i = 0; (i < read_idx || i < write_idx); i++) {
+ unsigned long value =
+ EMGD_READ32(mmio + platform->mtx_buf_offset + (i <<2));
+ EMGD_DEBUG(" %02lx: 0x%08lx", i, value);
+ }
+}
+#endif
+
+unsigned long lldma_decode(unsigned long val,
+ unsigned long to,
+ unsigned long from)
+{
+ if (to < 31) {
+ val &= ~(0xffffffff << (to + 1));
+ }
+ val = val >> from;
+
+ return val;
+}
+
+static void lldma_dump(unsigned long *cmd_base, unsigned long offset)
+{
+ int i;
+
+ /* FIXME - When the code in debug_mesg_info() is fixed (see the fixme in
+ * that function), the following if-return code can be removed.
+ */
+ if (cmd_base == NULL) {
+ return;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (i == 0) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: BSWAP = %ld", offset, lldma_decode(*cmd_base, 31, 31));
+ EMGD_DEBUG(" LLDMA: DIR = %ld", lldma_decode(*cmd_base, 30, 30));
+ EMGD_DEBUG(" LLDMA: PW = %ld", lldma_decode(*cmd_base, 29, 28));
+ } else if (i == 1) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: List_Fin = %ld", offset+1, lldma_decode(*cmd_base, 31, 31));
+ EMGD_DEBUG(" LLDMA: List_INT = %ld", lldma_decode(*cmd_base, 30, 30));
+ EMGD_DEBUG(" LLDMA: PI = %ld", lldma_decode(*cmd_base, 18, 17));
+ EMGD_DEBUG(" LLDMA: INCR = %ld", lldma_decode(*cmd_base, 16, 16));
+ EMGD_DEBUG(" LLDMA: LEN = %ld", lldma_decode(*cmd_base, 15, 0));
+ } else if (i == 2) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: ADDR = 0x%lx", offset+2, lldma_decode(*cmd_base, 22, 0));
+ } else if (i == 3) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: ACC_DEL = %ld", offset+3, lldma_decode(*cmd_base, 31, 29));
+ EMGD_DEBUG(" LLDMA: BURST = %ld", lldma_decode(*cmd_base, 28, 26));
+ EMGD_DEBUG(" LLDMA: EXT_SA = 0x%lx", lldma_decode(*cmd_base, 3, 0));
+ } else if (i == 4) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: 2D_MODE = %ld", offset+4, lldma_decode(*cmd_base, 16, 16));
+ EMGD_DEBUG(" LLDMA: REP_CNT = %ld", lldma_decode(*cmd_base, 10, 0));
+ } else if (i == 5) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: LINE_ADD = 0x%lx", offset+5, lldma_decode(*cmd_base, 25, 16));
+ EMGD_DEBUG(" LLDMA: ROW_LEN = %ld", lldma_decode(*cmd_base, 9, 0));
+ } else if (i == 6) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: SA = 0x%lx", offset+6, lldma_decode(*cmd_base, 31, 0));
+ } else if (i == 7) {
+ EMGD_DEBUG(" 0x%08lx LLDMA: LISTPTR = 0x%lx", offset+7, lldma_decode(*cmd_base, 27, 0));
+ }
+ cmd_base++;
+ }
+}
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
new file mode 100644
index 0000000..39932ca
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
@@ -0,0 +1,1753 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_init.c
+ * $Revision: 1.32 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Initialize the MSVDX video engine. This loads the MTX firmware and
+ * starts a MTX thread running the firmware.
+ * The host communicates with the firmware via messages. The following
+ * messages are supported:
+ * INIT -> MTX
+ * RENDER -> MTX
+ * DEBLOCK -> MTX
+ * BUBBLE -> MTX
+ * TEST1 -> MTX
+ * TEST2 -> MTX
+ * CMD_COMPLETED <- MTX
+ * CMD_COMPLTED_BATCH <- MTX
+ * DEBLOCK_REQUIRED <- MTX
+ * TEST_RESPONSE <- MTX
+ * ACK <- MTX
+ * CMD_FAILED <- MTX
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+#include <msvdx.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+#include <drm/drm.h>
+#include <drm_emgd_private.h>
+#include <emgd_drm.h>
+#include <osfunc.h> /* for OSFlushCPUCacheKM() */
+#include "msvdx_pvr.h"
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))
+#include <linux/module.h>
+#include <linux/export.h>
+#endif
+struct drm_device *gpDrmDevice = NULL;
+static int init_msvdx_first_time = 1;
+static unsigned long msvdx_compositor_mmu_base = 0;
+extern void send_to_mtx(igd_context_t *context, unsigned long *init_msg);
+extern int process_mtx_messages(igd_context_t *context,
+ unsigned long *mtx_msgs, unsigned long mtx_msg_cnt,
+ unsigned long fence);
+
+extern unsigned long populate_fence_id(igd_context_t *context, unsigned long *mtx_msgs,
+ unsigned long mtx_msg_cnt);
+extern int msvdx_dequeue_send(igd_context_t *context);
+extern int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1,
+ unsigned long size0, unsigned long size1);
+
+static int poll_mtx_irq(igd_context_t *context);
+static int reg_ready_psb(igd_context_t *context, unsigned long reg,
+ unsigned long mask, unsigned long value);
+int context_count = 0;
+
+void msvdx_reset_plb(igd_context_t *context);
+
+static msvdx_fw_t *priv_fw = NULL;
+
+extern unsigned long jiffies_at_last_dequeue;
+static int msvdx_fw_dma_upload = 1;
+
+MODULE_PARM_DESC(msvdx_dma_upload, "MSVDX: upload firmware using DMA");
+module_param_named(msvdx_dma_upload, msvdx_fw_dma_upload, int, 0600);
+unsigned long LastClockState;
+
+///// HHP TODO: Move to separate .h file
+#define MSVDX_MTX_DEBUG PSB_MSVDX_MTX_RAM_BANK
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_MASK (0x00000004)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_LSBMASK (0x00000001)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_SHIFT (2)
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_MASK (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_LSBMASK (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_SHIFT (0)
+
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_MASK (0x07000000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_SHIFT (24)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_MASK (0x00020000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_SHIFT (17)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_MASK (0x00010000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_SHIFT (16)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_MASK (0x0000FFFF)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_SHIFT (0)
+
+//#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_MASK (0x00001000)
+//#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_SHIFT (12)
+
+#define PSB_MSVDX_CONTROL_DMAC_CH0_SELECT_MASK (0x00001000)
+#define PSB_MSVDX_CONTROL_DMAC_CH0_SELECT_SHIFT (12)
+
+
+#define DMAC_DMAC_COUNT_BSWAP_LSBMASK (0x00000001)
+#define DMAC_DMAC_COUNT_BSWAP_SHIFT (30)
+
+#define DMAC_DMAC_COUNT_PW_LSBMASK (0x00000003)
+#define DMAC_DMAC_COUNT_PW_SHIFT (27)
+
+#define DMAC_DMAC_COUNT_DIR_LSBMASK (0x00000001)
+#define DMAC_DMAC_COUNT_DIR_SHIFT (26)
+
+#define DMAC_DMAC_COUNT_PI_LSBMASK (0x00000003)
+#define DMAC_DMAC_COUNT_PI_SHIFT (24)
+
+#define DMAC_DMAC_COUNT_EN_MASK (0x00010000)
+#define DMAC_DMAC_COUNT_EN_SHIFT (16)
+
+#define DMAC_DMAC_COUNT_CNT_LSBMASK (0x0000FFFF)
+#define DMAC_DMAC_COUNT_CNT_SHIFT (0)
+
+
+#define DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK (0x00000007)
+#define DMAC_DMAC_PERIPH_ACC_DEL_SHIFT (29)
+
+#define DMAC_DMAC_PERIPH_INCR_LSBMASK (0x00000001)
+#define DMAC_DMAC_PERIPH_INCR_SHIFT (27)
+
+#define DMAC_DMAC_PERIPH_BURST_LSBMASK (0x00000007)
+#define DMAC_DMAC_PERIPH_BURST_SHIFT (24)
+
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_MASK (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_LSBMASK (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_SHIFT (0)
+
+
+#define DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK (0x00020000)
+
+/*watch dog for FE and BE*/
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_OFFSET (MSVDX_BASE + 0x0064)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_MASK (0x00060000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_SHIFT (17)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_MASK (0x00010000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_SHIFT (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_MASK (0x00003000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_SHIFT (12)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_MASK (0x00000100)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_SHIFT (8)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_MASK (0x00000030)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_SHIFT (4)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_MASK (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_LSBMASK (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_SHIFT (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_OFFSET (MSVDX_BASE + 0x0068)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDTIMER, FE_WDT_COUNTER
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_SHIFT (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_OFFSET (MSVDX_BASE + 0x006C)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_MASK (0xFFFF0000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_SHIFT (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_OFFSET (MSVDX_BASE + 0x0070)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_MASK (0x001E0000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_LSBMASK (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_SHIFT (17)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_MASK (0x00010000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_SHIFT (16)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_MASK (0x00000100)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_SHIFT (8)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_MASK (0x000000F0)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_LSBMASK (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_SHIFT (4)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_MASK (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_LSBMASK (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_OFFSET (MSVDX_BASE + 0x0074)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDTIMER, BE_WDT_COUNTER
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_OFFSET (MSVDX_BASE + 0x0078)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH, BE_WDT_CM0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_SHIFT (0)
+/*watch dog end*/
+
+#define FW_SIZE 16128
+#define MAX_FW_SIZE 16 * 1024
+
+enum {
+ MSVDX_DMAC_BSWAP_NO_SWAP = 0x0, /* No byte swapping will be performed */
+ MSVDX_DMAC_BSWAP_REVERSE = 0x1, /* Byte order will be reversed */
+};
+
+enum {
+ MSVDX_DMAC_DIR_MEM_TO_PERIPH = 0x0, /* Data from memory to peripheral */
+ MSVDX_DMAC_DIR_PERIPH_TO_MEM = 0x1, /* Data from peripheral to memory */
+};
+
+enum {
+ MSVDX_DMAC_ACC_DEL_0 = 0x0, /* Access delay zero clock cycles */
+ MSVDX_DMAC_ACC_DEL_256 = 0x1, /* Access delay 256 clock cycles */
+ MSVDX_DMAC_ACC_DEL_512 = 0x2, /* Access delay 512 clock cycles */
+ MSVDX_DMAC_ACC_DEL_768 = 0x3, /* Access delay 768 clock cycles */
+ MSVDX_DMAC_ACC_DEL_1024 = 0x4, /* Access delay 1024 clock cycles */
+ MSVDX_DMAC_ACC_DEL_1280 = 0x5, /* Access delay 1280 clock cycles */
+ MSVDX_DMAC_ACC_DEL_1536 = 0x6, /* Access delay 1536 clock cycles */
+ MSVDX_DMAC_ACC_DEL_1792 = 0x7, /* Access delay 1792 clock cycles */
+};
+
+enum {
+ MSVDX_DMAC_INCR_OFF = 0x0, /* Static peripheral address */
+ MSVDX_DMAC_INCR_ON = 0x1, /* Incrementing peripheral address */
+};
+
+enum {
+ MSVDX_DMAC_BURST_0 = 0x0, /* burst size of 0 */
+ MSVDX_DMAC_BURST_1 = 0x1, /* burst size of 1 */
+ MSVDX_DMAC_BURST_2 = 0x2, /* burst size of 2 */
+ MSVDX_DMAC_BURST_3 = 0x3, /* burst size of 3 */
+ MSVDX_DMAC_BURST_4 = 0x4, /* burst size of 4 */
+ MSVDX_DMAC_BURST_5 = 0x5, /* burst size of 5 */
+ MSVDX_DMAC_BURST_6 = 0x6, /* burst size of 6 */
+ MSVDX_DMAC_BURST_7 = 0x7, /* burst size of 7 */
+};
+
+/* DMAC control */
+#define MSVDX_DMAC_VALUE_COUNT(BSWAP,PW,DIR,PERIPH_INCR,COUNT) \
+ (((BSWAP) & DMAC_DMAC_COUNT_BSWAP_LSBMASK) << DMAC_DMAC_COUNT_BSWAP_SHIFT) | \
+ (((PW) & DMAC_DMAC_COUNT_PW_LSBMASK) << DMAC_DMAC_COUNT_PW_SHIFT) | \
+ (((DIR) & DMAC_DMAC_COUNT_DIR_LSBMASK) << DMAC_DMAC_COUNT_DIR_SHIFT) | \
+ (((PERIPH_INCR) & DMAC_DMAC_COUNT_PI_LSBMASK) << DMAC_DMAC_COUNT_PI_SHIFT) | \
+ (((COUNT) & DMAC_DMAC_COUNT_CNT_LSBMASK) << DMAC_DMAC_COUNT_CNT_SHIFT)
+
+#define MSVDX_DMAC_VALUE_PERIPH_PARAM(ACC_DEL,INCR,BURST) \
+ (((ACC_DEL) & DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK) << DMAC_DMAC_PERIPH_ACC_DEL_SHIFT) | \
+ (((INCR) & DMAC_DMAC_PERIPH_INCR_LSBMASK) << DMAC_DMAC_PERIPH_INCR_SHIFT) | \
+ (((BURST) & DMAC_DMAC_PERIPH_BURST_LSBMASK) << DMAC_DMAC_PERIPH_BURST_SHIFT)
+
+
+
+#define REGIO_READ_FIELD(reg_val, reg, field) \
+ ((reg_val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
+
+#define REGIO_WRITE_FIELD(reg_val, reg, field, value) \
+ (reg_val) = \
+ ((reg_val) & ~(reg##_##field##_MASK)) | \
+ (((value) << (reg##_##field##_SHIFT)) & (reg##_##field##_MASK));
+
+#define REGIO_WRITE_FIELD_LITE(reg_val, reg, field, value) \
+ (reg_val) = \
+ ((reg_val) | ((value) << (reg##_##field##_SHIFT)));
+
+#define STACKGUARDWORD (0x10101010)
+
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK \
+ (0x00000001)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK \
+ (0x00000002)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK \
+ (0x00000004)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK \
+ (0x00000008)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK \
+ (0x00000010)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK \
+ (0x00000020)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK \
+ (0x00000040)
+
+typedef struct _msvdx_context {
+ unsigned long context_id;
+ void *drm_file_priv;
+} msvdx_context_t;
+
+#define MSVDX_MAXIMUM_CONTEXT 8
+
+static msvdx_context_t msvdx_contexts[MSVDX_MAXIMUM_CONTEXT];
+
+
+int msvdx_init_compositor_mmu(unsigned long mmu_base) {
+ msvdx_compositor_mmu_base = mmu_base;
+ return 0;
+}
+
+/*
+ * Map and copy the firmware image to the shared SGX heap.
+ */
+static int msvdx_map_fw(uint32_t size)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ platform_context_plb_t *platform;
+ PVRSRV_KERNEL_MEM_INFO *mem_info;
+ unsigned long alloc_size;
+ uint32_t *last_word;
+ void *mapped_fw_addr;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ /* Round up as DMA's can overrun a page */
+ alloc_size = (size + 8192) & ~0x0fff;
+
+ /* Verify there is enough memory for the firmware text */
+ if( ((priv_fw->fw_text_size * 4) <= 0) ||
+ ((priv_fw->fw_text_size * 4) > size) ) {
+ return -EINVAL;
+ }
+
+ if( ((priv_fw->fw_data_location - MTX_DATA_BASE) <=0) ||
+ ((priv_fw->fw_data_location - MTX_DATA_BASE) > size) ) {
+ return -EINVAL;
+ }
+
+ /* Verify there is enough memory for the firmware data */
+ if( ((priv_fw->fw_data_size * 4) <= 0) ||
+ ((priv_fw->fw_data_size * 4) > (size -
+ (priv_fw->fw_data_location - MTX_DATA_BASE))) ) {
+ return -EINVAL;
+ }
+
+ mem_info = platform->msvdx_pvr->fw_mem_info;
+ if (!mem_info) {
+ mem_info = msvdx_pvr_alloc_devmem(alloc_size, "MSVDX firmware");
+ if (!mem_info) {
+ printk(KERN_ERR "[EMGD] MSVDX: Failed to allocate %u "
+ "bytes from SGX heap\n",
+ (unsigned int)alloc_size);
+ return -ENOMEM;
+ }
+ platform->msvdx_pvr->fw_mem_info = mem_info;
+ }
+
+ mapped_fw_addr = (unsigned long *)mem_info->pvLinAddrKM;
+
+ memset(mapped_fw_addr, 0x00, size);
+
+ memcpy(mapped_fw_addr, priv_fw->fw_text, priv_fw->fw_text_size * 4);
+
+ memcpy(mapped_fw_addr + (priv_fw->fw_data_location - MTX_DATA_BASE),
+ priv_fw->fw_data, priv_fw->fw_data_size * 4);
+
+ /*
+ * Write a known value to the last word in MTX memory. Useful for
+ * detection of stack overruns.
+ */
+ last_word = (uint32_t *)(mapped_fw_addr + size - sizeof(uint32_t));
+ *last_word = STACKGUARDWORD;
+
+ OSFlushCPUCacheRangeKM(mapped_fw_addr, mapped_fw_addr + size);
+
+ return 0;
+}
+
+static void msvdx_get_mtx_control_from_dash(igd_context_t *context)
+{
+ platform_context_plb_t *platform;
+ unsigned char *mmio;
+ int count = 0;
+ uint32_t reg_val = 0;
+
+ mmio = context->device_context.virt_mmadr;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_IS_SLAVE, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_GPIO_IN, 0x02);
+ EMGD_WRITE32(reg_val, mmio + MSVDX_MTX_DEBUG);
+
+ do { reg_val = EMGD_READ32(mmio + MSVDX_MTX_DEBUG);
+ count++;
+ } while (((reg_val & 0x18) != 0) && count < 50000);
+
+ if (count >= 50000)
+ printk(KERN_ERR "[EMGD] MSVDX: timeout in %s\n", __FUNCTION__);
+
+ /* Save the RAM access control register */
+ platform->msvdx_dash_access_ctrl =
+ EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+}
+
+static void msvdx_release_mtx_control_from_dash(igd_context_t *context)
+{
+ platform_context_plb_t *platform;
+ unsigned char *mmio;
+
+ mmio = context->device_context.virt_mmadr;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ /* Restore access control */
+ EMGD_WRITE32(platform->msvdx_dash_access_ctrl,
+ mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ /* Release the bus */
+ EMGD_WRITE32(0x04, mmio + MSVDX_MTX_DEBUG);
+}
+
+static int msvdx_upload_fw_dma(uint32_t address)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ platform_context_plb_t *platform;
+ unsigned long addr;
+ unsigned char *mmio;
+ uint32_t core_rev;
+ uint32_t size;
+ uint32_t cmd;
+ uint32_t count_reg;
+ uint32_t dma_channel;
+ uint32_t reg_val;
+ int ret;
+
+ printk(KERN_INFO "MSVDX: Upload firmware by DMA\n");
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ mmio = context->device_context.virt_mmadr;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ dma_channel = 0; /* Use DMA channel 0 */
+
+ core_rev = EMGD_READ32(mmio + PSB_MSVDX_CORE_REV);
+ if ((core_rev & 0xffffff) < 0x020000)
+ size = 16 * 1024; /* mtx_mem_size */
+ else
+ size = 40 * 1024;
+
+ if (platform->msvdx_pvr && !platform->msvdx_pvr->fw_mem_info) {
+ ret = msvdx_map_fw(size);
+ if (ret)
+ return ret;
+ }
+
+ msvdx_get_mtx_control_from_dash(context);
+
+ /*
+ * dma transfers to/from the mtx have to be 32-bit aligned and in
+ * multiples of 32 bits
+ */
+ EMGD_WRITE32(address, mmio + PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAA);
+
+ reg_val = 0;
+ /* Burst size in multiples of 64 bytes (allowed values are 2 or 4) */
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, BURSTSIZE, 4);
+
+ /* False means write to MTX mem, true means read from MTX mem */
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, RNW, 0);
+
+ /* Begin transfer */
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, ENABLE, 1);
+
+ /* DMA transfer is in size of 32-bit words */
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, LENGTH, (size/4));
+
+ EMGD_WRITE32(reg_val, mmio + PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAC);
+
+ /* Toggle channel 0 usage between MTX and other MSVDX peripherals */
+ reg_val = EMGD_READ32(mmio + PSB_MSVDX_CONTROL);
+ REGIO_WRITE_FIELD(reg_val, PSB_MSVDX_CONTROL, DMAC_CH0_SELECT, 0);
+ EMGD_WRITE32(reg_val, mmio + PSB_MSVDX_CONTROL);
+
+ /* Clear the DMAC Stats */
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_DMAC_IRQ_STAT + (dma_channel * 0x20));
+
+ addr = platform->msvdx_pvr->fw_mem_info->sDevVAddr.uiAddr;
+
+ /* Use bank 0 */
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_MMU_BANK_INDEX);
+
+ /* Use the same MMU PTD as the SGX for MMU base 0 */
+ EMGD_WRITE32(platform->psb_cr_bif_dir_list_base1,
+ mmio + PSB_MSVDX_MMU_DIR_LIST_BASE0);
+
+ /* Invalidate and flush TLB */
+ msvdx_flush_tlb(context);
+
+ EMGD_WRITE32(addr,
+ mmio + PSB_MSVDX_DMAC_SETUP + (dma_channel * 0x20));
+
+ /* Only use single DMA - assert that this is valid */
+ if ((size / 4) >= (1 << 15)) {
+ printk(KERN_ERR "[EMGD] MSVDX: DMA size beyond limit. "
+ "Firmware uploading aborted.\n");
+ msvdx_release_mtx_control_from_dash(context);
+ return -ENODEV;
+ }
+
+ count_reg = MSVDX_DMAC_VALUE_COUNT(MSVDX_DMAC_BSWAP_NO_SWAP,
+ 0, /* 32 bits */
+ MSVDX_DMAC_DIR_MEM_TO_PERIPH,
+ 0,
+ (size / 4));
+
+ /* Set the number of bytes to DMA */
+ EMGD_WRITE32(count_reg,
+ mmio + PSB_MSVDX_DMAC_COUNT + (dma_channel * 0x20));
+
+ cmd = MSVDX_DMAC_VALUE_PERIPH_PARAM(MSVDX_DMAC_ACC_DEL_0,
+ MSVDX_DMAC_INCR_OFF,
+ MSVDX_DMAC_BURST_2);
+ EMGD_WRITE32(cmd, mmio + PSB_MSVDX_DMAC_PERIPH + (dma_channel * 0x20));
+
+ /* Set the destination port for DMA */
+ cmd = 0;
+ REGIO_WRITE_FIELD(cmd, DMAC_DMAC_PERIPHERAL_ADDR,
+ ADDR, (PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAT - MSVDX_BASE));
+ EMGD_WRITE32(cmd,
+ mmio + PSB_MSVDX_DMAC_PERIPHERAL_ADDR + (dma_channel * 0x20));
+
+ /* Finally, rewrite the count register with the enable bit set */
+ EMGD_WRITE32(count_reg | DMAC_DMAC_COUNT_EN_MASK,
+ mmio + PSB_MSVDX_DMAC_COUNT + (dma_channel * 0x20));
+
+ /* Wait for DMA to complete */
+ if (reg_ready_psb(context,
+ PSB_MSVDX_DMAC_IRQ_STAT + (dma_channel * 0x20),
+ DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK,
+ DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK)) {
+ msvdx_release_mtx_control_from_dash(context);
+
+ printk(KERN_ERR "[EMGD] MSVDX: DMA firmware upload timed "
+ "out\n");
+
+ return -ENODEV;
+ }
+
+ /* Assert that the MTX DMA port is done */
+ if (reg_ready_psb(context,
+ PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_CDMAS0, 1, 1)) {
+ msvdx_release_mtx_control_from_dash(context);
+ printk(KERN_ERR "[EMGD] MSVDX: MTX DMA port done timed out\n");
+ return -ENODEV;
+ }
+
+ msvdx_release_mtx_control_from_dash(context);
+ printk(KERN_INFO "[EMGD] MSVDX: firmware DMA upload done!\n");
+ return 0;
+}
+
+/*
+ * Upload firmware using PIO
+*/
+static int msvdx_upload_fw(void)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ unsigned char *mmio;
+ unsigned long ram_bank;
+ unsigned long bank_size;
+ unsigned long current_bank;
+ unsigned long acc_control;
+ unsigned long address;
+ unsigned long fw_size;
+ unsigned long *fw_data;
+ unsigned long ram_id;
+ unsigned long ctrl;
+ unsigned long i;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ mmio = context->device_context.virt_mmadr;
+
+ /*
+ * Get the ram bank size
+ * The banks size seems to be a 4 bit value in the MTX debug register.
+ */
+ ram_bank = EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_BANK);
+ bank_size = (ram_bank & 0x000f0000) >> 16;
+ bank_size = (1 << (bank_size + 2));
+
+ /* Save RAM access control register */
+ acc_control = EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ /* Loop writing text/code to core memory */
+ current_bank = ~0L;
+ address = PC_START_ADDRESS - MTX_CODE_BASE;
+
+ fw_data = priv_fw->fw_text;
+ fw_size = priv_fw->fw_text_size;
+
+ for (i = 0; i < fw_size; i++) {
+ /* Wait for MCMSTAT to become be idle 1 */
+ if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001) == 0) {
+ ram_id = MTX_CORE_CODE_MEM + (address / bank_size);
+ if (ram_id != current_bank) {
+ /*
+ * bits 20:27 - ram bank (CODE_BASE | DATA_BASE)
+ * bits 2:19 - address
+ * bit 1 - enable auto increment
+ * addressing mode
+ */
+ ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) | 0x02;
+ EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ current_bank = ram_id;
+ /* Wait for MCMSTAT to become be idle 1 */
+ reg_ready_psb(context,
+ PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001);
+ }
+
+ address += 4;
+ EMGD_WRITE32(fw_data[i],
+ mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+ } else {
+ printk(KERN_ERR
+ "[EMGD] MSVDX: Timeout waiting for MCMSTAT "
+ "to be idle\n");
+ }
+ }
+
+ /* verify firmware upload. */
+ current_bank = ~0L;
+ address = PC_START_ADDRESS - MTX_CODE_BASE;
+
+ for (i = 0; i < fw_size; i++) {
+ if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001) == 0) {
+ ram_id = MTX_CORE_CODE_MEM + (address / bank_size);
+ if (ram_id != current_bank) {
+ /*
+ * bits 20:27 - ram bank (CODE_BASE | DATA_BASE)
+ * bits 2:19 - address
+ * bit 1 - enable auto increment
+ * addressing mode
+ */
+ ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) | 0x03;
+ EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+ current_bank = ram_id;
+ reg_ready_psb(context,
+ PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001);
+ }
+
+ address += 4;
+ if (EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER) !=
+ fw_data[i]) {
+ printk(KERN_ERR "Verify Error at index %ld\n", i);
+ }
+ } else {
+ printk(KERN_ERR "Timeout waiting for MCMSTAT to be idle while verifying\n");
+ }
+ }
+
+ fw_data = priv_fw->fw_data;
+ fw_size = priv_fw->fw_data_size;
+
+ /* Loop writing data to core memory */
+ current_bank = ~0L;
+ address = priv_fw->fw_data_location - MTX_DATA_BASE;
+
+ for (i = 0; i < fw_size; i++) {
+ if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001) == 0) {
+ ram_id = MTX_CORE_DATA_MEM + (address / bank_size);
+ if (ram_id != current_bank) {
+ /*
+ * bits 20:27 - ram bank (CODE_BASE | DATA_BASE)
+ * bits 2:19 - address
+ * bit 1 - enable auto increment
+ * addressing mode
+ */
+ ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) | 0x02;
+ EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+ current_bank = ram_id;
+ reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
+ 0xffffffff, 0x00000001);
+ }
+
+ address += 4;
+ EMGD_WRITE32(fw_data[i],
+ mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+ } else {
+ printk(KERN_ERR
+ "[EMGD] MSVDX: Timeout waiting for MCMSTAT "
+ "to be idle - data segment\n");
+ }
+ }
+
+ /* Restore the RAM access control register */
+ EMGD_WRITE32(acc_control, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
+ return 0;
+}
+
+int msvdx_query_plb(igd_context_t *context,
+ unsigned long *status)
+{
+ platform_context_plb_t *platform;
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+ *status = 0;
+
+ if (priv_fw) {
+ *status |= VIDEO_STATE_FW_LOADED;
+ }
+
+ if(!platform->rendec_base0 || !platform->rendec_base1) {
+ *status |= VIDEO_STATE_RENDEC_FREED;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int msvdx_pwr_plb(
+ igd_context_t *context,
+ unsigned long power_state)
+{
+ platform_context_plb_t *platform = (platform_context_plb_t *)context->platform_context;
+
+ /* NOTE: The MSVDX need to reset after resume */
+ EMGD_TRACE_ENTER;
+ if(power_state != IGD_POWERSTATE_D0){
+ platform->msvdx_needs_reset = 1;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int msvdx_pre_init_plb(struct drm_device *dev)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+
+ EMGD_TRACE_ENTER;
+
+ gpDrmDevice = dev;
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+
+ context->mod_dispatch.msvdx_pwr = msvdx_pwr_plb;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int msvdx_init_plb(unsigned long base0, unsigned long base1,
+ void *mem_handle_fw, int reset_flag)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ unsigned char *mmio;
+ unsigned long mmu_base_address;
+ unsigned long base_addr0, base_addr1, size0, size1;
+ unsigned long ctrl;
+ int tmp;
+ unsigned long fw_size;
+ unsigned long reg_val;
+ unsigned long irq_flags;
+ msvdx_fw_t *fw = NULL;
+ platform_context_plb_t *platform = NULL;
+ int ret =0;
+ int msvdx_status;
+ PVRSRV_ERROR err;
+ PVRSRV_PER_PROCESS_DATA *ps_data = NULL;
+ IMG_UINT32 pid = 0;
+ PVRSRV_KERNEL_MEM_INFO *mem_info_fw = NULL;
+
+ if(mem_handle_fw) {
+
+ pid = OSGetCurrentProcessIDKM();
+ ps_data = PVRSRVPerProcessData(pid);
+ if (!ps_data) {
+ printk(KERN_ERR "MSVDX: Cannot get process data information");
+ return -1;
+ }
+
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, (void **)&mem_info_fw,
+ (IMG_HANDLE)mem_handle_fw, PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(err != PVRSRV_OK) {
+ printk(KERN_ERR "MSVDX: Cannot get memory context from process data");
+ return -1;
+ }
+
+ }
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ mmio = context->device_context.virt_mmadr;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ // return back if firmware is already loaded
+ if (init_msvdx_first_time) {
+ spin_lock_init(&platform->msvdx_init_plb);
+ } else if(!reset_flag){
+ if (context_count == 0) {
+ spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
+ INIT_LIST_HEAD(&platform->msvdx_queue); // empty the list.
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+ }
+
+ return ret;
+ }
+
+ // Set the status for firmware loading
+ spin_lock(&platform->msvdx_init_plb);
+ platform->msvdx_status = platform->msvdx_status | 1;
+ spin_unlock(&platform->msvdx_init_plb);
+
+ // now wait for message processing to finish
+ do
+ {
+ spin_lock(&platform->msvdx_init_plb);
+ msvdx_status = platform->msvdx_status ;
+ spin_unlock(&platform->msvdx_init_plb);
+ OS_SLEEP(100);
+ }
+ while((msvdx_status & 2));
+
+ if (!priv_fw && mem_handle_fw) {
+ if(!mem_info_fw) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if(mem_info_fw->ui32AllocSize < FW_SIZE) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ fw = (msvdx_fw_t *)mem_info_fw->pvLinAddrKM;
+
+ if((fw->fw_version_size <= 0) || (fw->fw_version_size > 64 )) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ fw_size = sizeof(unsigned long) * fw->fw_text_size;
+ if((fw_size == 0) || (fw_size > MAX_FW_SIZE)) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ fw_size = sizeof(unsigned long) * fw->fw_data_size;
+ if((fw_size == 0) || (fw_size > MAX_FW_SIZE)) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ priv_fw = kzalloc(sizeof(msvdx_fw_t), GFP_KERNEL);
+ if (priv_fw == NULL) {
+ printk(KERN_ERR "MSVDX: Out of memory\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ priv_fw->fw_text_size = fw->fw_text_size;
+ priv_fw->fw_data_size = fw->fw_data_size;
+ priv_fw->fw_version_size = fw->fw_version_size;
+ priv_fw->fw_data_location = fw->fw_data_location;
+
+ fw_size = sizeof(unsigned long) * fw->fw_text_size;
+ priv_fw->fw_text = kmalloc(fw_size, GFP_KERNEL);
+ if (priv_fw->fw_text == NULL) {
+ kfree (priv_fw);
+ priv_fw = NULL;
+ printk(KERN_ERR "MSVDX: Out of memory\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ memcpy(priv_fw->fw_text, (void *) ((unsigned long)mem_info_fw->pvLinAddrKM) +
+ ((unsigned long) fw->fw_text), fw_size);
+
+ fw_size = sizeof(unsigned long) * fw->fw_data_size;
+ priv_fw->fw_data = kmalloc(fw_size, GFP_KERNEL);
+ if (priv_fw->fw_data == NULL) {
+ kfree (priv_fw->fw_text);
+ priv_fw->fw_text = NULL;
+ kfree (priv_fw);
+ priv_fw = NULL;
+ printk(KERN_ERR "MSVDX: Out of memory\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ memcpy(priv_fw->fw_data, (void *) ((unsigned long) mem_info_fw->pvLinAddrKM) +
+ ((unsigned long) fw->fw_data), fw_size);
+
+ priv_fw->fw_version = kzalloc(priv_fw->fw_version_size, GFP_KERNEL);
+ if (priv_fw->fw_version == NULL) {
+ kfree (priv_fw->fw_text);
+ kfree (priv_fw->fw_data);
+ priv_fw->fw_text = NULL;
+ priv_fw->fw_data = NULL;
+ kfree(priv_fw);
+ priv_fw = NULL;
+ printk(KERN_ERR "MSVDX: Out of memory\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ strncpy(priv_fw->fw_version, (char *) (((unsigned long) mem_info_fw->pvLinAddrKM) +
+ ((unsigned long) fw->fw_version)), priv_fw->fw_version_size);
+
+ } else if (!priv_fw) {
+ printk(KERN_INFO "Kernel firmware is not loaded");
+ if(init_msvdx_first_time) {
+ printk(KERN_ERR "!priv_fw at msvdx init 1st");
+ }
+ ret = -1;
+ goto cleanup;
+ }
+
+ if(!context_count || reset_flag) {
+
+ //init_msvdx_first_time = 1;
+ /* Reset MSVDX engine */
+ EMGD_WRITE32(0x00000100, mmio + PSB_MSVDX_CONTROL);
+ reg_ready_psb(context, PSB_MSVDX_CONTROL, 0x00000100, 0);
+
+ /*
+ * Make sure the clock is on.
+ *
+ * Clock enable bits are 0 - 6, with each bit controlling one of the
+ * clocks. For this, make sure all the clocks are enabled.
+ */
+ EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ /* Set default MMU PTD to the same value used by the SGX */
+ if (!msvdx_compositor_mmu_base) {
+ printk(KERN_ERR "XSERVER never sent compositor MMU base!!!");
+ mmu_base_address = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE1);
+ tmp = 0;
+ while(!mmu_base_address){
+ mmu_base_address = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+ ++tmp;
+ if(!tmp%100){
+ printk(KERN_ERR "Cant read SGX Base0 count = %d", tmp);
+ }
+ if(tmp > 10000){
+ printk(KERN_ERR "Giving up reading SGX Base0 from register - expect hang!");
+ break;
+ }
+ }
+ platform->psb_cr_bif_dir_list_base1 = mmu_base_address;
+ } else {
+ platform->psb_cr_bif_dir_list_base1 = msvdx_compositor_mmu_base;
+ }
+
+ EMGD_WRITE32(platform->psb_cr_bif_dir_list_base1,
+ mmio + PSB_MSVDX_MMU_DIR_LIST_BASE0);
+
+ /*
+ * MMU Page size = 12
+ * MMU best count = 7
+ * MMU ADT TTE = 0
+ * MMU TTE threshold = 12
+ */
+ EMGD_WRITE32(0xc070000c, mmio + PSB_MSVDX_MMU_CONTROL1);
+
+
+ /* Flush the directory cache */
+ ctrl = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0) | 0x0C; /* Flush */
+ EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MMU_CONTROL0);
+
+#if 1 //disable watchdog
+ reg_val = 0;
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL, 0x3);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE, 0);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT, 7);
+ printk(KERN_INFO "CTL_MSG: WDT Control value = 0x%x", reg_val);
+ EMGD_WRITE32(0, mmio + MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_OFFSET);
+ EMGD_WRITE32(reg_val, mmio + MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_OFFSET);
+
+ reg_val = 0;
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL, 0x7);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE, 0);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT, 0xd);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT, 7);
+ printk(KERN_INFO "CTL_MSG: WDT Control value = 0x%x", reg_val);
+ EMGD_WRITE32(0, mmio + MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_OFFSET);
+ EMGD_WRITE32(reg_val, mmio + MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_OFFSET);
+
+
+#endif
+
+ /* Enable MMU by removing all bypass bits */
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_MMU_CONTROL0);
+ }
+
+ /* Set up the RENDEC.
+ * The RENDEC requires two blocks of virtual address space so those
+ * must be allocated and then the RENDEC is initialized using those
+ * address ranges.
+ *
+ * RENDEC control0:
+ * bit 3 1 - search MTX_to_MTX header
+ * bit 2 1 - skip next slice
+ * bit 1 1 - flush remaining bit stream
+ * bit 0 1 - initialize RENDEC
+ *
+ * RENDEC control1:
+ * bit 24: 1 - enables data to be transferred through ext. memory
+ * bit 19:18 WR burst size (0 = 32 bytes, 1 = 64 bytes, 2 = 128 bytes)
+ * bit 17:16 RD burst size (0 = 32 bytes, 1 = 64 bytes, 2 = 128 bytes)
+ * bit 7: 0 start size (zero)
+ */
+
+ size0 = RENDEC_A_SIZE;
+ size1 = RENDEC_B_SIZE;
+
+ /*
+ * These allocations need to be undone when shutting down. Where
+ * should they be saved?
+ */
+ if (init_msvdx_first_time) {
+ base_addr0 = base0;
+ base_addr1 = base1;
+
+ //printk(KERN_INFO "get the base_addr=%lx, base_addr1=%lx\n", base_addr0,base_addr1);
+
+ /* Save the offsets so it can be freed and restored later */
+ platform = (platform_context_plb_t *)context->platform_context;
+ platform->rendec_base0 = base_addr0;
+ platform->rendec_base1 = base_addr1;
+
+ init_msvdx_first_time = 0;
+ INIT_LIST_HEAD(&platform->msvdx_queue);
+ spin_lock_init(&platform->msvdx_lock);
+
+ memset(msvdx_contexts, 0x00, sizeof(msvdx_context_t) * MSVDX_MAXIMUM_CONTEXT);
+ } else {
+ /* restore offsets. */
+ platform = (platform_context_plb_t *)context->platform_context;
+ base_addr0 = platform->rendec_base0;
+ base_addr1 = platform->rendec_base1;
+
+ /* Init link list */
+ if(!context_count) {
+ INIT_LIST_HEAD(&platform->msvdx_queue);
+ } else {
+ if(!reset_flag){
+ EMGD_TRACE_EXIT;
+ ret = 0;
+ goto cleanup;
+ }
+ }
+ }
+
+
+ platform->msvdx_busy = 0;
+ EMGD_WRITE32(base_addr0, mmio + PSB_MSVDX_RENDEC_BASE_ADDR0);
+ EMGD_WRITE32(base_addr1, mmio + PSB_MSVDX_RENDEC_BASE_ADDR1);
+
+ EMGD_WRITE32((((size1 / 4096) << 16) | (size0 / 4096)),
+ mmio + PSB_MSVDX_RENDEC_BUFFER_SIZE);
+
+ /* Rendec setup:
+ * Start size = 0
+ * Burst size R = 4 words
+ * Burst size W = 4 words
+ * External memory enabled
+ * Stream End = 0
+ * Slice mode = 0
+ * DEC disable = 0
+ */
+ EMGD_WRITE32(0x01050000, mmio + PSB_MSVDX_RENDEC_CONTROL1);
+
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT0);
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT1);
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT2);
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT3);
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT4);
+ EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT5);
+
+ EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_RENDEC_CONTROL0);
+
+
+ /* Start Firmware Load process */
+
+ /* Reset the MTX */
+ EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MTX_SOFT_RESET);
+
+ /* Reset the counter that looks for MSVDX getting into a bad state */
+ jiffies_at_last_dequeue = 0;
+
+ /*
+ * Should this check the core revision and only do this if it is
+ * a specific version or range of versions?
+ *
+ * Stepping prior to D0, need to set COMMS_OFFSET_FLAGS to 0
+ * Stepping D0 should set MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0 (0x222)
+ * Stepping D1 should set MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1 (0x220)
+ */
+#if 0
+ /* If POULSBO_D1 or later use MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION */
+ EMGD_WRITE32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT,
+ mmio + PSB_MSVDX_COMMS_OFFSET_FLAGS);
+ /* Else EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_OFFSET_FLAGS); */
+#endif
+#if 1
+{
+#define DISABLE_FW_WDT 0x0008
+#define ABORT_ON_ERRORS_IMMEDIATE 0x0010
+#define ABORT_FAULTED_SLICE_IMMEDIATE 0x0020
+#define RETURN_VDEB_DATA_IN_COMPLETION 0x0800
+#define DISABLE_Auto_CLOCK_GATING 0x1000
+#define DISABLE_IDLE_GPIO_SIG 0x2000
+
+ unsigned long msvdx_fw_flag;
+
+ // msvdx_fw_flag = DISABLE_Auto_CLOCK_GATING | RETURN_VDEB_DATA_IN_COMPLETION | DISABLE_FW_WDT;
+ msvdx_fw_flag = DISABLE_FW_WDT; /* Per ImgTec ticket 16892 */
+
+ EMGD_WRITE32(msvdx_fw_flag, mmio + PSB_MSVDX_COMMS_OFFSET_FLAGS);
+
+ /*
+ * Following two setting can't find reg definition in spec, just copy
+ * from IMG DDK 187
+ */
+ /* 1/200th of the clock frequency */
+ EMGD_WRITE32(200 - 1,
+ mmio + PSB_MSVDX_MTX_CORE_CR_MTX_SYSC_TIMERDIV_OFFSET);
+ EMGD_WRITE32(0, mmio + 0x2884); /* EXT_FW_ERROR_STATE */
+}
+#endif
+ /* Initialize communication control */
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_MSG_COUNTER);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_SIGNATURE);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_HOST_RD_INDEX);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_HOST_WRT_INDEX);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_MTX_RD_INDEX);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
+ EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_FW_STATUS);
+
+ printk(KERN_INFO "MSVDX: Firmware version is %s\n", priv_fw->fw_version);
+ if (msvdx_fw_dma_upload)
+ msvdx_upload_fw_dma(0 /* Offset of firmware's .text section */);
+ else
+ msvdx_upload_fw();
+
+ /* Start the firmware thread running */
+ EMGD_WRITE32(PC_START_ADDRESS, mmio + PSB_MSVDX_MTX_REGISTER_READ_WRITE_DATA);
+ EMGD_WRITE32(MTX_PC, mmio + PSB_MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);
+ reg_ready_psb(context, PSB_MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+ 0x80000000, 0x80000000);
+
+ /* Enable the MTX */
+ printk(KERN_INFO "Enabling MTX 0x%x\n", EMGD_READ32(mmio + PSB_MSVDX_MTX_ENABLE));
+ EMGD_WRITE32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, mmio + PSB_MSVDX_MTX_ENABLE);
+ printk(KERN_INFO "Enabled MTX 0x%x\n", EMGD_READ32(mmio + PSB_MSVDX_MTX_ENABLE));
+
+ /*
+ * Wait for signature value to be written.
+ *
+ * This is how the firmware thread notifies us that it is running.
+ */
+ if (reg_ready_psb(context, PSB_MSVDX_COMMS_SIGNATURE, 0xffffffff,
+ 0xA5A5A5A5)){
+ /* Error initializing firmware.... */
+ EMGD_DEBUG("Error, no MSVDX COMMS Signature");
+ ret = -1; /* FIXME: return an error code */
+ goto cleanup;
+ }
+ printk(KERN_INFO "MSVDX COMMS Signature OK\n");
+
+ /* Locate message buffers */
+ platform->mtx_buf_size = EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_MTX_BUF_SIZE) & 0xFFFF;
+ platform->host_buf_size = EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_HOST_BUF_SIZE) & 0xFFFF;
+ platform->mtx_buf_offset = MSVDX_BASE + (EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_MTX_BUF_SIZE) >> 16) + 0x2000;
+ platform->host_buf_offset = MSVDX_BASE + (EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_HOST_BUF_SIZE) >> 16) + 0x2000;
+
+ platform->sequence = 1;
+ platform->mtx_submitted = 0;
+
+ /* Send initialization message to firmware, newer versions don't */
+ if (0) {
+ unsigned long init_msg[2];
+
+ init_msg[0] = 8 | (0x80 << 8);
+
+ /* physical address of the PD shared by SGX/MSVDX */
+ init_msg[1] = EMGD_READ32(mmio + 0x40c84);
+
+ send_to_mtx(context, init_msg);
+
+ /* Check response from MTX firmware */
+ poll_mtx_irq(context);
+ }
+
+ /* Clear the firmware buffer, this is mostly to make debugging easier */
+ if (1) {
+ unsigned long i;
+
+ for (i = 0; i < platform->mtx_buf_size; i++) {
+ EMGD_WRITE32(0, mmio + platform->mtx_buf_offset + (i <<2));
+ }
+ for (i = 0; i < platform->host_buf_size; i++) {
+ EMGD_WRITE32(0, mmio + platform->host_buf_offset + (i <<2));
+ }
+ }
+
+
+ /* Enable minimal clocks */
+ EMGD_WRITE32(PSB_CLK_ENABLE_MIN, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ /* Enable MTX interrupts to host */
+ EMGD_WRITE32(1<<14, mmio + PSB_MSVDX_HOST_INTERRUPT_ENABLE);
+
+cleanup:
+ // unset fw loading flag
+ spin_lock(&platform->msvdx_init_plb);
+ platform->msvdx_status = platform->msvdx_status & ~1;
+ spin_unlock(&platform->msvdx_init_plb);
+ /* Are we done? */
+ EMGD_TRACE_EXIT;
+ return ret; /* Successfully initialized the MTX firmware */
+}
+
+
+int msvdx_uninit_plb(igd_context_t *context)
+{
+ EMGD_TRACE_ENTER;
+
+ if(!context_count) {
+ //msvdx_reset_plb(context);
+ //msvdx_pvr_deinit();
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+int msvdx_close_context(igd_context_t *context, unsigned long context_id)
+{
+ unsigned long irq_flags;
+ struct list_head *entry = NULL, *cur = NULL;
+ struct msvdx_cmd_queue *msvdx_cmd = NULL;
+ platform_context_plb_t *platform;
+ int i;
+
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
+
+ list_for_each(entry, &platform->msvdx_queue) {
+ msvdx_cmd = (struct msvdx_cmd_queue *) entry;
+ if (msvdx_cmd->context_id == context_id) {
+ cur = entry;
+ entry = entry->prev;
+ list_del(cur);
+ msvdx_cmd->cmd = NULL;
+ kfree(msvdx_cmd);
+ }
+ }
+
+ for (i = 0; i < MSVDX_MAXIMUM_CONTEXT; ++i) {
+ if (msvdx_contexts[i].context_id == context_id) {
+ msvdx_contexts[i].drm_file_priv = NULL;
+ msvdx_contexts[i].context_id = 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+
+ if(context_count) {
+ context_count -= 1;
+
+ if (context_count == 0 && !list_empty(&platform->msvdx_queue)) {
+ printk(KERN_ERR "MSVDX!!! Closing final context but the list is still not empty");
+ spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
+ INIT_LIST_HEAD(&platform->msvdx_queue); // empty the list.
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+ }
+ } else {
+ EMGD_TRACE_EXIT;
+ return 1;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+int msvdx_create_context(igd_context_t *context, void * drm_file_priv, unsigned long ctx_id)
+{
+ int i = 0, ret = 0;
+ EMGD_TRACE_ENTER;
+
+ if(!drm_file_priv) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MSVDX_MAXIMUM_CONTEXT; ++i) {
+ if (msvdx_contexts[i].drm_file_priv == NULL) {
+ msvdx_contexts[i].drm_file_priv = drm_file_priv;
+ msvdx_contexts[i].context_id = ctx_id;
+ break;
+ }
+ }
+
+ if (i < MSVDX_MAXIMUM_CONTEXT) {
+ context_count += 1;
+ } else {
+ ret = -1;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+void msvdx_postclose_check(igd_context_t *context, void *drm_file_priv)
+{
+ int i;
+ EMGD_TRACE_ENTER;
+
+ for (i = 0; i < MSVDX_MAXIMUM_CONTEXT; ++i) {
+ if (msvdx_contexts[i].drm_file_priv == drm_file_priv) {
+ printk(KERN_ERR "MSVDX!!! User mode does not call video closing ioctl.");
+ msvdx_close_context(context, msvdx_contexts[i].context_id);
+ msvdx_contexts[i].drm_file_priv = NULL;
+ msvdx_contexts[i].context_id = 0;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+int process_video_decode_plb(igd_context_t *context, unsigned long offset,
+ void* mem_handle, unsigned long *fence_id)
+{
+ unsigned long *mtx_buf;
+ unsigned long *mtx_msgs;
+ unsigned long mtx_offset;
+ unsigned long mtx_msg_cnt;
+ unsigned long irq_flags;
+ int ret = 0;
+ platform_context_plb_t *platform;
+ PVRSRV_ERROR err;
+ PVRSRV_PER_PROCESS_DATA *ps_data = NULL;
+ IMG_UINT32 pid = 0;
+ PVRSRV_KERNEL_MEM_INFO *mem_info_mtx_buf = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if(!mem_handle || !fence_id) {
+ printk(KERN_ERR "Invalid message");
+ return -EINVAL;
+ }
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ pid = OSGetCurrentProcessIDKM();
+ ps_data = PVRSRVPerProcessData(pid);
+ if (!ps_data) {
+ printk(KERN_ERR "MSVDX: Cannot get process data information");
+ return -1;
+ }
+
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, (void **)&mem_info_mtx_buf,
+ (IMG_HANDLE)mem_handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(err != PVRSRV_OK) {
+ printk(KERN_ERR "MSVDX: Cannot get mtx buf memory context from process data");
+ return -1;
+ }
+
+ if(!mem_info_mtx_buf) {
+ printk(KERN_ERR "MSVDX: invalid mtx buf memory context from process data");
+ return -1;
+ }
+
+ mtx_buf = (unsigned long *) mem_info_mtx_buf->pvLinAddrKM;
+ mtx_offset = mtx_buf[0];
+ mtx_msg_cnt = mtx_buf[1];
+
+ if (mtx_msg_cnt > 0x20) {
+ printk(KERN_ERR "Message count too big at %ld\n", mtx_msg_cnt);
+ return -EINVAL;
+ }
+
+ mtx_msgs = mtx_buf + (mtx_offset / sizeof (unsigned long));
+ if(!mtx_msgs) {
+ printk(KERN_ERR "Invalid message");
+ return -EINVAL;
+ }
+
+ if (mtx_msg_cnt > 0) {
+ //if ((mtx_buf[0] != 0x8) || (mtx_buf[2] != 0x8504)) {
+
+ spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
+
+ if (!platform->msvdx_busy) {
+
+ platform->msvdx_busy = 1;
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+
+
+ if (platform->msvdx_needs_reset) {
+ msvdx_reset_plb(context);
+ msvdx_init_plb(0, 0, NULL, 1);
+ jiffies_at_last_dequeue = 0;
+ }
+ // Send message buffer to MSVDX Firmware
+
+ populate_fence_id(context, mtx_msgs, mtx_msg_cnt);
+ ret = process_mtx_messages(context, mtx_msgs, mtx_msg_cnt, platform->msvdx_fence);
+
+ if (ret) {
+ ret = -EINVAL;
+
+ }
+ } else {
+ struct msvdx_cmd_queue *msvdx_cmd;
+
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+
+ msvdx_cmd = kzalloc(sizeof(struct msvdx_cmd_queue), GFP_KERNEL);
+ if (msvdx_cmd == NULL) {
+ printk(KERN_ERR "MSVDXQUE: Out of memory\n");
+ return -ENOMEM;
+ }
+
+ msvdx_cmd->context_id = populate_fence_id(context, mtx_msgs, mtx_msg_cnt);
+ msvdx_cmd->cmd = mtx_msgs;
+ msvdx_cmd->cmd_size = mtx_msg_cnt;
+ /* If more than 1000 msec (1 second or 1000 jiffies) passes since
+ * the last time a video cmd has been decoded, MSVDX may be hung
+ * and needing to be reset.
+ */
+ if ((jiffies_at_last_dequeue != 0) &&
+ ((jiffies - jiffies_at_last_dequeue) > 1000)) {
+ printk(KERN_ERR "Video decode hardware appears to be hung; "
+ "resetting\n");
+ platform->msvdx_needs_reset = 1;
+ }
+ if (platform->msvdx_needs_reset) {
+ msvdx_reset_plb(context);
+ msvdx_init_plb(0, 0, NULL, 1);
+ platform->msvdx_busy = 0;
+ jiffies_at_last_dequeue = 0;
+ }
+
+ spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
+ list_add_tail(&msvdx_cmd->head, &platform->msvdx_queue);
+ if (!platform->msvdx_busy) {
+ platform->msvdx_busy = 1;
+ msvdx_dequeue_send(context);
+ }
+
+ spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
+
+ }
+ *fence_id = platform->msvdx_fence;
+ } else {
+ /* return the fence id even there is no messages to process.
+ * Used this for context id.
+ */
+ *fence_id = platform->msvdx_fence;
+ }
+
+ return ret;
+}
+
+int msvdx_get_fence_id(igd_context_t *context, unsigned long *fence_id)
+{
+ int ret = 0;
+ platform_context_plb_t *platform;
+
+ if(!fence_id) {
+ return -EINVAL;
+ }
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ *fence_id = platform->mtx_completed;
+
+ return ret;
+}
+
+int msvdx_flush_tlb(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long msvdx_mmu;
+ msvdx_mmu = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
+ msvdx_mmu &= 0xFFFFFFF0;
+ msvdx_mmu |= 0x0C; /* MMU_INVALDC + MMU_FLUSH */
+ EMGD_WRITE32(msvdx_mmu, mmio + PSB_MSVDX_MMU_CONTROL0);
+
+ msvdx_mmu = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
+ msvdx_mmu &= 0xFFFFFF00;
+ EMGD_WRITE32(msvdx_mmu, mmio + PSB_MSVDX_MMU_CONTROL0);
+ EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
+
+ return 0;
+
+}
+
+
+/*
+ * Resets the MSVDX engine via the soft reset control.
+ *
+ * This function is exported.
+ */
+void msvdx_reset_plb(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ platform_context_plb_t *platform;
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ /* Reset MSVDX engine */
+ EMGD_WRITE32(0x11111100, mmio + PSB_MSVDX_CONTROL);
+ reg_ready_psb(context, PSB_MSVDX_CONTROL, 0x00000100, 0);
+
+ /* Clear interrupt and clear pending interrupts */
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_HOST_INTERRUPT_ENABLE);
+ EMGD_WRITE32(0xffffffff, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ /* Mark the engine as being reset */
+ platform->msvdx_needs_reset = 0;
+}
+
+#if 0
+void MSVDXSetClocksEnable(int ClockState)
+{
+ unsigned long reg_val = 0;
+
+ if(ClockState == 0)
+ {
+ // Turn off clocks procedure
+
+ if(LastClockState)
+ {
+ // Turn off all the clocks except core
+ EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ // Make sure all the clocks are off except core
+ reg_ready_psb(context, PSB_MSVDX_MAN_CLK_ENABLE, 0x00000001, 0);
+
+ // Turn off core clock
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+ }
+
+ LastClockState = 0;
+ }
+ else
+ {
+ // ui32ClockState
+ unsigned long ClocksEn = ClockState;
+
+ //Make sure that core clock is not accidentally turned off
+ ClocksEn |= 0x00000001;
+
+ //If all clocks were disable do the bring up procedure
+ if(LastClockState == 0 )
+ {
+ // turn on core clock
+ EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ // Make sure it is on
+ reg_ready_psb(context, PSB_MSVDX_MAN_CLK_ENABLE, 0x00000001, 0);
+
+ // turn on the other clocks as well
+ EMGD_WRITE32(ClocksEn, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ // Make sure that they are on
+ reg_ready_psb(context, PSB_MSVDX_MAN_CLK_ENABLE, ClocksEn, 0);
+ }
+ else
+ {
+ EMGD_WRITE32(ClocksEn, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ // Make sure that they are on
+ reg_ready_psb(context, PSB_MSVDX_MAN_CLK_ENABLE, ClocksEn, 0);
+ }
+
+ LastClockState = ClocksEn;
+ }
+}
+
+void msvdx_reset_plb_workaround(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ platform_context_plb_t *platform;
+
+ EMGD_TRACE_ENTER;
+
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ /*
+ * Make sure the clock is on.
+ *
+ * Clock enable bits are 0 - 6, with each bit controlling one of the
+ * clocks. For this, make sure all the clocks are enabled.
+ */
+
+ EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
+
+ /* Reset MSVDX engine */
+ EMGD_WRITE32(0x11111100, mmio + PSB_MSVDX_CONTROL);
+ reg_ready_psb(context, PSB_MSVDX_CONTROL, 0x00000100, 0);
+
+ /* Clear interrupt and clear pending interrupts */
+ EMGD_WRITE32(0, mmio + PSB_MSVDX_HOST_INTERRUPT_ENABLE);
+ EMGD_WRITE32(0xffffffff, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ /* Mark the engine as being reset */
+ platform->msvdx_needs_reset = 0;
+}
+#endif
+/*
+ * When shuting down, need to reset the MSVDX engine too.
+ */
+int msvdx_shutdown_plb(igd_context_t *context)
+{
+ platform_context_plb_t *platform;
+ EMGD_TRACE_ENTER;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ /* Reset MSVDX engine */
+ msvdx_reset_plb(context);
+ msvdx_pvr_deinit();
+ /* Free RENDEC memory allocations */
+ platform->rendec_base0 = 0;
+ platform->rendec_base1 = 0;
+ init_msvdx_first_time = 1;
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+static int reg_ready_psb(igd_context_t *context,
+ unsigned long reg,
+ unsigned long mask,
+ unsigned long value)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long status;
+ int poll_cnt = 1000;
+
+ while (poll_cnt) {
+ status = EMGD_READ32(mmio + reg);
+ if ((status & mask) == value) {
+ return 0;
+ }
+ poll_cnt--;
+ OS_SLEEP(100);
+ }
+
+ /* Timeout waiting for RAM ACCESS ready */
+ EMGD_DEBUG("TIMEOUT: Got 0x%08lx while waiting for 0x%08lx", status, value);
+ return 1;
+}
+
+
+static int poll_mtx_irq(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ int ret;
+ unsigned long mtx_int;
+
+ EMGD_TRACE_ENTER;
+ mtx_int = (1 << 14);
+
+ ret = reg_ready_psb(context, PSB_MSVDX_INTERRUPT_STATUS, mtx_int, mtx_int);
+ if (ret) {
+ /* Timeout waiting on interrupt status */
+ return ret;
+ }
+
+ /* Clear the interrupt */
+ EMGD_WRITE32(mtx_int, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
+
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
new file mode 100644
index 0000000..d26ddcc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
@@ -0,0 +1,583 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_pvr.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "msvdx.h"
+#include "msvdx_pvr.h"
+#include "sgxinfokm.h"
+#include "services_headers.h"
+//#include "sgxinfokm.h"
+#include "sgxapi_km.h"
+#include "services.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+#include "syscommon.h"
+#include "memory.h"
+#include "memmap.h"
+#include <drm_emgd_private.h>
+#include "emgd_drm.h"
+#include <linux/kthread.h>
+#include <plb/regs.h>
+#include <plb/context.h>
+
+extern IMG_BOOL msvdx_mtx_isr(IMG_VOID *pvData);
+#if 0
+extern int emgd_test_pvrsrv(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv);
+
+static PVRSRV_PER_PROCESS_DATA *psPerProc = NULL;
+static unsigned long dev_ids[2] = {0, 0};
+static void *dev_mem_context = NULL;
+static IMG_BOOL mem_created, dummy;
+static PVRSRV_DEVICE_IDENTIFIER dev_id_list[10];
+static PVRSRV_HEAP_INFO heap_info[PVRSRV_MAX_CLIENT_HEAPS];
+
+int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1,
+ unsigned long size0, unsigned long size1)
+{
+ unsigned long pid = OSGetCurrentProcessIDKM();
+ unsigned long num = 10;
+ unsigned long heap_count = 0;
+ void *sgx_cookie = NULL;
+ unsigned long heapIndex = 0, generalHeapIndex = 0;
+ PVRSRV_ERROR err;
+ PVRSRV_KERNEL_MEM_INFO *rendec0MemInfo;
+ PVRSRV_KERNEL_MEM_INFO *rendec1MemInfo;
+ int i;
+
+ printk(KERN_INFO "Calling PVRSRVPerProcessData()\n");
+ if (PVRSRVPerProcessDataConnect(200) != PVRSRV_OK) {
+ printk(KERN_ERR "msvdx_init: connect to PVR failed\n");
+ }
+
+ psPerProc = PVRSRVPerProcessData(200);
+ if (psPerProc == IMG_NULL)
+ {
+ printk(KERN_ERR "msvdx_init: Couldn't find per process data for pid=%lx\n", pid);
+ }
+
+ printk(KERN_INFO " TEST: pp_data = 0x%p\n", psPerProc);
+
+
+ PVRSRVEnumerateDevicesKM(&num, dev_id_list);
+ printk(KERN_INFO "Calling PVRSRVEnumerateDevicesKM()\n");
+ if (PVRSRVEnumerateDevicesKM(&num, dev_id_list) != PVRSRV_OK) {
+ printk(KERN_ERR "msvdx_init: PVRSRVEnumerateDevice failed\n");
+ } else {
+ printk(KERN_INFO " PVRSRVEnumerateDevicesKM() found %ld devices\n", num);
+ for (i = 0 ; i < num ; i++) {
+ PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i;
+ unsigned long cookie = 0;
+ printk(KERN_INFO " Device %d has type %d, class %d & index %ld\n", i,
+ id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex);
+ if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) {
+ // Call PVRSRVAcquireDeviceDataKM():
+ printk(KERN_INFO "Calling PVRSRVAcquireDeviceDataKM()\n");
+ err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
+ PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] PVRSRVAcquireDeviceDataKM() "
+ "returned %d\n", err);
+ break;
+ }
+ if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
+ printk(KERN_INFO " Found cookie = 0x%lx\n", cookie);
+ // Save this away for later:
+ sgx_cookie = (void *) cookie;
+ }
+ }
+ }
+ }
+
+ // Enumerate the display class devices to be able to find the 3DD:
+ printk(KERN_INFO "Calling PVRSRVEnumerateDCKM()\n");
+ err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY,
+ &num, dev_ids);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err);
+ } else {
+ // Find the 3DD:
+ printk(KERN_INFO " PVRSRVEnumerateDCKM() found %ld devices\n", num);
+ for (i = 0 ; i < num ; i++) {
+ printk(KERN_INFO " device %d has ID %ld\n", i, dev_ids[i]);
+ }
+ if (0 == dev_ids[0]) {
+ printk(KERN_ERR "[EMGD] Did not find 3rd-party display driver ID\n");
+ }
+ }
+
+ // Call PVRSRVCreateDeviceMemContextKM():
+
+ printk(KERN_INFO "Calling PVRSRVCreateDeviceMemContextKM()\n");
+ err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, psPerProc,
+ &dev_mem_context, &heap_count, heap_info, &mem_created, &dummy);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] PVRSRVCreateDeviceMemContextKM() "
+ "returned %d\n", err);
+ }
+
+
+ for (heapIndex=0; heapIndex<heap_count; heapIndex++) {
+ if (HEAP_IDX(heap_info[heapIndex].ui32HeapID) == SGX_GENERAL_HEAP_ID)
+ {
+ generalHeapIndex = heapIndex;
+ break;
+ }
+ }
+
+ if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ size0, 0, &rendec0MemInfo, "") != PVRSRV_OK) {
+ printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n");
+ }
+
+ if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ size1, 0, &rendec1MemInfo, "") != PVRSRV_OK) {
+ printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n");
+ }
+
+ *base_addr0 = rendec0MemInfo->sDevVAddr.uiAddr;
+ *base_addr1 = rendec1MemInfo->sDevVAddr.uiAddr;
+
+ //printk(KERN_INFO "pvr size0=%lx, size1=%lx, heap=%ld\n", size0, size1, generalHeapIndex);
+
+// return PVRSRV_OK;
+ return 0;
+
+}
+#endif
+
+/*
+ * Dummy kernel thread. Needed for a persistent per process data for
+ * PVR services.
+ */
+static int msvdx_pvr_kthread(void *data)
+{
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ return 0;
+}
+
+int msvdx_preinit_mmu(unsigned long hmemcxt)
+{
+ PVRSRV_ERROR err;
+ PVRSRV_PER_PROCESS_DATA *ps_data = NULL;
+ IMG_HANDLE hmem = (IMG_HANDLE) hmemcxt;
+ IMG_HANDLE hmemkm;
+ IMG_DEV_PHYADDR addr;
+ IMG_UINT32 pid = OSGetCurrentProcessIDKM();
+ int ret;
+ drm_emgd_priv_t *priv = gpDrmDevice->dev_private;
+ igd_context_t *context = priv->context;
+ platform_context_plb_t *platform =
+ (platform_context_plb_t *) context->platform_context;
+
+ ps_data = PVRSRVPerProcessData(pid);
+ if (!ps_data) {
+ printk(KERN_ERR "MSVDX: Cannot get process data information");
+
+ return -1;
+ }
+
+
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, &hmemkm, hmem, PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(err != PVRSRV_OK)
+ {
+ printk(KERN_ERR "MSVDX: Cannot get memory context from process data");
+
+ return -1;
+ }
+
+ addr = BM_GetDeviceNode(hmemkm)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hmemkm));
+ msvdx_init_compositor_mmu(addr.uiAddr);
+
+ if (!platform->msvdx_pvr) {
+ ret = msvdx_pvr_init();
+ if (ret) {
+ printk(KERN_INFO "Failed in msvdx_pvr_init()");
+ } else {
+
+ printk(KERN_INFO "Succeed for msvdx_pvr_init()");
+
+ }
+ }
+
+
+ return 0;
+}
+
+/*
+ * Can't call from module initialization, since PVR services are started when
+ * the Xorg server starts.
+ */
+int msvdx_pvr_init(void)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ platform_context_plb_t *platform;
+ struct msvdx_pvr_info *pvr;
+ PVRSRV_DEVICE_IDENTIFIER dev_id_list[PVRSRV_MAX_DEVICES];
+ IMG_UINT32 pid;
+ IMG_UINT32 num_devices;
+ IMG_UINT32 i;
+ IMG_BOOL mem_created;
+ PVRSRV_ERROR err;
+ int ret;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ if (platform->msvdx_pvr) {
+ printk(KERN_INFO "[EMGD] MSVDX: PVR services already "
+ "initialized\n");
+ return 0;
+ }
+
+ pvr = kzalloc(sizeof(*pvr), GFP_KERNEL);
+ if (!pvr)
+ return -ENOMEM;
+
+ /*
+ * Create a dummy kernel thread so that a persistent PVR per process
+ * data could be created.
+ */
+ pvr->kthread = kthread_run(msvdx_pvr_kthread, NULL, "msvdx-pvr");
+ if (IS_ERR(pvr->kthread)) {
+ ret = PTR_ERR(pvr->kthread);
+ printk(KERN_ERR "[EMGD] MSVDX: failed to create MSVDX PVR "
+ "kernel tread, error=%i\n", ret);
+ pvr->kthread = NULL;
+ goto out_free;
+ }
+
+ ret = -ENODEV;
+ pid = OSGetCurrentProcessIDKM(); //(IMG_UINT32)pvr->kthread->pid;
+ err = PVRSRVPerProcessDataConnect(pid);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] MSVDX: connect to PVR failed (pid=%u), "
+ "error=%i\n", (unsigned int)err, err);
+ goto out_stop_kthread;
+ }
+ pvr->per_proc = PVRSRVPerProcessData(pid);
+ if (pvr->per_proc == IMG_NULL) {
+ printk(KERN_ERR "[EMGD] MSVDX: Couldn't find per process "
+ "data for pid=%u\n", (unsigned int)pid);
+ goto out_stop_kthread;
+ }
+
+ err = PVRSRVEnumerateDevicesKM(&num_devices, dev_id_list);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] MSVDX: PVRSRVEnumerateDevice() failed, "
+ "error=%u\n", (unsigned int)err);
+ goto out_stop_kthread;
+ }
+
+ for (i = 0 ; i < num_devices ; i++) {
+ PVRSRV_DEVICE_IDENTIFIER *id;
+ IMG_HANDLE cookie;
+
+ cookie = IMG_NULL;
+ id = &dev_id_list[i];
+
+ if (id->eDeviceType != PVRSRV_DEVICE_TYPE_EXT) {
+ err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
+ PVRSRV_DEVICE_TYPE_UNKNOWN, &cookie);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] MSVDX: "
+ "PVRSRVAcquireDeviceDataKM() failed, "
+ "error=%u\n", err);
+ break;
+ }
+ if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
+ pvr->sgx_cookie = cookie;
+ break;
+ }
+ }
+ }
+
+ if (pvr->sgx_cookie == IMG_NULL)
+ goto out_stop_kthread;
+
+ err = PVRSRVCreateDeviceMemContextKM(pvr->sgx_cookie, pvr->per_proc,
+ &pvr->dev_mem_context, &pvr->heap_count,
+ pvr->heap_info, &mem_created, pvr->heap_shared);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] MSVDX: PVRSRVCreateDeviceMemContextKM()"
+ " failed, error=%u\n", (unsigned int)err);
+ goto out_stop_kthread;
+ }
+
+ for (i = 0; i < pvr->heap_count; i++) {
+ if (HEAP_IDX(pvr->heap_info[i].ui32HeapID) ==
+ SGX_VIDEO_HEAP_ID) {
+ pvr->mapping_heap_index = i;
+ break;
+ }
+ }
+
+ platform->msvdx_pvr = pvr;
+ pvr->pid = pid;
+
+
+ return 0;
+
+out_stop_kthread:
+ kthread_stop(pvr->kthread);
+out_free:
+ kfree(pvr);
+ return ret;
+}
+
+/*
+ * HHP: FIXME:
+ * This should also be called when GMM/GTT is re-initialized, i.e. when
+ * the Xorg server stops. The PVR backed memory is invalid when this happens,
+ * so if we call this function from msvdx_driver_unload() when the module is
+ * removed, the "fw_mem_info" and "dev_mem_context" are invalid.
+ */
+void msvdx_pvr_deinit(void)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ platform_context_plb_t *platform;
+ struct msvdx_pvr_info *pvr;
+ IMG_BOOL mem_destroyed;
+ int pid=0;
+ unsigned char *mmio;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ platform = (platform_context_plb_t *)context->platform_context;
+ mmio = context->device_context.virt_mmadr;
+ pvr = platform->msvdx_pvr;
+
+ //Reset MTX before unloading firmware
+ EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MTX_SOFT_RESET);
+
+
+ if (pvr) {
+ kthread_stop(pvr->kthread);
+ if (pvr->fw_mem_info)
+ PVRSRVFreeDeviceMemKM(pvr->sgx_cookie,
+ pvr->fw_mem_info);
+
+ PVRSRVDestroyDeviceMemContextKM(pvr->sgx_cookie,
+ pvr->dev_mem_context,
+ &mem_destroyed);
+
+ // PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->kthread->pid);
+ PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->pid);
+ pid = pvr->pid;
+ kfree(pvr);
+ platform->msvdx_pvr = NULL;
+ }
+
+}
+
+PVRSRV_KERNEL_MEM_INFO *msvdx_pvr_alloc_devmem(unsigned long alloc_size,
+ const char *mame)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ platform_context_plb_t *platform;
+ struct msvdx_pvr_info *pvr;
+ PVRSRV_KERNEL_MEM_INFO *mem_info;
+ PVRSRV_ERROR err;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ platform = (platform_context_plb_t *)context->platform_context;
+
+ pvr = platform->msvdx_pvr;
+ if (!pvr)
+ return NULL;
+
+ /* Is PVRSRV_MEM_CACHE_CONSISTENT needed in the allocation flags? */
+ err = PVRSRVAllocDeviceMemKM(pvr->sgx_cookie, pvr->per_proc,
+ pvr->heap_info[pvr->mapping_heap_index].hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ alloc_size, 0, &mem_info, name);
+ if (err != PVRSRV_OK) {
+ printk(KERN_ERR "[EMGD] MSVDX: PVRSRVAllocDeviceMemKM failed, "
+ "error=%u\n", (unsigned int)err);
+ return NULL;
+ }
+
+ return mem_info;
+}
+
+static PVRSRV_ERROR DevInitMSVDXPart1(IMG_VOID *pvDeviceNode)
+{
+ /*
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ */
+
+ /* register power operation function */
+ /* FIXME: this should be in part2 init function, but
+ * currently here only OSPM needs IMG device... */
+ /*
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+ MSVDXPrePowerState,
+ MSVDXPostPowerState,
+ MSVDXPreClockSpeedChange,
+ MSVDXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_ON,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitMSVDXPart1: failed to "
+ "register device with power manager"));
+ return eError;
+ }
+ */
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitMSVDX(IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+
+ /* should deinit all resource */
+
+ eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ /* version check */
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_MSVDX;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_VIDEO;
+
+ psDeviceNode->pfnInitDevice = DevInitMSVDXPart1;
+ psDeviceNode->pfnDeInitDevice = DevDeInitMSVDX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = MSVDXDevInitCompatCheck;
+
+ psDeviceNode->pfnDeviceISR = msvdx_mtx_isr;
+ psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+
+ return PVRSRV_OK;
+}
+
+/*
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ // ask for a change not power on
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+
+ // context save
+ psb_msvdx_save_context(gpDrmDevice);
+
+ // internally close the device //
+
+ // ask for power off //
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ // here will deinitialize the driver if needed //
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ // if ask for change & current status is not on //
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ // internally open device //
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+ // context restore //
+ psb_msvdx_restore_context(gpDrmDevice);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ // here will initialize the driver if needed //
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
+*/
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
new file mode 100644
index 0000000..070c935
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_pvr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef MSVDX_POWER_H_
+#define MSVDX_POWER_H_
+#include <linux/sched.h>
+#include "services_headers.h"
+#include "sysconfig.h"
+
+extern struct drm_device *gpDrmDevice;
+
+struct msvdx_pvr_info {
+ /* HHP: FIXME: review if a mutex lock is needed here */
+ IMG_HANDLE sgx_cookie;
+ IMG_HANDLE dev_mem_context;
+ PVRSRV_PER_PROCESS_DATA *per_proc;
+ PVRSRV_HEAP_INFO heap_info[PVRSRV_MAX_CLIENT_HEAPS];
+ IMG_BOOL heap_shared[PVRSRV_MAX_CLIENT_HEAPS];
+ IMG_UINT32 heap_count;
+ /* index of SGX_GENERAL_MAPPING_HEAP_ID in heap_info[] */
+ int mapping_heap_index;
+ PVRSRV_KERNEL_MEM_INFO *fw_mem_info;
+ /* Needed for PVR per process data */
+ struct task_struct *kthread;
+ IMG_UINT32 pid;
+};
+/* function define */
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+extern int msvdx_pvr_init(void);
+extern void msvdx_pvr_deinit(void);
+extern PVRSRV_KERNEL_MEM_INFO *msvdx_pvr_alloc_devmem(
+ unsigned long alloc_size, const char *name);
+#endif /* !MSVDX_POWER_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
new file mode 100755
index 0000000..c5ee729
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
@@ -0,0 +1,554 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_ovl.c
+ * $Revision: 1.28 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <context.h>
+#include <memory.h>
+#include <dsp.h>
+#include <io.h>
+
+#include <igd_mode.h>
+#include <igd_gmm.h>
+#include <igd_ovl.h>
+#include <igd_errno.h>
+#include <igd_pwr.h>
+#include <igd_render.h>
+#include <igd_blend.h>
+
+#include <general.h>
+#include <mode_access.h>
+#include <dispatch.h>
+#include <intelpci.h>
+
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+
+void _overlay_shutdown(igd_context_t *context);
+
+
+extern ovl_dispatch_t ovl_dispatch_plb[];
+extern ovl_dispatch_t ovl_dispatch_tnc[];
+
+static dispatch_table_t ovl_dispatch_list[] = {
+
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &ovl_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &ovl_dispatch_tnc},
+#endif
+
+ {0, NULL}
+};
+
+ovl_context_t ovl_context[1];
+
+/* Description: Turns off video plane that was turned by fw/EFI. To be called by
+ * alter_ovl if needed.
+ *
+ * Notes:Upon video splash being turned on, in order to reset it, need to call
+ * secondary ovl dispatch function to turn off the right registers
+ */
+void igd_reset_fw_ovl(igd_display_context_t *display)
+{
+ ovl_dispatch_t *ovl_dispatch = (ovl_dispatch_t *)ovl_context->dispatch;
+ if(NULL == ovl_dispatch){
+ EMGD_DEBUG("ovl_dispatch_t *ovl_dispatch == NULL");
+ return ;
+ }
+ ovl_dispatch[OVL_SECONDARY].alter_ovl(display,
+ NULL, NULL, NULL, NULL, IGD_OVL_ALTER_OFF);
+}
+
+static int igd_ovl_set_display(igd_display_h ovl_display[])
+{
+ ovl_context->ovl_display_km[OVL_PRIMARY] = (igd_display_context_t *)ovl_display[OVL_PRIMARY];
+ ovl_context->ovl_display_km[OVL_SECONDARY] = (igd_display_context_t *)ovl_display[OVL_SECONDARY];
+
+ ovl_context->ovl_display_swapped = 1;
+ return 0;
+}
+
+static int ovl_get_display(igd_display_context_t *display,
+ igd_display_context_t *(ovl_displays[]),
+ unsigned long flags)
+{
+ igd_display_context_t *primary, *secondary;
+ unsigned long dc;
+
+ display->context->mod_dispatch.dsp_get_dc(&dc, &primary, &secondary);
+
+ /* This is a special case to enable Dual Overlay */
+ if(flags & IGD_OVL_FORCE_USE_DISP) {
+
+ /* Use the passed in Display Handle */
+ if(display == primary) {
+
+ ovl_displays[OVL_PRIMARY] = display;
+ ovl_displays[OVL_SECONDARY] = NULL;
+
+ } else if(display == secondary) {
+
+ ovl_displays[OVL_PRIMARY] = NULL;
+ ovl_displays[OVL_SECONDARY] = display;
+ }
+
+ return 0;
+ }
+
+ if (dc & IGD_DISPLAY_CONFIG_CLONE || display->context->mod_dispatch.in_dih_clone_mode) {
+ /* CLONE or Vertical Extended
+ * Primary Overlay uses the display from the primary pipe.
+ * Secondary Overlay uses the display from the secondary pipe. */
+ /* The above is TRUE on init, but subsequent
+ * video plane override calls will change the overlay plane assignment.
+ * Use ovl_um_context->ovl_display_km[OVL_PRIMARY] &
+ * ovl_um_context->ovl_display_km[OVL_SECONDARY] to retrieve
+ * HW overlay(PRIMARY) & SpriteC(SECONDARY) plane to display
+ * handle assignment respectively */
+ ovl_displays[OVL_PRIMARY] = ovl_context->ovl_display_km[OVL_PRIMARY];
+ ovl_displays[OVL_SECONDARY] = ovl_context->ovl_display_km[OVL_SECONDARY];
+ } else {
+ /* Single, Twin, Extended */
+ if (ovl_context->ovl_display_km[OVL_PRIMARY] == display) {
+ ovl_displays[OVL_PRIMARY] = display;
+ ovl_displays[OVL_SECONDARY] = NULL;
+ } else {
+ ovl_displays[OVL_PRIMARY] = NULL;
+ ovl_displays[OVL_SECONDARY] = display;
+ }
+ }
+
+ return 0;
+}
+
+static int igd_alter_ovl2(igd_display_h display_h,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_display_context_t *display =
+ (igd_display_context_t *)display_h;
+ ovl_dispatch_t *ovl_dispatch =
+ (ovl_dispatch_t *)ovl_context->dispatch;
+ int cur_ovl, ret = 0;
+ igd_display_context_t *primary, *secondary;
+ unsigned long dc;
+ igd_display_context_t *ovl_displays[OVL_MAX_HW];
+
+ EMGD_TRACE_ENTER;
+
+ if(NULL == ovl_dispatch) {
+ EMGD_DEBUG("ovl_dispatch == NULL");
+ return IGD_SUCCESS;
+ }
+
+ if(flags == IGD_FW_VIDEO_OFF)
+ {
+ igd_reset_fw_ovl(display);
+ return IGD_SUCCESS;
+ }
+
+ /* Determine which display this overlay belongs to */
+ if(display->context == NULL){
+ EMGD_DEBUG("display->context == NULL");
+ return -IGD_ERROR_INVAL;
+ }
+ display->context->mod_dispatch.dsp_get_dc(&dc, &primary, &secondary);
+
+ if ((ovl_context->ovl_display_km[OVL_PRIMARY] == NULL) &&
+ (ovl_context->ovl_display_km[OVL_SECONDARY] == NULL)) {
+ /* One time initialization of ovl_display_km */
+ ovl_displays[OVL_PRIMARY] = primary;
+ ovl_displays[OVL_SECONDARY] = secondary;
+ igd_ovl_set_display((igd_display_h)ovl_displays);
+ }
+
+ /* Determine which overlays belong to which displays */
+ ovl_get_display(display, ovl_displays, flags);
+
+ /* Determine which display this overlay belongs to */
+ if(display == ovl_displays[OVL_PRIMARY]) {
+ cur_ovl = 0;
+ } else if (display == ovl_displays[OVL_SECONDARY]) {
+ cur_ovl = 1;
+ } else {
+ /* shouldn't get here. */
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+
+ /* Is the overlay is being turned off? */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+
+ /* Call family dependent overlay
+ * function to alter the overlay. */
+ ret = ovl_dispatch[cur_ovl].alter_ovl(display,
+ src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+
+ /* Call family dependent overlay function
+ * to alter the overlay. */
+ ret = ovl_dispatch[cur_ovl].alter_ovl(display,
+ src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags);
+
+ if (ret != IGD_SUCCESS) {
+ /* Turn the overlay off when there is an error */
+ ovl_dispatch[cur_ovl].alter_ovl(display,
+ NULL, NULL, NULL, NULL,
+ IGD_OVL_ALTER_OFF);
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+static int igd_query_ovl(igd_display_h display_h,
+ unsigned int flags)
+{
+ igd_display_context_t *display =
+ (igd_display_context_t *)display_h;
+ ovl_dispatch_t *ovl_dispatch =
+ (ovl_dispatch_t *)ovl_context->dispatch;
+ int cur_ovl;
+ igd_display_context_t *(ovl_displays[OVL_MAX_HW]); /* Array of pointers */
+ int ret = FALSE;
+
+ ovl_get_display(display, ovl_displays, flags);
+
+ /* This is a bit of a short circuit (since the hardware dependent functions
+ * are not being called), but to determine if the hardware overlay is on,
+ * just check the state of the ovl_context. */
+ if (flags == IGD_OVL_QUERY_IS_ON) {
+ if (ovl_context->state == OVL_STATE_ON) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ /* NOTE: As with alter_ovl2, user mode driver should decide which ovl
+ * to flip. Instead of having a duplicate logic here to check for clone,
+ * just flip the ovl bound to the display handle. This prevents a condition
+ * in clone mode, where the user mode driver does 2 query_ovl calls for
+ * each ovl plane, that translates into 4 query_ovl calls in kernel.
+ */
+
+ /* Determine which display this overlay belongs to */
+ if(display == ovl_displays[OVL_PRIMARY]) {
+ cur_ovl = 0;
+ } else if (display == ovl_displays[OVL_SECONDARY]) {
+ cur_ovl = 1;
+ } else {
+ /* shouldn't get here. */
+ EMGD_TRACE_EXIT;
+ return -IGD_ERROR_INVAL;
+ }
+
+ ret = ovl_dispatch[cur_ovl].query_ovl(
+ (igd_display_h)(ovl_displays[cur_ovl]),
+ (flags & IGD_OVL_QUERY_MASK));
+ if (ret == FALSE) {
+ /* Can only return TRUE (event has occured and capability
+ * is available) if it is TRUE for all displays */
+ return FALSE;
+ }
+
+ return ret;
+}
+static int igd_query_max_size_ovl(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height)
+{
+ igd_display_context_t *display =
+ (igd_display_context_t *)display_h;
+ ovl_dispatch_t *ovl_dispatch =
+ (ovl_dispatch_t *)ovl_context->dispatch;
+ int cur_ovl;
+ igd_display_context_t *(ovl_displays[OVL_MAX_HW]); /* Array of pointers */
+ unsigned int tmp_max_width, tmp_max_height;
+ int ret = -IGD_ERROR_INVAL;
+
+ *max_width = 0x10000000;
+ *max_height = 0x10000000;
+
+ /* pass a dummy flag */
+ ovl_get_display(display, ovl_displays, 0);
+
+ for (cur_ovl = 0; cur_ovl < OVL_MAX_HW; cur_ovl++) {
+ if (ovl_displays[cur_ovl] != NULL) {
+ ret = ovl_dispatch[cur_ovl].query_max_size_ovl(
+ (igd_display_h)(ovl_displays[cur_ovl]), pf,
+ &tmp_max_width, &tmp_max_height);
+ if (ret != IGD_SUCCESS) {
+ /* Can only return IGD_SUCCESS (no error)
+ * if there is no error for all displays */
+ return ret;
+ }
+ if (tmp_max_width < *max_width) {
+ *max_width = tmp_max_width;
+ }
+ if (tmp_max_height < *max_height) {
+ *max_height = tmp_max_height;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+/* This is a wrapper function that will call the device specific alter_ovl2_osd
+ * function. Currently this function is used by video driver to map the subpicture
+ * surface to second overlay so that it blends with the video surface on first
+ * overlay. Furthermore, this is only enabled for PLB device only.
+ */
+static int igd_alter_ovl2_osd(igd_display_h display_h,
+ igd_surface_t *sub_surface,
+ igd_rect_t *sub_src_rect,
+ igd_rect_t *sub_dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl_dispatch_t *ovl_dispatch =
+ (ovl_dispatch_t *)ovl_context->dispatch;
+ igd_display_context_t *display =
+ (igd_display_context_t *)display_h;
+
+ int ret = 0;
+
+ ret = ovl_dispatch[1].alter_ovl(display,
+ sub_surface, sub_src_rect, sub_dest_rect,
+ ovl_info, flags);
+
+ return ret;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: igd_get_ovl_init_params(ovl_um_context_t *ovl_um_context)
+ * Description:
+ *
+ * Notes in Usage:
+ * the user mode caller fills in the primary and secondary display handles.
+ *
+ *----------------------------------------------------------------------*/
+int igd_get_ovl_init_params(igd_driver_h driver_handle,
+ ovl_um_context_t *ovl_um_context)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t *primary, *secondary;
+ unsigned long dc;
+
+ context->mod_dispatch.dsp_get_dc(&dc, &primary, &secondary);
+ ovl_um_context->dc = dc;
+ ovl_um_context->primary = primary;
+ ovl_um_context->secondary = secondary;
+ ovl_um_context->chiptype = 0;
+
+ return IGD_SUCCESS;
+}
+
+
+
+int ovl_full_init(igd_context_t *context,
+ igd_param_t *params,
+ ovl_context_t *ovl_context)
+{
+ unsigned long tmp_reg_size;
+ unsigned long region_type = IGD_GMM_REGION_TYPE_OVLREG;
+ void *virt;
+
+ if(context->device_context.did == PCI_DEVICE_ID_VGA_TNC){
+ /* Atom E6xx needs the overlay update register offset
+ * to be a 64K aligned address. */
+ region_type = IGD_GMM_REGION_TYPE_OVLREG64;
+ }
+
+ /* Allocate a 4K page aligned region from
+ * memory manager for overlay register update memory */
+
+ tmp_reg_size = 4096;
+ GMM_SET_DEBUG_NAME("Overlay Register Buffer");
+ if(context->dispatch.gmm_alloc_region(
+ &(ovl_context->reg_update_offset),
+ &tmp_reg_size,
+ IGD_GMM_REGION_TYPE_OVLREG,
+ 0)){
+
+ EMGD_ERROR_EXIT("Memory allocation for "
+ "Overlay Register Update failed");
+
+ ovl_context->reg_allocated = 0;
+
+ return -IGD_ERROR_NOMEM;
+ }
+ ovl_context->reg_allocated = 1;
+ ovl_context->ovl_display_swapped = 0;
+
+ /* Get the register update physical address in RAM */
+ if(context->dispatch.gmm_virt_to_phys(
+ ovl_context->reg_update_offset,
+ &ovl_context->reg_update_phys)) {
+
+ EMGD_ERROR_EXIT("Virtual to Physical Address translation failed");
+ return -IGD_ERROR_NOMEM;
+ }
+
+ /*
+ * TODO: Verify that phys_to_virt returns a valid address for
+ * agp memory
+ */
+ virt = phys_to_virt(ovl_context->reg_update_phys);
+
+ /* Clear the register update page */
+ OS_MEMSET(virt, 0, tmp_reg_size);
+
+
+ /* Get overlay's dispatch table */
+ ovl_context->dispatch = (ovl_dispatch_t (*)[])dispatch_acquire(context,
+ ovl_dispatch_list);
+ if(!ovl_context->dispatch) {
+ EMGD_ERROR_EXIT("Unsupported Device");
+ return -IGD_ERROR_NODEV;
+ }
+
+
+ /* Hook up the IGD dispatch table entries for overlay
+ * Alter has a common function, query can call the family function
+ * directly */
+ context->dispatch.get_ovl_init_params = igd_get_ovl_init_params;
+ context->dispatch.alter_ovl = NULL;
+ context->dispatch.alter_ovl2 = igd_alter_ovl2;
+// context->dispatch.alter_ovl2_dihclone = igd_alter_ovl2_dihclone;
+ context->dispatch.query_ovl = igd_query_ovl;
+ context->dispatch.query_max_size_ovl = igd_query_max_size_ovl;
+ context->dispatch.alter_ovl2_osd = igd_alter_ovl2_osd;
+ context->dispatch.set_ovl_display = igd_ovl_set_display;
+
+ /* Hook up optional inter-module functions */
+ context->mod_dispatch.overlay_shutdown = _overlay_shutdown;
+
+ /* Initialize any OS / Chipst general HAL params for overlay */
+ if(params->display_flags & IGD_DISPLAY_FB_BLEND_OVL){
+ ovl_context->fb_blend_ovl = 1;
+ }
+ ovl_context->saved_src_surf = NULL;
+ ovl_context->saved_src_rect = NULL;
+ ovl_context->saved_dest_rect = NULL;
+ ovl_context->saved_ovl_info = NULL;
+ ovl_context->saved_flags = 0;
+ ovl_context->ovl_display_km[OVL_PRIMARY] = NULL;
+ ovl_context->ovl_display_km[OVL_SECONDARY] = NULL;
+
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+void _overlay_shutdown(igd_context_t *context)
+{
+
+ EMGD_TRACE_ENTER;
+
+ if (ovl_context->reg_allocated) {
+ context->dispatch.gmm_free(ovl_context->reg_update_offset);
+ ovl_context->reg_update_offset = 0;
+ ovl_context->reg_allocated = 0;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return;
+}
+
+/*----------------------------------------------------------------------
+ * Function: igd_overlay_pwr()
+ * Description:
+ * igd_overlay_pwr will only be called from power module .
+ * It shuts down / powers up overlay output based on the power
+ * state transition requested.
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+int igd_overlay_pwr(
+ igd_driver_h driver_handle,
+ int power_state)
+{
+ igd_context_t *context = (igd_context_t *)driver_handle;
+ igd_display_context_t *primary, *secondary;
+
+ /* NOTE: The overlay will not be turned on by this method, but will be
+ * turned on with the next call to alter_ovl */
+
+ /* Turn off the overlay for every display. Most of the displays will
+ * likely not have the overlay off, but there should be no harm it turning
+ * it off for a display which does not have the overlay. */
+
+ EMGD_TRACE_ENTER;
+ if(power_state != IGD_POWERSTATE_D0){
+ context->mod_dispatch.dsp_get_dc(NULL, &primary, &secondary);
+
+ if(primary) {
+ /* Turn the overlay off. */
+ igd_alter_ovl2((igd_display_h)primary,
+ NULL, NULL, NULL, NULL, IGD_OVL_ALTER_OFF);
+ }
+ if(secondary) {
+ igd_alter_ovl2((igd_display_h)secondary,
+ NULL, NULL, NULL, NULL, IGD_OVL_ALTER_OFF);
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
new file mode 100644
index 0000000..7a15220
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
@@ -0,0 +1,165 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_ovl.c
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <context.h>
+#include <memory.h>
+#include <dsp.h>
+#include <io.h>
+
+#include <igd_mode.h>
+#include <igd_gmm.h>
+//#include <igd_ovl.h>
+#include <igd_pwr.h>
+#include <igd_render.h>
+#include <igd_blend.h>
+
+#include <general.h>
+#include <mode_access.h>
+#include <dispatch.h>
+#include <intelpci.h>
+
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+
+/*
+ * TODO: If there is micro overlay for device dependent layer
+ * modify extern below to the correct micro device dispatch
+ * Only two micro overlay existing is for Plb and Ctg
+ */
+
+extern ovl_dispatch_t ovl_micro_dispatch_plb[];
+
+static dispatch_table_t ovl_micro_dispatch_list[] = {
+/*
+ * TODO: Fix this.
+ * * This table would point the micro dispatch tables.
+ * For now, other than Plb ,refer the micro dispatch
+ * to the original table
+ * */
+
+#ifdef CONFIG_PLB
+ {PCI_DEVICE_ID_VGA_PLB, &ovl_micro_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+ {PCI_DEVICE_ID_VGA_TNC, &ovl_micro_dispatch_plb},
+#endif
+ {0, NULL}
+};
+extern int ovl_full_init(igd_context_t *context, igd_param_t *params,ovl_context_t *ovl_context);
+
+#ifndef CONFIG_MICRO_OVERLAY
+#define OVL_FULL_INIT(a, b, c) ovl_full_init(a, b, c)
+#else
+#define OVL_FULL_INIT(a, b, c) 1
+#endif
+
+extern ovl_context_t ovl_context[1];
+static int igd_micro_alter_ovl(igd_display_h display_h,
+ igd_appcontext_h appcontext_h,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_display_context_t *display =
+ (igd_display_context_t *)display_h;
+ ovl_dispatch_t *ovl_dispatch =
+ (ovl_dispatch_t *)ovl_context->dispatch;
+
+ igd_display_context_t *ovl_display;
+
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ ovl_display = display;
+
+ /* Call family dependent overlay function to alter the overlay. */
+ ret = ovl_dispatch->alter_ovl(
+ ovl_display, src_surf, src_rect,
+ dest_rect, ovl_info, flags);
+
+ if (ret != IGD_SUCCESS) {
+ EMGD_ERROR("Error micro alter overlay\n");
+ /* Turn the overlay off when there is an error */
+ ovl_dispatch->alter_ovl(ovl_display,
+ NULL, NULL, NULL, NULL, IGD_OVL_ALTER_OFF);
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+int _overlay_init(igd_context_t *context, igd_param_t *params)
+{
+
+ EMGD_TRACE_ENTER;
+
+ /* Ensure the device context pointer is valid */
+ if(!context){
+ EMGD_ERROR_EXIT("Error: Null context");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Clear the allocated memory for overlay context */
+ OS_MEMSET((void *)ovl_context, 0, sizeof(ovl_context_t));
+
+ /* Get overlay's dispatch table */
+ ovl_context->dispatch = (ovl_dispatch_t (*)[])dispatch_acquire(context,
+ ovl_micro_dispatch_list);
+ if(!ovl_context->dispatch) {
+ EMGD_ERROR_EXIT("Error: Unsupported Device");
+ return -IGD_ERROR_NODEV;
+ }
+
+
+ /* Hook up the IGD dispatch table entries for overlay
+ * Alter has a common function, query can call the family function
+ * directly */
+ context->dispatch.alter_ovl = igd_micro_alter_ovl;
+ context->dispatch.query_ovl = NULL;
+ context->dispatch.query_max_size_ovl = NULL;
+ context->mod_dispatch.overlay_shutdown = NULL;
+
+ if (OVL_FULL_INIT(context, params, ovl_context)) {
+ /*
+ * Even if full init failed we can still use the micro-gmm
+ */
+ EMGD_DEBUG("Full overlay did not initialize, using micro-overlay");
+
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
new file mode 100644
index 0000000..fc08f0e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
@@ -0,0 +1,1127 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_coeff.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file calculates the coefficient values used by the various
+ * platform families.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <general.h>
+#include <memory.h>
+
+#include "ovl_coeff.h"
+
+/*****************************************************************
+ * *
+ * HARDCODED QUARTER SINE WAVE TABLES *
+ * 4096 unsigned shorts MSB is integer *
+ * and 15 LSB's are after the radix *
+ * *
+ *****************************************************************/
+static unsigned short wave_table[4096] = {
+ /* 16 bit value - all 16 bits are fp only */
+ 0x0, 0x19, 0x32, 0x4b, 0x65, 0x7e, 0x97, 0xb0, 0xc9, 0xe2,
+ 0xfb, 0x114, 0x12e, 0x147, 0x160, 0x179, 0x192, 0x1ab, 0x1c4, 0x1de,
+ 0x1f7, 0x210, 0x229, 0x242, 0x25b, 0x274, 0x28d, 0x2a7, 0x2c0, 0x2d9,
+ 0x2f2, 0x30b, 0x324, 0x33d, 0x356, 0x370, 0x389, 0x3a2, 0x3bb, 0x3d4,
+ 0x3ed, 0x406, 0x420, 0x439, 0x452, 0x46b, 0x484, 0x49d, 0x4b6, 0x4cf,
+ 0x4e9, 0x502, 0x51b, 0x534, 0x54d, 0x566, 0x57f, 0x598, 0x5b2, 0x5cb,
+ 0x5e4, 0x5fd, 0x616, 0x62f, 0x648, 0x661, 0x67b, 0x694, 0x6ad, 0x6c6,
+ 0x6df, 0x6f8, 0x711, 0x72a, 0x744, 0x75d, 0x776, 0x78f, 0x7a8, 0x7c1,
+ 0x7da, 0x7f3, 0x80d, 0x826, 0x83f, 0x858, 0x871, 0x88a, 0x8a3, 0x8bc,
+ 0x8d5, 0x8ef, 0x908, 0x921, 0x93a, 0x953, 0x96c, 0x985, 0x99e, 0x9b8,
+ 0x9d1, 0x9ea, 0xa03, 0xa1c, 0xa35, 0xa4e, 0xa67, 0xa80, 0xa9a, 0xab3,
+ 0xacc, 0xae5, 0xafe, 0xb17, 0xb30, 0xb49, 0xb62, 0xb7c, 0xb95, 0xbae,
+ 0xbc7, 0xbe0, 0xbf9, 0xc12, 0xc2b, 0xc44, 0xc5d, 0xc77, 0xc90, 0xca9,
+ 0xcc2, 0xcdb, 0xcf4, 0xd0d, 0xd26, 0xd3f, 0xd59, 0xd72, 0xd8b, 0xda4,
+ 0xdbd, 0xdd6, 0xdef, 0xe08, 0xe21, 0xe3a, 0xe53, 0xe6d, 0xe86, 0xe9f,
+ 0xeb8, 0xed1, 0xeea, 0xf03, 0xf1c, 0xf35, 0xf4e, 0xf67, 0xf81, 0xf9a,
+ 0xfb3, 0xfcc, 0xfe5, 0xffe, 0x1017, 0x1030, 0x1049, 0x1062, 0x107b, 0x1094,
+ 0x10ae, 0x10c7, 0x10e0, 0x10f9, 0x1112, 0x112b, 0x1144, 0x115d, 0x1176, 0x118f,
+ 0x11a8, 0x11c1, 0x11da, 0x11f4, 0x120d, 0x1226, 0x123f, 0x1258, 0x1271, 0x128a,
+ 0x12a3, 0x12bc, 0x12d5, 0x12ee, 0x1307, 0x1320, 0x1339, 0x1352, 0x136c, 0x1385,
+ 0x139e, 0x13b7, 0x13d0, 0x13e9, 0x1402, 0x141b, 0x1434, 0x144d, 0x1466, 0x147f,
+ 0x1498, 0x14b1, 0x14ca, 0x14e3, 0x14fc, 0x1515, 0x152e, 0x1548, 0x1561, 0x157a,
+ 0x1593, 0x15ac, 0x15c5, 0x15de, 0x15f7, 0x1610, 0x1629, 0x1642, 0x165b, 0x1674,
+ 0x168d, 0x16a6, 0x16bf, 0x16d8, 0x16f1, 0x170a, 0x1723, 0x173c, 0x1755, 0x176e,
+ 0x1787, 0x17a0, 0x17b9, 0x17d2, 0x17eb, 0x1804, 0x181d, 0x1837, 0x1850, 0x1869,
+ 0x1882, 0x189b, 0x18b4, 0x18cd, 0x18e6, 0x18ff, 0x1918, 0x1931, 0x194a, 0x1963,
+ 0x197c, 0x1995, 0x19ae, 0x19c7, 0x19e0, 0x19f9, 0x1a12, 0x1a2b, 0x1a44, 0x1a5d,
+ 0x1a76, 0x1a8f, 0x1aa8, 0x1ac1, 0x1ada, 0x1af3, 0x1b0c, 0x1b25, 0x1b3e, 0x1b57,
+ 0x1b70, 0x1b89, 0x1ba2, 0x1bbb, 0x1bd4, 0x1bed, 0x1c06, 0x1c1f, 0x1c38, 0x1c51,
+ 0x1c69, 0x1c82, 0x1c9b, 0x1cb4, 0x1ccd, 0x1ce6, 0x1cff, 0x1d18, 0x1d31, 0x1d4a,
+ 0x1d63, 0x1d7c, 0x1d95, 0x1dae, 0x1dc7, 0x1de0, 0x1df9, 0x1e12, 0x1e2b, 0x1e44,
+ 0x1e5d, 0x1e76, 0x1e8f, 0x1ea8, 0x1ec1, 0x1eda, 0x1ef3, 0x1f0b, 0x1f24, 0x1f3d,
+ 0x1f56, 0x1f6f, 0x1f88, 0x1fa1, 0x1fba, 0x1fd3, 0x1fec, 0x2005, 0x201e, 0x2037,
+ 0x2050, 0x2069, 0x2082, 0x209a, 0x20b3, 0x20cc, 0x20e5, 0x20fe, 0x2117, 0x2130,
+ 0x2149, 0x2162, 0x217b, 0x2194, 0x21ad, 0x21c6, 0x21de, 0x21f7, 0x2210, 0x2229,
+ 0x2242, 0x225b, 0x2274, 0x228d, 0x22a6, 0x22bf, 0x22d7, 0x22f0, 0x2309, 0x2322,
+ 0x233b, 0x2354, 0x236d, 0x2386, 0x239f, 0x23b8, 0x23d0, 0x23e9, 0x2402, 0x241b,
+ 0x2434, 0x244d, 0x2466, 0x247f, 0x2497, 0x24b0, 0x24c9, 0x24e2, 0x24fb, 0x2514,
+ 0x252d, 0x2546, 0x255e, 0x2577, 0x2590, 0x25a9, 0x25c2, 0x25db, 0x25f4, 0x260c,
+ 0x2625, 0x263e, 0x2657, 0x2670, 0x2689, 0x26a2, 0x26ba, 0x26d3, 0x26ec, 0x2705,
+ 0x271e, 0x2737, 0x274f, 0x2768, 0x2781, 0x279a, 0x27b3, 0x27cc, 0x27e4, 0x27fd,
+ 0x2816, 0x282f, 0x2848, 0x2860, 0x2879, 0x2892, 0x28ab, 0x28c4, 0x28dd, 0x28f5,
+ 0x290e, 0x2927, 0x2940, 0x2959, 0x2971, 0x298a, 0x29a3, 0x29bc, 0x29d5, 0x29ed,
+ 0x2a06, 0x2a1f, 0x2a38, 0x2a51, 0x2a69, 0x2a82, 0x2a9b, 0x2ab4, 0x2acc, 0x2ae5,
+ 0x2afe, 0x2b17, 0x2b30, 0x2b48, 0x2b61, 0x2b7a, 0x2b93, 0x2bab, 0x2bc4, 0x2bdd,
+ 0x2bf6, 0x2c0e, 0x2c27, 0x2c40, 0x2c59, 0x2c71, 0x2c8a, 0x2ca3, 0x2cbc, 0x2cd4,
+ 0x2ced, 0x2d06, 0x2d1f, 0x2d37, 0x2d50, 0x2d69, 0x2d82, 0x2d9a, 0x2db3, 0x2dcc,
+ 0x2de5, 0x2dfd, 0x2e16, 0x2e2f, 0x2e47, 0x2e60, 0x2e79, 0x2e92, 0x2eaa, 0x2ec3,
+ 0x2edc, 0x2ef4, 0x2f0d, 0x2f26, 0x2f3f, 0x2f57, 0x2f70, 0x2f89, 0x2fa1, 0x2fba,
+ 0x2fd3, 0x2feb, 0x3004, 0x301d, 0x3035, 0x304e, 0x3067, 0x307f, 0x3098, 0x30b1,
+ 0x30ca, 0x30e2, 0x30fb, 0x3114, 0x312c, 0x3145, 0x315e, 0x3176, 0x318f, 0x31a7,
+ 0x31c0, 0x31d9, 0x31f1, 0x320a, 0x3223, 0x323b, 0x3254, 0x326d, 0x3285, 0x329e,
+ 0x32b7, 0x32cf, 0x32e8, 0x3300, 0x3319, 0x3332, 0x334a, 0x3363, 0x337c, 0x3394,
+ 0x33ad, 0x33c5, 0x33de, 0x33f7, 0x340f, 0x3428, 0x3440, 0x3459, 0x3472, 0x348a,
+ 0x34a3, 0x34bb, 0x34d4, 0x34ed, 0x3505, 0x351e, 0x3536, 0x354f, 0x3568, 0x3580,
+ 0x3599, 0x35b1, 0x35ca, 0x35e2, 0x35fb, 0x3614, 0x362c, 0x3645, 0x365d, 0x3676,
+ 0x368e, 0x36a7, 0x36c0, 0x36d8, 0x36f1, 0x3709, 0x3722, 0x373a, 0x3753, 0x376b,
+ 0x3784, 0x379c, 0x37b5, 0x37cd, 0x37e6, 0x37fe, 0x3817, 0x3830, 0x3848, 0x3861,
+ 0x3879, 0x3892, 0x38aa, 0x38c3, 0x38db, 0x38f4, 0x390c, 0x3925, 0x393d, 0x3956,
+ 0x396e, 0x3987, 0x399f, 0x39b8, 0x39d0, 0x39e9, 0x3a01, 0x3a1a, 0x3a32, 0x3a4a,
+ 0x3a63, 0x3a7b, 0x3a94, 0x3aac, 0x3ac5, 0x3add, 0x3af6, 0x3b0e, 0x3b27, 0x3b3f,
+ 0x3b58, 0x3b70, 0x3b88, 0x3ba1, 0x3bb9, 0x3bd2, 0x3bea, 0x3c03, 0x3c1b, 0x3c33,
+ 0x3c4c, 0x3c64, 0x3c7d, 0x3c95, 0x3cae, 0x3cc6, 0x3cde, 0x3cf7, 0x3d0f, 0x3d28,
+ 0x3d40, 0x3d58, 0x3d71, 0x3d89, 0x3da2, 0x3dba, 0x3dd2, 0x3deb, 0x3e03, 0x3e1c,
+ 0x3e34, 0x3e4c, 0x3e65, 0x3e7d, 0x3e95, 0x3eae, 0x3ec6, 0x3edf, 0x3ef7, 0x3f0f,
+ 0x3f28, 0x3f40, 0x3f58, 0x3f71, 0x3f89, 0x3fa1, 0x3fba, 0x3fd2, 0x3fea, 0x4003,
+ 0x401b, 0x4033, 0x404c, 0x4064, 0x407c, 0x4095, 0x40ad, 0x40c5, 0x40de, 0x40f6,
+ 0x410e, 0x4127, 0x413f, 0x4157, 0x416f, 0x4188, 0x41a0, 0x41b8, 0x41d1, 0x41e9,
+ 0x4201, 0x421a, 0x4232, 0x424a, 0x4262, 0x427b, 0x4293, 0x42ab, 0x42c3, 0x42dc,
+ 0x42f4, 0x430c, 0x4324, 0x433d, 0x4355, 0x436d, 0x4385, 0x439e, 0x43b6, 0x43ce,
+ 0x43e6, 0x43ff, 0x4417, 0x442f, 0x4447, 0x4460, 0x4478, 0x4490, 0x44a8, 0x44c0,
+ 0x44d9, 0x44f1, 0x4509, 0x4521, 0x4539, 0x4552, 0x456a, 0x4582, 0x459a, 0x45b2,
+ 0x45cb, 0x45e3, 0x45fb, 0x4613, 0x462b, 0x4643, 0x465c, 0x4674, 0x468c, 0x46a4,
+ 0x46bc, 0x46d4, 0x46ec, 0x4705, 0x471d, 0x4735, 0x474d, 0x4765, 0x477d, 0x4795,
+ 0x47ae, 0x47c6, 0x47de, 0x47f6, 0x480e, 0x4826, 0x483e, 0x4856, 0x486f, 0x4887,
+ 0x489f, 0x48b7, 0x48cf, 0x48e7, 0x48ff, 0x4917, 0x492f, 0x4947, 0x495f, 0x4978,
+ 0x4990, 0x49a8, 0x49c0, 0x49d8, 0x49f0, 0x4a08, 0x4a20, 0x4a38, 0x4a50, 0x4a68,
+ 0x4a80, 0x4a98, 0x4ab0, 0x4ac8, 0x4ae0, 0x4af8, 0x4b10, 0x4b28, 0x4b40, 0x4b58,
+ 0x4b71, 0x4b89, 0x4ba1, 0x4bb9, 0x4bd1, 0x4be9, 0x4c01, 0x4c19, 0x4c31, 0x4c49,
+ 0x4c61, 0x4c79, 0x4c90, 0x4ca8, 0x4cc0, 0x4cd8, 0x4cf0, 0x4d08, 0x4d20, 0x4d38,
+ 0x4d50, 0x4d68, 0x4d80, 0x4d98, 0x4db0, 0x4dc8, 0x4de0, 0x4df8, 0x4e10, 0x4e28,
+ 0x4e40, 0x4e58, 0x4e70, 0x4e87, 0x4e9f, 0x4eb7, 0x4ecf, 0x4ee7, 0x4eff, 0x4f17,
+ 0x4f2f, 0x4f47, 0x4f5f, 0x4f77, 0x4f8e, 0x4fa6, 0x4fbe, 0x4fd6, 0x4fee, 0x5006,
+ 0x501e, 0x5036, 0x504d, 0x5065, 0x507d, 0x5095, 0x50ad, 0x50c5, 0x50dd, 0x50f4,
+ 0x510c, 0x5124, 0x513c, 0x5154, 0x516c, 0x5183, 0x519b, 0x51b3, 0x51cb, 0x51e3,
+ 0x51fb, 0x5212, 0x522a, 0x5242, 0x525a, 0x5272, 0x5289, 0x52a1, 0x52b9, 0x52d1,
+ 0x52e8, 0x5300, 0x5318, 0x5330, 0x5348, 0x535f, 0x5377, 0x538f, 0x53a7, 0x53be,
+ 0x53d6, 0x53ee, 0x5406, 0x541d, 0x5435, 0x544d, 0x5464, 0x547c, 0x5494, 0x54ac,
+ 0x54c3, 0x54db, 0x54f3, 0x550b, 0x5522, 0x553a, 0x5552, 0x5569, 0x5581, 0x5599,
+ 0x55b0, 0x55c8, 0x55e0, 0x55f7, 0x560f, 0x5627, 0x563e, 0x5656, 0x566e, 0x5685,
+ 0x569d, 0x56b5, 0x56cc, 0x56e4, 0x56fc, 0x5713, 0x572b, 0x5743, 0x575a, 0x5772,
+ 0x5789, 0x57a1, 0x57b9, 0x57d0, 0x57e8, 0x57ff, 0x5817, 0x582f, 0x5846, 0x585e,
+ 0x5875, 0x588d, 0x58a5, 0x58bc, 0x58d4, 0x58eb, 0x5903, 0x591a, 0x5932, 0x594a,
+ 0x5961, 0x5979, 0x5990, 0x59a8, 0x59bf, 0x59d7, 0x59ee, 0x5a06, 0x5a1d, 0x5a35,
+ 0x5a4c, 0x5a64, 0x5a7b, 0x5a93, 0x5aaa, 0x5ac2, 0x5ad9, 0x5af1, 0x5b08, 0x5b20,
+ 0x5b37, 0x5b4f, 0x5b66, 0x5b7e, 0x5b95, 0x5bad, 0x5bc4, 0x5bdc, 0x5bf3, 0x5c0b,
+ 0x5c22, 0x5c3a, 0x5c51, 0x5c68, 0x5c80, 0x5c97, 0x5caf, 0x5cc6, 0x5cde, 0x5cf5,
+ 0x5d0c, 0x5d24, 0x5d3b, 0x5d53, 0x5d6a, 0x5d81, 0x5d99, 0x5db0, 0x5dc8, 0x5ddf,
+ 0x5df6, 0x5e0e, 0x5e25, 0x5e3c, 0x5e54, 0x5e6b, 0x5e83, 0x5e9a, 0x5eb1, 0x5ec9,
+ 0x5ee0, 0x5ef7, 0x5f0f, 0x5f26, 0x5f3d, 0x5f55, 0x5f6c, 0x5f83, 0x5f9b, 0x5fb2,
+ 0x5fc9, 0x5fe1, 0x5ff8, 0x600f, 0x6026, 0x603e, 0x6055, 0x606c, 0x6084, 0x609b,
+ 0x60b2, 0x60c9, 0x60e1, 0x60f8, 0x610f, 0x6126, 0x613e, 0x6155, 0x616c, 0x6183,
+ 0x619b, 0x61b2, 0x61c9, 0x61e0, 0x61f8, 0x620f, 0x6226, 0x623d, 0x6254, 0x626c,
+ 0x6283, 0x629a, 0x62b1, 0x62c8, 0x62e0, 0x62f7, 0x630e, 0x6325, 0x633c, 0x6353,
+ 0x636b, 0x6382, 0x6399, 0x63b0, 0x63c7, 0x63de, 0x63f5, 0x640d, 0x6424, 0x643b,
+ 0x6452, 0x6469, 0x6480, 0x6497, 0x64ae, 0x64c6, 0x64dd, 0x64f4, 0x650b, 0x6522,
+ 0x6539, 0x6550, 0x6567, 0x657e, 0x6595, 0x65ac, 0x65c3, 0x65db, 0x65f2, 0x6609,
+ 0x6620, 0x6637, 0x664e, 0x6665, 0x667c, 0x6693, 0x66aa, 0x66c1, 0x66d8, 0x66ef,
+ 0x6706, 0x671d, 0x6734, 0x674b, 0x6762, 0x6779, 0x6790, 0x67a7, 0x67be, 0x67d5,
+ 0x67ec, 0x6803, 0x681a, 0x6831, 0x6848, 0x685f, 0x6876, 0x688d, 0x68a3, 0x68ba,
+ 0x68d1, 0x68e8, 0x68ff, 0x6916, 0x692d, 0x6944, 0x695b, 0x6972, 0x6989, 0x69a0,
+ 0x69b6, 0x69cd, 0x69e4, 0x69fb, 0x6a12, 0x6a29, 0x6a40, 0x6a57, 0x6a6d, 0x6a84,
+ 0x6a9b, 0x6ab2, 0x6ac9, 0x6ae0, 0x6af6, 0x6b0d, 0x6b24, 0x6b3b, 0x6b52, 0x6b69,
+ 0x6b7f, 0x6b96, 0x6bad, 0x6bc4, 0x6bdb, 0x6bf1, 0x6c08, 0x6c1f, 0x6c36, 0x6c4d,
+ 0x6c63, 0x6c7a, 0x6c91, 0x6ca8, 0x6cbe, 0x6cd5, 0x6cec, 0x6d03, 0x6d19, 0x6d30,
+ 0x6d47, 0x6d5e, 0x6d74, 0x6d8b, 0x6da2, 0x6db8, 0x6dcf, 0x6de6, 0x6dfc, 0x6e13,
+ 0x6e2a, 0x6e41, 0x6e57, 0x6e6e, 0x6e85, 0x6e9b, 0x6eb2, 0x6ec9, 0x6edf, 0x6ef6,
+ 0x6f0d, 0x6f23, 0x6f3a, 0x6f50, 0x6f67, 0x6f7e, 0x6f94, 0x6fab, 0x6fc2, 0x6fd8,
+ 0x6fef, 0x7005, 0x701c, 0x7033, 0x7049, 0x7060, 0x7076, 0x708d, 0x70a3, 0x70ba,
+ 0x70d1, 0x70e7, 0x70fe, 0x7114, 0x712b, 0x7141, 0x7158, 0x716e, 0x7185, 0x719b,
+ 0x71b2, 0x71c9, 0x71df, 0x71f6, 0x720c, 0x7223, 0x7239, 0x7250, 0x7266, 0x727c,
+ 0x7293, 0x72a9, 0x72c0, 0x72d6, 0x72ed, 0x7303, 0x731a, 0x7330, 0x7347, 0x735d,
+ 0x7373, 0x738a, 0x73a0, 0x73b7, 0x73cd, 0x73e4, 0x73fa, 0x7410, 0x7427, 0x743d,
+ 0x7454, 0x746a, 0x7480, 0x7497, 0x74ad, 0x74c3, 0x74da, 0x74f0, 0x7507, 0x751d,
+ 0x7533, 0x754a, 0x7560, 0x7576, 0x758d, 0x75a3, 0x75b9, 0x75d0, 0x75e6, 0x75fc,
+ 0x7612, 0x7629, 0x763f, 0x7655, 0x766c, 0x7682, 0x7698, 0x76ae, 0x76c5, 0x76db,
+ 0x76f1, 0x7708, 0x771e, 0x7734, 0x774a, 0x7760, 0x7777, 0x778d, 0x77a3, 0x77b9,
+ 0x77d0, 0x77e6, 0x77fc, 0x7812, 0x7828, 0x783f, 0x7855, 0x786b, 0x7881, 0x7897,
+ 0x78ad, 0x78c4, 0x78da, 0x78f0, 0x7906, 0x791c, 0x7932, 0x7949, 0x795f, 0x7975,
+ 0x798b, 0x79a1, 0x79b7, 0x79cd, 0x79e3, 0x79f9, 0x7a10, 0x7a26, 0x7a3c, 0x7a52,
+ 0x7a68, 0x7a7e, 0x7a94, 0x7aaa, 0x7ac0, 0x7ad6, 0x7aec, 0x7b02, 0x7b18, 0x7b2e,
+ 0x7b44, 0x7b5a, 0x7b70, 0x7b86, 0x7b9c, 0x7bb2, 0x7bc8, 0x7bde, 0x7bf4, 0x7c0a,
+ 0x7c20, 0x7c36, 0x7c4c, 0x7c62, 0x7c78, 0x7c8e, 0x7ca4, 0x7cba, 0x7cd0, 0x7ce6,
+ 0x7cfc, 0x7d12, 0x7d28, 0x7d3e, 0x7d54, 0x7d6a, 0x7d7f, 0x7d95, 0x7dab, 0x7dc1,
+ 0x7dd7, 0x7ded, 0x7e03, 0x7e19, 0x7e2f, 0x7e44, 0x7e5a, 0x7e70, 0x7e86, 0x7e9c,
+ 0x7eb2, 0x7ec8, 0x7edd, 0x7ef3, 0x7f09, 0x7f1f, 0x7f35, 0x7f4a, 0x7f60, 0x7f76,
+ 0x7f8c, 0x7fa2, 0x7fb7, 0x7fcd, 0x7fe3, 0x7ff9, 0x800f, 0x8024, 0x803a, 0x8050,
+ 0x8066, 0x807b, 0x8091, 0x80a7, 0x80bc, 0x80d2, 0x80e8, 0x80fe, 0x8113, 0x8129,
+ 0x813f, 0x8154, 0x816a, 0x8180, 0x8195, 0x81ab, 0x81c1, 0x81d6, 0x81ec, 0x8202,
+ 0x8217, 0x822d, 0x8243, 0x8258, 0x826e, 0x8284, 0x8299, 0x82af, 0x82c4, 0x82da,
+ 0x82f0, 0x8305, 0x831b, 0x8330, 0x8346, 0x835c, 0x8371, 0x8387, 0x839c, 0x83b2,
+ 0x83c7, 0x83dd, 0x83f2, 0x8408, 0x841d, 0x8433, 0x8449, 0x845e, 0x8474, 0x8489,
+ 0x849f, 0x84b4, 0x84ca, 0x84df, 0x84f5, 0x850a, 0x851f, 0x8535, 0x854a, 0x8560,
+ 0x8575, 0x858b, 0x85a0, 0x85b6, 0x85cb, 0x85e0, 0x85f6, 0x860b, 0x8621, 0x8636,
+ 0x864c, 0x8661, 0x8676, 0x868c, 0x86a1, 0x86b6, 0x86cc, 0x86e1, 0x86f7, 0x870c,
+ 0x8721, 0x8737, 0x874c, 0x8761, 0x8777, 0x878c, 0x87a1, 0x87b7, 0x87cc, 0x87e1,
+ 0x87f6, 0x880c, 0x8821, 0x8836, 0x884c, 0x8861, 0x8876, 0x888b, 0x88a1, 0x88b6,
+ 0x88cb, 0x88e0, 0x88f6, 0x890b, 0x8920, 0x8935, 0x894a, 0x8960, 0x8975, 0x898a,
+ 0x899f, 0x89b4, 0x89ca, 0x89df, 0x89f4, 0x8a09, 0x8a1e, 0x8a34, 0x8a49, 0x8a5e,
+ 0x8a73, 0x8a88, 0x8a9d, 0x8ab2, 0x8ac7, 0x8add, 0x8af2, 0x8b07, 0x8b1c, 0x8b31,
+ 0x8b46, 0x8b5b, 0x8b70, 0x8b85, 0x8b9a, 0x8baf, 0x8bc5, 0x8bda, 0x8bef, 0x8c04,
+ 0x8c19, 0x8c2e, 0x8c43, 0x8c58, 0x8c6d, 0x8c82, 0x8c97, 0x8cac, 0x8cc1, 0x8cd6,
+ 0x8ceb, 0x8d00, 0x8d15, 0x8d2a, 0x8d3f, 0x8d54, 0x8d69, 0x8d7e, 0x8d93, 0x8da7,
+ 0x8dbc, 0x8dd1, 0x8de6, 0x8dfb, 0x8e10, 0x8e25, 0x8e3a, 0x8e4f, 0x8e64, 0x8e79,
+ 0x8e8d, 0x8ea2, 0x8eb7, 0x8ecc, 0x8ee1, 0x8ef6, 0x8f0b, 0x8f1f, 0x8f34, 0x8f49,
+ 0x8f5e, 0x8f73, 0x8f88, 0x8f9c, 0x8fb1, 0x8fc6, 0x8fdb, 0x8ff0, 0x9004, 0x9019,
+ 0x902e, 0x9043, 0x9057, 0x906c, 0x9081, 0x9096, 0x90aa, 0x90bf, 0x90d4, 0x90e9,
+ 0x90fd, 0x9112, 0x9127, 0x913b, 0x9150, 0x9165, 0x9179, 0x918e, 0x91a3, 0x91b7,
+ 0x91cc, 0x91e1, 0x91f5, 0x920a, 0x921f, 0x9233, 0x9248, 0x925d, 0x9271, 0x9286,
+ 0x929a, 0x92af, 0x92c4, 0x92d8, 0x92ed, 0x9301, 0x9316, 0x932a, 0x933f, 0x9354,
+ 0x9368, 0x937d, 0x9391, 0x93a6, 0x93ba, 0x93cf, 0x93e3, 0x93f8, 0x940c, 0x9421,
+ 0x9435, 0x944a, 0x945e, 0x9473, 0x9487, 0x949c, 0x94b0, 0x94c5, 0x94d9, 0x94ee,
+ 0x9502, 0x9516, 0x952b, 0x953f, 0x9554, 0x9568, 0x957d, 0x9591, 0x95a5, 0x95ba,
+ 0x95ce, 0x95e2, 0x95f7, 0x960b, 0x9620, 0x9634, 0x9648, 0x965d, 0x9671, 0x9685,
+ 0x969a, 0x96ae, 0x96c2, 0x96d7, 0x96eb, 0x96ff, 0x9713, 0x9728, 0x973c, 0x9750,
+ 0x9765, 0x9779, 0x978d, 0x97a1, 0x97b6, 0x97ca, 0x97de, 0x97f2, 0x9807, 0x981b,
+ 0x982f, 0x9843, 0x9857, 0x986c, 0x9880, 0x9894, 0x98a8, 0x98bc, 0x98d0, 0x98e5,
+ 0x98f9, 0x990d, 0x9921, 0x9935, 0x9949, 0x995d, 0x9972, 0x9986, 0x999a, 0x99ae,
+ 0x99c2, 0x99d6, 0x99ea, 0x99fe, 0x9a12, 0x9a26, 0x9a3a, 0x9a4f, 0x9a63, 0x9a77,
+ 0x9a8b, 0x9a9f, 0x9ab3, 0x9ac7, 0x9adb, 0x9aef, 0x9b03, 0x9b17, 0x9b2b, 0x9b3f,
+ 0x9b53, 0x9b67, 0x9b7b, 0x9b8f, 0x9ba3, 0x9bb7, 0x9bca, 0x9bde, 0x9bf2, 0x9c06,
+ 0x9c1a, 0x9c2e, 0x9c42, 0x9c56, 0x9c6a, 0x9c7e, 0x9c92, 0x9ca6, 0x9cb9, 0x9ccd,
+ 0x9ce1, 0x9cf5, 0x9d09, 0x9d1d, 0x9d31, 0x9d44, 0x9d58, 0x9d6c, 0x9d80, 0x9d94,
+ 0x9da7, 0x9dbb, 0x9dcf, 0x9de3, 0x9df7, 0x9e0a, 0x9e1e, 0x9e32, 0x9e46, 0x9e59,
+ 0x9e6d, 0x9e81, 0x9e95, 0x9ea8, 0x9ebc, 0x9ed0, 0x9ee3, 0x9ef7, 0x9f0b, 0x9f1f,
+ 0x9f32, 0x9f46, 0x9f5a, 0x9f6d, 0x9f81, 0x9f95, 0x9fa8, 0x9fbc, 0x9fd0, 0x9fe3,
+ 0x9ff7, 0xa00a, 0xa01e, 0xa032, 0xa045, 0xa059, 0xa06c, 0xa080, 0xa094, 0xa0a7,
+ 0xa0bb, 0xa0ce, 0xa0e2, 0xa0f5, 0xa109, 0xa11c, 0xa130, 0xa143, 0xa157, 0xa16b,
+ 0xa17e, 0xa192, 0xa1a5, 0xa1b9, 0xa1cc, 0xa1df, 0xa1f3, 0xa206, 0xa21a, 0xa22d,
+ 0xa241, 0xa254, 0xa268, 0xa27b, 0xa28e, 0xa2a2, 0xa2b5, 0xa2c9, 0xa2dc, 0xa2ef,
+ 0xa303, 0xa316, 0xa32a, 0xa33d, 0xa350, 0xa364, 0xa377, 0xa38a, 0xa39e, 0xa3b1,
+ 0xa3c4, 0xa3d8, 0xa3eb, 0xa3fe, 0xa412, 0xa425, 0xa438, 0xa44b, 0xa45f, 0xa472,
+ 0xa485, 0xa498, 0xa4ac, 0xa4bf, 0xa4d2, 0xa4e5, 0xa4f9, 0xa50c, 0xa51f, 0xa532,
+ 0xa545, 0xa559, 0xa56c, 0xa57f, 0xa592, 0xa5a5, 0xa5b8, 0xa5cc, 0xa5df, 0xa5f2,
+ 0xa605, 0xa618, 0xa62b, 0xa63e, 0xa652, 0xa665, 0xa678, 0xa68b, 0xa69e, 0xa6b1,
+ 0xa6c4, 0xa6d7, 0xa6ea, 0xa6fd, 0xa710, 0xa723, 0xa736, 0xa749, 0xa75c, 0xa76f,
+ 0xa782, 0xa795, 0xa7a8, 0xa7bb, 0xa7ce, 0xa7e1, 0xa7f4, 0xa807, 0xa81a, 0xa82d,
+ 0xa840, 0xa853, 0xa866, 0xa879, 0xa88c, 0xa89f, 0xa8b2, 0xa8c5, 0xa8d7, 0xa8ea,
+ 0xa8fd, 0xa910, 0xa923, 0xa936, 0xa949, 0xa95c, 0xa96e, 0xa981, 0xa994, 0xa9a7,
+ 0xa9ba, 0xa9cd, 0xa9df, 0xa9f2, 0xaa05, 0xaa18, 0xaa2a, 0xaa3d, 0xaa50, 0xaa63,
+ 0xaa76, 0xaa88, 0xaa9b, 0xaaae, 0xaac1, 0xaad3, 0xaae6, 0xaaf9, 0xab0b, 0xab1e,
+ 0xab31, 0xab43, 0xab56, 0xab69, 0xab7b, 0xab8e, 0xaba1, 0xabb3, 0xabc6, 0xabd9,
+ 0xabeb, 0xabfe, 0xac11, 0xac23, 0xac36, 0xac48, 0xac5b, 0xac6d, 0xac80, 0xac93,
+ 0xaca5, 0xacb8, 0xacca, 0xacdd, 0xacef, 0xad02, 0xad14, 0xad27, 0xad39, 0xad4c,
+ 0xad5e, 0xad71, 0xad83, 0xad96, 0xada8, 0xadbb, 0xadcd, 0xade0, 0xadf2, 0xae05,
+ 0xae17, 0xae29, 0xae3c, 0xae4e, 0xae61, 0xae73, 0xae85, 0xae98, 0xaeaa, 0xaebd,
+ 0xaecf, 0xaee1, 0xaef4, 0xaf06, 0xaf18, 0xaf2b, 0xaf3d, 0xaf4f, 0xaf62, 0xaf74,
+ 0xaf86, 0xaf99, 0xafab, 0xafbd, 0xafcf, 0xafe2, 0xaff4, 0xb006, 0xb018, 0xb02b,
+ 0xb03d, 0xb04f, 0xb061, 0xb074, 0xb086, 0xb098, 0xb0aa, 0xb0bc, 0xb0ce, 0xb0e1,
+ 0xb0f3, 0xb105, 0xb117, 0xb129, 0xb13b, 0xb14e, 0xb160, 0xb172, 0xb184, 0xb196,
+ 0xb1a8, 0xb1ba, 0xb1cc, 0xb1de, 0xb1f0, 0xb203, 0xb215, 0xb227, 0xb239, 0xb24b,
+ 0xb25d, 0xb26f, 0xb281, 0xb293, 0xb2a5, 0xb2b7, 0xb2c9, 0xb2db, 0xb2ed, 0xb2ff,
+ 0xb311, 0xb323, 0xb335, 0xb347, 0xb358, 0xb36a, 0xb37c, 0xb38e, 0xb3a0, 0xb3b2,
+ 0xb3c4, 0xb3d6, 0xb3e8, 0xb3fa, 0xb40b, 0xb41d, 0xb42f, 0xb441, 0xb453, 0xb465,
+ 0xb477, 0xb488, 0xb49a, 0xb4ac, 0xb4be, 0xb4d0, 0xb4e1, 0xb4f3, 0xb505, 0xb517,
+ 0xb528, 0xb53a, 0xb54c, 0xb55e, 0xb56f, 0xb581, 0xb593, 0xb5a5, 0xb5b6, 0xb5c8,
+ 0xb5da, 0xb5eb, 0xb5fd, 0xb60f, 0xb620, 0xb632, 0xb644, 0xb655, 0xb667, 0xb679,
+ 0xb68a, 0xb69c, 0xb6ad, 0xb6bf, 0xb6d1, 0xb6e2, 0xb6f4, 0xb705, 0xb717, 0xb729,
+ 0xb73a, 0xb74c, 0xb75d, 0xb76f, 0xb780, 0xb792, 0xb7a3, 0xb7b5, 0xb7c6, 0xb7d8,
+ 0xb7e9, 0xb7fb, 0xb80c, 0xb81e, 0xb82f, 0xb841, 0xb852, 0xb864, 0xb875, 0xb886,
+ 0xb898, 0xb8a9, 0xb8bb, 0xb8cc, 0xb8dd, 0xb8ef, 0xb900, 0xb912, 0xb923, 0xb934,
+ 0xb946, 0xb957, 0xb968, 0xb97a, 0xb98b, 0xb99c, 0xb9ae, 0xb9bf, 0xb9d0, 0xb9e1,
+ 0xb9f3, 0xba04, 0xba15, 0xba26, 0xba38, 0xba49, 0xba5a, 0xba6b, 0xba7d, 0xba8e,
+ 0xba9f, 0xbab0, 0xbac1, 0xbad3, 0xbae4, 0xbaf5, 0xbb06, 0xbb17, 0xbb28, 0xbb3a,
+ 0xbb4b, 0xbb5c, 0xbb6d, 0xbb7e, 0xbb8f, 0xbba0, 0xbbb1, 0xbbc3, 0xbbd4, 0xbbe5,
+ 0xbbf6, 0xbc07, 0xbc18, 0xbc29, 0xbc3a, 0xbc4b, 0xbc5c, 0xbc6d, 0xbc7e, 0xbc8f,
+ 0xbca0, 0xbcb1, 0xbcc2, 0xbcd3, 0xbce4, 0xbcf5, 0xbd06, 0xbd17, 0xbd28, 0xbd39,
+ 0xbd4a, 0xbd5a, 0xbd6b, 0xbd7c, 0xbd8d, 0xbd9e, 0xbdaf, 0xbdc0, 0xbdd1, 0xbde2,
+ 0xbdf2, 0xbe03, 0xbe14, 0xbe25, 0xbe36, 0xbe47, 0xbe57, 0xbe68, 0xbe79, 0xbe8a,
+ 0xbe9b, 0xbeab, 0xbebc, 0xbecd, 0xbede, 0xbeee, 0xbeff, 0xbf10, 0xbf21, 0xbf31,
+ 0xbf42, 0xbf53, 0xbf63, 0xbf74, 0xbf85, 0xbf95, 0xbfa6, 0xbfb7, 0xbfc7, 0xbfd8,
+ 0xbfe9, 0xbff9, 0xc00a, 0xc01b, 0xc02b, 0xc03c, 0xc04c, 0xc05d, 0xc06e, 0xc07e,
+ 0xc08f, 0xc09f, 0xc0b0, 0xc0c0, 0xc0d1, 0xc0e1, 0xc0f2, 0xc102, 0xc113, 0xc123,
+ 0xc134, 0xc144, 0xc155, 0xc165, 0xc176, 0xc186, 0xc197, 0xc1a7, 0xc1b8, 0xc1c8,
+ 0xc1d8, 0xc1e9, 0xc1f9, 0xc20a, 0xc21a, 0xc22a, 0xc23b, 0xc24b, 0xc25c, 0xc26c,
+ 0xc27c, 0xc28d, 0xc29d, 0xc2ad, 0xc2be, 0xc2ce, 0xc2de, 0xc2ee, 0xc2ff, 0xc30f,
+ 0xc31f, 0xc330, 0xc340, 0xc350, 0xc360, 0xc371, 0xc381, 0xc391, 0xc3a1, 0xc3b1,
+ 0xc3c2, 0xc3d2, 0xc3e2, 0xc3f2, 0xc402, 0xc413, 0xc423, 0xc433, 0xc443, 0xc453,
+ 0xc463, 0xc473, 0xc483, 0xc494, 0xc4a4, 0xc4b4, 0xc4c4, 0xc4d4, 0xc4e4, 0xc4f4,
+ 0xc504, 0xc514, 0xc524, 0xc534, 0xc544, 0xc554, 0xc564, 0xc574, 0xc584, 0xc594,
+ 0xc5a4, 0xc5b4, 0xc5c4, 0xc5d4, 0xc5e4, 0xc5f4, 0xc604, 0xc614, 0xc624, 0xc634,
+ 0xc644, 0xc653, 0xc663, 0xc673, 0xc683, 0xc693, 0xc6a3, 0xc6b3, 0xc6c2, 0xc6d2,
+ 0xc6e2, 0xc6f2, 0xc702, 0xc712, 0xc721, 0xc731, 0xc741, 0xc751, 0xc761, 0xc770,
+ 0xc780, 0xc790, 0xc7a0, 0xc7af, 0xc7bf, 0xc7cf, 0xc7de, 0xc7ee, 0xc7fe, 0xc80d,
+ 0xc81d, 0xc82d, 0xc83c, 0xc84c, 0xc85c, 0xc86b, 0xc87b, 0xc88b, 0xc89a, 0xc8aa,
+ 0xc8ba, 0xc8c9, 0xc8d9, 0xc8e8, 0xc8f8, 0xc907, 0xc917, 0xc927, 0xc936, 0xc946,
+ 0xc955, 0xc965, 0xc974, 0xc984, 0xc993, 0xc9a3, 0xc9b2, 0xc9c2, 0xc9d1, 0xc9e1,
+ 0xc9f0, 0xc9ff, 0xca0f, 0xca1e, 0xca2e, 0xca3d, 0xca4d, 0xca5c, 0xca6b, 0xca7b,
+ 0xca8a, 0xca99, 0xcaa9, 0xcab8, 0xcac7, 0xcad7, 0xcae6, 0xcaf5, 0xcb05, 0xcb14,
+ 0xcb23, 0xcb33, 0xcb42, 0xcb51, 0xcb61, 0xcb70, 0xcb7f, 0xcb8e, 0xcb9e, 0xcbad,
+ 0xcbbc, 0xcbcb, 0xcbda, 0xcbea, 0xcbf9, 0xcc08, 0xcc17, 0xcc26, 0xcc35, 0xcc45,
+ 0xcc54, 0xcc63, 0xcc72, 0xcc81, 0xcc90, 0xcc9f, 0xccae, 0xccbe, 0xcccd, 0xccdc,
+ 0xcceb, 0xccfa, 0xcd09, 0xcd18, 0xcd27, 0xcd36, 0xcd45, 0xcd54, 0xcd63, 0xcd72,
+ 0xcd81, 0xcd90, 0xcd9f, 0xcdae, 0xcdbd, 0xcdcc, 0xcddb, 0xcdea, 0xcdf9, 0xce08,
+ 0xce17, 0xce25, 0xce34, 0xce43, 0xce52, 0xce61, 0xce70, 0xce7f, 0xce8e, 0xce9c,
+ 0xceab, 0xceba, 0xcec9, 0xced8, 0xcee7, 0xcef5, 0xcf04, 0xcf13, 0xcf22, 0xcf30,
+ 0xcf3f, 0xcf4e, 0xcf5d, 0xcf6b, 0xcf7a, 0xcf89, 0xcf98, 0xcfa6, 0xcfb5, 0xcfc4,
+ 0xcfd2, 0xcfe1, 0xcff0, 0xcffe, 0xd00d, 0xd01c, 0xd02a, 0xd039, 0xd047, 0xd056,
+ 0xd065, 0xd073, 0xd082, 0xd090, 0xd09f, 0xd0ae, 0xd0bc, 0xd0cb, 0xd0d9, 0xd0e8,
+ 0xd0f6, 0xd105, 0xd113, 0xd122, 0xd130, 0xd13f, 0xd14d, 0xd15c, 0xd16a, 0xd179,
+ 0xd187, 0xd195, 0xd1a4, 0xd1b2, 0xd1c1, 0xd1cf, 0xd1de, 0xd1ec, 0xd1fa, 0xd209,
+ 0xd217, 0xd225, 0xd234, 0xd242, 0xd250, 0xd25f, 0xd26d, 0xd27b, 0xd28a, 0xd298,
+ 0xd2a6, 0xd2b5, 0xd2c3, 0xd2d1, 0xd2df, 0xd2ee, 0xd2fc, 0xd30a, 0xd318, 0xd326,
+ 0xd335, 0xd343, 0xd351, 0xd35f, 0xd36d, 0xd37c, 0xd38a, 0xd398, 0xd3a6, 0xd3b4,
+ 0xd3c2, 0xd3d0, 0xd3df, 0xd3ed, 0xd3fb, 0xd409, 0xd417, 0xd425, 0xd433, 0xd441,
+ 0xd44f, 0xd45d, 0xd46b, 0xd479, 0xd487, 0xd495, 0xd4a3, 0xd4b1, 0xd4bf, 0xd4cd,
+ 0xd4db, 0xd4e9, 0xd4f7, 0xd505, 0xd513, 0xd521, 0xd52f, 0xd53d, 0xd54b, 0xd559,
+ 0xd566, 0xd574, 0xd582, 0xd590, 0xd59e, 0xd5ac, 0xd5ba, 0xd5c7, 0xd5d5, 0xd5e3,
+ 0xd5f1, 0xd5ff, 0xd60c, 0xd61a, 0xd628, 0xd636, 0xd644, 0xd651, 0xd65f, 0xd66d,
+ 0xd67a, 0xd688, 0xd696, 0xd6a4, 0xd6b1, 0xd6bf, 0xd6cd, 0xd6da, 0xd6e8, 0xd6f6,
+ 0xd703, 0xd711, 0xd71f, 0xd72c, 0xd73a, 0xd747, 0xd755, 0xd763, 0xd770, 0xd77e,
+ 0xd78b, 0xd799, 0xd7a6, 0xd7b4, 0xd7c1, 0xd7cf, 0xd7dc, 0xd7ea, 0xd7f8, 0xd805,
+ 0xd812, 0xd820, 0xd82d, 0xd83b, 0xd848, 0xd856, 0xd863, 0xd871, 0xd87e, 0xd88b,
+ 0xd899, 0xd8a6, 0xd8b4, 0xd8c1, 0xd8ce, 0xd8dc, 0xd8e9, 0xd8f6, 0xd904, 0xd911,
+ 0xd91e, 0xd92c, 0xd939, 0xd946, 0xd954, 0xd961, 0xd96e, 0xd97b, 0xd989, 0xd996,
+ 0xd9a3, 0xd9b0, 0xd9be, 0xd9cb, 0xd9d8, 0xd9e5, 0xd9f2, 0xda00, 0xda0d, 0xda1a,
+ 0xda27, 0xda34, 0xda41, 0xda4f, 0xda5c, 0xda69, 0xda76, 0xda83, 0xda90, 0xda9d,
+ 0xdaaa, 0xdab7, 0xdac4, 0xdad1, 0xdade, 0xdaeb, 0xdaf8, 0xdb05, 0xdb12, 0xdb1f,
+ 0xdb2c, 0xdb39, 0xdb46, 0xdb53, 0xdb60, 0xdb6d, 0xdb7a, 0xdb87, 0xdb94, 0xdba1,
+ 0xdbae, 0xdbbb, 0xdbc8, 0xdbd5, 0xdbe1, 0xdbee, 0xdbfb, 0xdc08, 0xdc15, 0xdc22,
+ 0xdc2f, 0xdc3b, 0xdc48, 0xdc55, 0xdc62, 0xdc6f, 0xdc7b, 0xdc88, 0xdc95, 0xdca2,
+ 0xdcae, 0xdcbb, 0xdcc8, 0xdcd5, 0xdce1, 0xdcee, 0xdcfb, 0xdd07, 0xdd14, 0xdd21,
+ 0xdd2d, 0xdd3a, 0xdd47, 0xdd53, 0xdd60, 0xdd6c, 0xdd79, 0xdd86, 0xdd92, 0xdd9f,
+ 0xddab, 0xddb8, 0xddc5, 0xddd1, 0xddde, 0xddea, 0xddf7, 0xde03, 0xde10, 0xde1c,
+ 0xde29, 0xde35, 0xde42, 0xde4e, 0xde5b, 0xde67, 0xde74, 0xde80, 0xde8c, 0xde99,
+ 0xdea5, 0xdeb2, 0xdebe, 0xdeca, 0xded7, 0xdee3, 0xdef0, 0xdefc, 0xdf08, 0xdf15,
+ 0xdf21, 0xdf2d, 0xdf39, 0xdf46, 0xdf52, 0xdf5e, 0xdf6b, 0xdf77, 0xdf83, 0xdf8f,
+ 0xdf9c, 0xdfa8, 0xdfb4, 0xdfc0, 0xdfcd, 0xdfd9, 0xdfe5, 0xdff1, 0xdffd, 0xe009,
+ 0xe016, 0xe022, 0xe02e, 0xe03a, 0xe046, 0xe052, 0xe05e, 0xe06a, 0xe077, 0xe083,
+ 0xe08f, 0xe09b, 0xe0a7, 0xe0b3, 0xe0bf, 0xe0cb, 0xe0d7, 0xe0e3, 0xe0ef, 0xe0fb,
+ 0xe107, 0xe113, 0xe11f, 0xe12b, 0xe137, 0xe143, 0xe14f, 0xe15b, 0xe167, 0xe172,
+ 0xe17e, 0xe18a, 0xe196, 0xe1a2, 0xe1ae, 0xe1ba, 0xe1c6, 0xe1d1, 0xe1dd, 0xe1e9,
+ 0xe1f5, 0xe201, 0xe20d, 0xe218, 0xe224, 0xe230, 0xe23c, 0xe247, 0xe253, 0xe25f,
+ 0xe26b, 0xe276, 0xe282, 0xe28e, 0xe299, 0xe2a5, 0xe2b1, 0xe2bd, 0xe2c8, 0xe2d4,
+ 0xe2df, 0xe2eb, 0xe2f7, 0xe302, 0xe30e, 0xe31a, 0xe325, 0xe331, 0xe33c, 0xe348,
+ 0xe353, 0xe35f, 0xe36b, 0xe376, 0xe382, 0xe38d, 0xe399, 0xe3a4, 0xe3b0, 0xe3bb,
+ 0xe3c7, 0xe3d2, 0xe3de, 0xe3e9, 0xe3f4, 0xe400, 0xe40b, 0xe417, 0xe422, 0xe42e,
+ 0xe439, 0xe444, 0xe450, 0xe45b, 0xe466, 0xe472, 0xe47d, 0xe488, 0xe494, 0xe49f,
+ 0xe4aa, 0xe4b6, 0xe4c1, 0xe4cc, 0xe4d7, 0xe4e3, 0xe4ee, 0xe4f9, 0xe504, 0xe510,
+ 0xe51b, 0xe526, 0xe531, 0xe53d, 0xe548, 0xe553, 0xe55e, 0xe569, 0xe574, 0xe57f,
+ 0xe58b, 0xe596, 0xe5a1, 0xe5ac, 0xe5b7, 0xe5c2, 0xe5cd, 0xe5d8, 0xe5e3, 0xe5ee,
+ 0xe5f9, 0xe605, 0xe610, 0xe61b, 0xe626, 0xe631, 0xe63c, 0xe647, 0xe652, 0xe65c,
+ 0xe667, 0xe672, 0xe67d, 0xe688, 0xe693, 0xe69e, 0xe6a9, 0xe6b4, 0xe6bf, 0xe6ca,
+ 0xe6d5, 0xe6df, 0xe6ea, 0xe6f5, 0xe700, 0xe70b, 0xe716, 0xe720, 0xe72b, 0xe736,
+ 0xe741, 0xe74c, 0xe756, 0xe761, 0xe76c, 0xe777, 0xe781, 0xe78c, 0xe797, 0xe7a1,
+ 0xe7ac, 0xe7b7, 0xe7c2, 0xe7cc, 0xe7d7, 0xe7e2, 0xe7ec, 0xe7f7, 0xe801, 0xe80c,
+ 0xe817, 0xe821, 0xe82c, 0xe836, 0xe841, 0xe84c, 0xe856, 0xe861, 0xe86b, 0xe876,
+ 0xe880, 0xe88b, 0xe895, 0xe8a0, 0xe8aa, 0xe8b5, 0xe8bf, 0xe8ca, 0xe8d4, 0xe8df,
+ 0xe8e9, 0xe8f3, 0xe8fe, 0xe908, 0xe913, 0xe91d, 0xe927, 0xe932, 0xe93c, 0xe947,
+ 0xe951, 0xe95b, 0xe966, 0xe970, 0xe97a, 0xe985, 0xe98f, 0xe999, 0xe9a3, 0xe9ae,
+ 0xe9b8, 0xe9c2, 0xe9cc, 0xe9d7, 0xe9e1, 0xe9eb, 0xe9f5, 0xe9ff, 0xea0a, 0xea14,
+ 0xea1e, 0xea28, 0xea32, 0xea3c, 0xea47, 0xea51, 0xea5b, 0xea65, 0xea6f, 0xea79,
+ 0xea83, 0xea8d, 0xea97, 0xeaa1, 0xeaab, 0xeab6, 0xeac0, 0xeaca, 0xead4, 0xeade,
+ 0xeae8, 0xeaf2, 0xeafc, 0xeb06, 0xeb0f, 0xeb19, 0xeb23, 0xeb2d, 0xeb37, 0xeb41,
+ 0xeb4b, 0xeb55, 0xeb5f, 0xeb69, 0xeb73, 0xeb7c, 0xeb86, 0xeb90, 0xeb9a, 0xeba4,
+ 0xebae, 0xebb7, 0xebc1, 0xebcb, 0xebd5, 0xebdf, 0xebe8, 0xebf2, 0xebfc, 0xec06,
+ 0xec0f, 0xec19, 0xec23, 0xec2c, 0xec36, 0xec40, 0xec4a, 0xec53, 0xec5d, 0xec66,
+ 0xec70, 0xec7a, 0xec83, 0xec8d, 0xec97, 0xeca0, 0xecaa, 0xecb3, 0xecbd, 0xecc6,
+ 0xecd0, 0xecda, 0xece3, 0xeced, 0xecf6, 0xed00, 0xed09, 0xed13, 0xed1c, 0xed26,
+ 0xed2f, 0xed38, 0xed42, 0xed4b, 0xed55, 0xed5e, 0xed68, 0xed71, 0xed7a, 0xed84,
+ 0xed8d, 0xed97, 0xeda0, 0xeda9, 0xedb3, 0xedbc, 0xedc5, 0xedcf, 0xedd8, 0xede1,
+ 0xedea, 0xedf4, 0xedfd, 0xee06, 0xee0f, 0xee19, 0xee22, 0xee2b, 0xee34, 0xee3e,
+ 0xee47, 0xee50, 0xee59, 0xee62, 0xee6b, 0xee75, 0xee7e, 0xee87, 0xee90, 0xee99,
+ 0xeea2, 0xeeab, 0xeeb4, 0xeebd, 0xeec7, 0xeed0, 0xeed9, 0xeee2, 0xeeeb, 0xeef4,
+ 0xeefd, 0xef06, 0xef0f, 0xef18, 0xef21, 0xef2a, 0xef33, 0xef3c, 0xef45, 0xef4d,
+ 0xef56, 0xef5f, 0xef68, 0xef71, 0xef7a, 0xef83, 0xef8c, 0xef95, 0xef9d, 0xefa6,
+ 0xefaf, 0xefb8, 0xefc1, 0xefca, 0xefd2, 0xefdb, 0xefe4, 0xefed, 0xeff5, 0xeffe,
+ 0xf007, 0xf010, 0xf018, 0xf021, 0xf02a, 0xf033, 0xf03b, 0xf044, 0xf04d, 0xf055,
+ 0xf05e, 0xf067, 0xf06f, 0xf078, 0xf080, 0xf089, 0xf092, 0xf09a, 0xf0a3, 0xf0ab,
+ 0xf0b4, 0xf0bc, 0xf0c5, 0xf0ce, 0xf0d6, 0xf0df, 0xf0e7, 0xf0f0, 0xf0f8, 0xf101,
+ 0xf109, 0xf111, 0xf11a, 0xf122, 0xf12b, 0xf133, 0xf13c, 0xf144, 0xf14c, 0xf155,
+ 0xf15d, 0xf166, 0xf16e, 0xf176, 0xf17f, 0xf187, 0xf18f, 0xf198, 0xf1a0, 0xf1a8,
+ 0xf1b1, 0xf1b9, 0xf1c1, 0xf1c9, 0xf1d2, 0xf1da, 0xf1e2, 0xf1ea, 0xf1f3, 0xf1fb,
+ 0xf203, 0xf20b, 0xf213, 0xf21b, 0xf224, 0xf22c, 0xf234, 0xf23c, 0xf244, 0xf24c,
+ 0xf254, 0xf25d, 0xf265, 0xf26d, 0xf275, 0xf27d, 0xf285, 0xf28d, 0xf295, 0xf29d,
+ 0xf2a5, 0xf2ad, 0xf2b5, 0xf2bd, 0xf2c5, 0xf2cd, 0xf2d5, 0xf2dd, 0xf2e5, 0xf2ed,
+ 0xf2f5, 0xf2fd, 0xf304, 0xf30c, 0xf314, 0xf31c, 0xf324, 0xf32c, 0xf334, 0xf33c,
+ 0xf343, 0xf34b, 0xf353, 0xf35b, 0xf363, 0xf36a, 0xf372, 0xf37a, 0xf382, 0xf38a,
+ 0xf391, 0xf399, 0xf3a1, 0xf3a8, 0xf3b0, 0xf3b8, 0xf3c0, 0xf3c7, 0xf3cf, 0xf3d7,
+ 0xf3de, 0xf3e6, 0xf3ed, 0xf3f5, 0xf3fd, 0xf404, 0xf40c, 0xf413, 0xf41b, 0xf423,
+ 0xf42a, 0xf432, 0xf439, 0xf441, 0xf448, 0xf450, 0xf457, 0xf45f, 0xf466, 0xf46e,
+ 0xf475, 0xf47d, 0xf484, 0xf48c, 0xf493, 0xf49a, 0xf4a2, 0xf4a9, 0xf4b1, 0xf4b8,
+ 0xf4bf, 0xf4c7, 0xf4ce, 0xf4d5, 0xf4dd, 0xf4e4, 0xf4eb, 0xf4f3, 0xf4fa, 0xf501,
+ 0xf509, 0xf510, 0xf517, 0xf51e, 0xf526, 0xf52d, 0xf534, 0xf53b, 0xf543, 0xf54a,
+ 0xf551, 0xf558, 0xf55f, 0xf566, 0xf56e, 0xf575, 0xf57c, 0xf583, 0xf58a, 0xf591,
+ 0xf598, 0xf59f, 0xf5a6, 0xf5ae, 0xf5b5, 0xf5bc, 0xf5c3, 0xf5ca, 0xf5d1, 0xf5d8,
+ 0xf5df, 0xf5e6, 0xf5ed, 0xf5f4, 0xf5fb, 0xf602, 0xf609, 0xf610, 0xf616, 0xf61d,
+ 0xf624, 0xf62b, 0xf632, 0xf639, 0xf640, 0xf647, 0xf64e, 0xf654, 0xf65b, 0xf662,
+ 0xf669, 0xf670, 0xf677, 0xf67d, 0xf684, 0xf68b, 0xf692, 0xf698, 0xf69f, 0xf6a6,
+ 0xf6ad, 0xf6b3, 0xf6ba, 0xf6c1, 0xf6c7, 0xf6ce, 0xf6d5, 0xf6db, 0xf6e2, 0xf6e9,
+ 0xf6ef, 0xf6f6, 0xf6fd, 0xf703, 0xf70a, 0xf710, 0xf717, 0xf71e, 0xf724, 0xf72b,
+ 0xf731, 0xf738, 0xf73e, 0xf745, 0xf74b, 0xf752, 0xf758, 0xf75f, 0xf765, 0xf76c,
+ 0xf772, 0xf779, 0xf77f, 0xf785, 0xf78c, 0xf792, 0xf799, 0xf79f, 0xf7a5, 0xf7ac,
+ 0xf7b2, 0xf7b8, 0xf7bf, 0xf7c5, 0xf7cb, 0xf7d2, 0xf7d8, 0xf7de, 0xf7e5, 0xf7eb,
+ 0xf7f1, 0xf7f7, 0xf7fe, 0xf804, 0xf80a, 0xf810, 0xf816, 0xf81d, 0xf823, 0xf829,
+ 0xf82f, 0xf835, 0xf83b, 0xf842, 0xf848, 0xf84e, 0xf854, 0xf85a, 0xf860, 0xf866,
+ 0xf86c, 0xf872, 0xf878, 0xf87e, 0xf885, 0xf88b, 0xf891, 0xf897, 0xf89d, 0xf8a3,
+ 0xf8a9, 0xf8af, 0xf8b4, 0xf8ba, 0xf8c0, 0xf8c6, 0xf8cc, 0xf8d2, 0xf8d8, 0xf8de,
+ 0xf8e4, 0xf8ea, 0xf8f0, 0xf8f5, 0xf8fb, 0xf901, 0xf907, 0xf90d, 0xf913, 0xf918,
+ 0xf91e, 0xf924, 0xf92a, 0xf930, 0xf935, 0xf93b, 0xf941, 0xf946, 0xf94c, 0xf952,
+ 0xf958, 0xf95d, 0xf963, 0xf969, 0xf96e, 0xf974, 0xf97a, 0xf97f, 0xf985, 0xf98a,
+ 0xf990, 0xf996, 0xf99b, 0xf9a1, 0xf9a6, 0xf9ac, 0xf9b2, 0xf9b7, 0xf9bd, 0xf9c2,
+ 0xf9c8, 0xf9cd, 0xf9d3, 0xf9d8, 0xf9de, 0xf9e3, 0xf9e8, 0xf9ee, 0xf9f3, 0xf9f9,
+ 0xf9fe, 0xfa04, 0xfa09, 0xfa0e, 0xfa14, 0xfa19, 0xfa1f, 0xfa24, 0xfa29, 0xfa2f,
+ 0xfa34, 0xfa39, 0xfa3e, 0xfa44, 0xfa49, 0xfa4e, 0xfa54, 0xfa59, 0xfa5e, 0xfa63,
+ 0xfa69, 0xfa6e, 0xfa73, 0xfa78, 0xfa7d, 0xfa83, 0xfa88, 0xfa8d, 0xfa92, 0xfa97,
+ 0xfa9c, 0xfaa1, 0xfaa7, 0xfaac, 0xfab1, 0xfab6, 0xfabb, 0xfac0, 0xfac5, 0xfaca,
+ 0xfacf, 0xfad4, 0xfad9, 0xfade, 0xfae3, 0xfae8, 0xfaed, 0xfaf2, 0xfaf7, 0xfafc,
+ 0xfb01, 0xfb06, 0xfb0b, 0xfb10, 0xfb15, 0xfb1a, 0xfb1f, 0xfb23, 0xfb28, 0xfb2d,
+ 0xfb32, 0xfb37, 0xfb3c, 0xfb40, 0xfb45, 0xfb4a, 0xfb4f, 0xfb54, 0xfb58, 0xfb5d,
+ 0xfb62, 0xfb67, 0xfb6b, 0xfb70, 0xfb75, 0xfb7a, 0xfb7e, 0xfb83, 0xfb88, 0xfb8c,
+ 0xfb91, 0xfb96, 0xfb9a, 0xfb9f, 0xfba4, 0xfba8, 0xfbad, 0xfbb1, 0xfbb6, 0xfbbb,
+ 0xfbbf, 0xfbc4, 0xfbc8, 0xfbcd, 0xfbd1, 0xfbd6, 0xfbda, 0xfbdf, 0xfbe3, 0xfbe8,
+ 0xfbec, 0xfbf1, 0xfbf5, 0xfbfa, 0xfbfe, 0xfc02, 0xfc07, 0xfc0b, 0xfc10, 0xfc14,
+ 0xfc18, 0xfc1d, 0xfc21, 0xfc26, 0xfc2a, 0xfc2e, 0xfc33, 0xfc37, 0xfc3b, 0xfc3f,
+ 0xfc44, 0xfc48, 0xfc4c, 0xfc51, 0xfc55, 0xfc59, 0xfc5d, 0xfc61, 0xfc66, 0xfc6a,
+ 0xfc6e, 0xfc72, 0xfc76, 0xfc7b, 0xfc7f, 0xfc83, 0xfc87, 0xfc8b, 0xfc8f, 0xfc93,
+ 0xfc97, 0xfc9b, 0xfca0, 0xfca4, 0xfca8, 0xfcac, 0xfcb0, 0xfcb4, 0xfcb8, 0xfcbc,
+ 0xfcc0, 0xfcc4, 0xfcc8, 0xfccc, 0xfcd0, 0xfcd4, 0xfcd8, 0xfcdc, 0xfcdf, 0xfce3,
+ 0xfce7, 0xfceb, 0xfcef, 0xfcf3, 0xfcf7, 0xfcfb, 0xfcfe, 0xfd02, 0xfd06, 0xfd0a,
+ 0xfd0e, 0xfd12, 0xfd15, 0xfd19, 0xfd1d, 0xfd21, 0xfd24, 0xfd28, 0xfd2c, 0xfd30,
+ 0xfd33, 0xfd37, 0xfd3b, 0xfd3e, 0xfd42, 0xfd46, 0xfd49, 0xfd4d, 0xfd51, 0xfd54,
+ 0xfd58, 0xfd5b, 0xfd5f, 0xfd63, 0xfd66, 0xfd6a, 0xfd6d, 0xfd71, 0xfd74, 0xfd78,
+ 0xfd7c, 0xfd7f, 0xfd83, 0xfd86, 0xfd89, 0xfd8d, 0xfd90, 0xfd94, 0xfd97, 0xfd9b,
+ 0xfd9e, 0xfda2, 0xfda5, 0xfda8, 0xfdac, 0xfdaf, 0xfdb3, 0xfdb6, 0xfdb9, 0xfdbd,
+ 0xfdc0, 0xfdc3, 0xfdc7, 0xfdca, 0xfdcd, 0xfdd0, 0xfdd4, 0xfdd7, 0xfdda, 0xfddd,
+ 0xfde1, 0xfde4, 0xfde7, 0xfdea, 0xfdee, 0xfdf1, 0xfdf4, 0xfdf7, 0xfdfa, 0xfdfd,
+ 0xfe01, 0xfe04, 0xfe07, 0xfe0a, 0xfe0d, 0xfe10, 0xfe13, 0xfe16, 0xfe19, 0xfe1c,
+ 0xfe1f, 0xfe22, 0xfe25, 0xfe28, 0xfe2b, 0xfe2e, 0xfe31, 0xfe34, 0xfe37, 0xfe3a,
+ 0xfe3d, 0xfe40, 0xfe43, 0xfe46, 0xfe49, 0xfe4c, 0xfe4f, 0xfe52, 0xfe55, 0xfe57,
+ 0xfe5a, 0xfe5d, 0xfe60, 0xfe63, 0xfe66, 0xfe68, 0xfe6b, 0xfe6e, 0xfe71, 0xfe73,
+ 0xfe76, 0xfe79, 0xfe7c, 0xfe7e, 0xfe81, 0xfe84, 0xfe87, 0xfe89, 0xfe8c, 0xfe8f,
+ 0xfe91, 0xfe94, 0xfe97, 0xfe99, 0xfe9c, 0xfe9e, 0xfea1, 0xfea4, 0xfea6, 0xfea9,
+ 0xfeab, 0xfeae, 0xfeb0, 0xfeb3, 0xfeb5, 0xfeb8, 0xfeba, 0xfebd, 0xfebf, 0xfec2,
+ 0xfec4, 0xfec7, 0xfec9, 0xfecc, 0xfece, 0xfed1, 0xfed3, 0xfed5, 0xfed8, 0xfeda,
+ 0xfedd, 0xfedf, 0xfee1, 0xfee4, 0xfee6, 0xfee8, 0xfeeb, 0xfeed, 0xfeef, 0xfef1,
+ 0xfef4, 0xfef6, 0xfef8, 0xfefb, 0xfefd, 0xfeff, 0xff01, 0xff03, 0xff06, 0xff08,
+ 0xff0a, 0xff0c, 0xff0e, 0xff10, 0xff13, 0xff15, 0xff17, 0xff19, 0xff1b, 0xff1d,
+ 0xff1f, 0xff21, 0xff23, 0xff25, 0xff28, 0xff2a, 0xff2c, 0xff2e, 0xff30, 0xff32,
+ 0xff34, 0xff36, 0xff38, 0xff3a, 0xff3b, 0xff3d, 0xff3f, 0xff41, 0xff43, 0xff45,
+ 0xff47, 0xff49, 0xff4b, 0xff4d, 0xff4e, 0xff50, 0xff52, 0xff54, 0xff56, 0xff58,
+ 0xff59, 0xff5b, 0xff5d, 0xff5f, 0xff60, 0xff62, 0xff64, 0xff66, 0xff67, 0xff69,
+ 0xff6b, 0xff6c, 0xff6e, 0xff70, 0xff71, 0xff73, 0xff75, 0xff76, 0xff78, 0xff7a,
+ 0xff7b, 0xff7d, 0xff7e, 0xff80, 0xff82, 0xff83, 0xff85, 0xff86, 0xff88, 0xff89,
+ 0xff8b, 0xff8c, 0xff8e, 0xff8f, 0xff91, 0xff92, 0xff94, 0xff95, 0xff96, 0xff98,
+ 0xff99, 0xff9b, 0xff9c, 0xff9d, 0xff9f, 0xffa0, 0xffa2, 0xffa3, 0xffa4, 0xffa6,
+ 0xffa7, 0xffa8, 0xffa9, 0xffab, 0xffac, 0xffad, 0xffaf, 0xffb0, 0xffb1, 0xffb2,
+ 0xffb4, 0xffb5, 0xffb6, 0xffb7, 0xffb8, 0xffb9, 0xffbb, 0xffbc, 0xffbd, 0xffbe,
+ 0xffbf, 0xffc0, 0xffc1, 0xffc2, 0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9,
+ 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1, 0xffd2, 0xffd3,
+ 0xffd4, 0xffd5, 0xffd5, 0xffd6, 0xffd7, 0xffd8, 0xffd9, 0xffda, 0xffdb, 0xffdc,
+ 0xffdc, 0xffdd, 0xffde, 0xffdf, 0xffe0, 0xffe0, 0xffe1, 0xffe2, 0xffe3, 0xffe3,
+ 0xffe4, 0xffe5, 0xffe6, 0xffe6, 0xffe7, 0xffe8, 0xffe8, 0xffe9, 0xffea, 0xffea,
+ 0xffeb, 0xffec, 0xffec, 0xffed, 0xffed, 0xffee, 0xffef, 0xffef, 0xfff0, 0xfff0,
+ 0xfff1, 0xfff1, 0xfff2, 0xfff2, 0xfff3, 0xfff3, 0xfff4, 0xfff4, 0xfff5, 0xfff5,
+ 0xfff6, 0xfff6, 0xfff7, 0xfff7, 0xfff7, 0xfff8, 0xfff8, 0xfff9, 0xfff9, 0xfff9,
+ 0xfffa, 0xfffa, 0xfffa, 0xfffb, 0xfffb, 0xfffb, 0xfffc, 0xfffc, 0xfffc, 0xfffc,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
+/* in actual sine / cosine functions, the last 5
+ * values will be added with a int '1' */
+
+/* FIXME: The coefficients could use a bit of cleanup */
+/*----------------------------------------------------------------------
+ * Function: ovl_util_sine()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static int ovl_util_sine(int radiant_input)
+{
+
+ /*
+ * the radiant input parameter is a 32 signed number where the LSB
+ * 16 bits are the FP portion
+ */
+
+ short sign = 0; /* 0 positive for and 1 for negative */
+ int pi_half_count = 0;
+ int pi_half = 0;
+ int balance = 0;
+ int answer = 0;
+
+ /* lets rule that the input is a signed integer in which:
+ * the first 16 bits represent the integer
+ * the last 16 bits represent the floating point portion */
+
+ /* first we have to normalize it to a positive number.*/
+ if(radiant_input<0)
+ {
+ sign = 1;
+ radiant_input = -radiant_input;
+ }
+
+ /* let's get pi/2 variable with 16 LSB FP just like this input data.*/
+ pi_half = 0x3243f; /* = 3.141586 */
+ pi_half += 0x1; /* for rounding off */
+ pi_half = pi_half >> 1; /* divided by 2 */
+
+
+ /* now we have to count how many pi/2 there are in this value
+ * (since pi/2 = 90' = one quarter sine wave from 0 to 1) */
+ balance = radiant_input;
+ while(balance >= pi_half)
+ {
+ balance = balance - pi_half;
+ ++pi_half_count;
+ }
+
+ /* using the pi_half_count, we can figure out how many 90 degrees.
+ * thru the sine wave we are looking at */
+ pi_half_count = pi_half_count%4;
+
+ /*
+ * balance is something between '0' and 'pi/2' - exactly what we need
+ * to use in the table however, this is 16 bits shifted and our table
+ * is a max of 12 bits - lets not forget to adjust but first we have to
+ * use the balance according to which 90' of the sine wave we are in
+ */
+
+ /* now we get the actual sine value of excess that's less than a
+ * quarter pi if quart_count = 0, then answer is direct from table; */
+ if(pi_half_count == 0){
+
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+ balance = balance << 13;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+ balance = balance / pi_half;
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ }
+
+ /* if quart_count = 1, then formula is =
+ * answer = sin[(pi/2) - balance)] */
+ else if(pi_half_count == 1){
+ balance = pi_half - balance;
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ }
+
+ /*
+ * if quart_count = 2, then formula is = answer = the negative of the
+ * case it being 0;
+ */
+ else if(pi_half_count == 2){
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ answer = 0 - answer;
+ }
+
+ /*
+ * if quart_count = 3, then formula is = answer = the negative of the
+ * case it being 1;
+ */
+ else if(pi_half_count == 3){
+ balance = pi_half - balance;
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ answer = 0 - answer;
+ }
+
+ if(sign==1) {
+ answer = 0-answer;
+ }
+
+ return answer;
+ /*
+ * so return value is a signed short where 16 MSBits are integer and
+ * 16 LSBits are FP
+ */
+}
+
+/*----------------------------------------------------------------------
+ * Function: ovl_util_cosine()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static int ovl_util_cosine(int radiant_input)
+{
+ /*
+ * the radiant input parameter is a 32 signed number where the LSB
+ * 16 bits are the FP portion
+ */
+
+ short sign = 0; /* 0 positive for and 1 for negative */
+ int pi_half_count = 0;
+ int pi_half = 0;
+ int balance = 0;
+ int answer = 0;
+
+ /* lets rule that the input is a signed integer in which:
+ * the first 16 bits represent the integer
+ * the last 16 bits represent the floating point portion */
+
+ /* first we have to normalize it to a positive number.*/
+ if(radiant_input<0) {
+ sign = 1;
+ radiant_input = -radiant_input;
+ }
+
+ /* let's get pi/2 variable with 16 LSB FP just like this input data.*/
+ pi_half = 0x3243f; /* = 3.141586 */
+ pi_half += 0x1; /* for rounding off */
+ pi_half = pi_half >> 1; /* divided by 2 */
+
+
+ /* now we have to count how many pi/2 there are in this value
+ * (since pi/2 = 90' = one quarter sine wave from 0 to 1) */
+ balance = radiant_input;
+ while(balance >= pi_half) {
+ balance = balance - pi_half;
+ ++pi_half_count;
+ }
+
+ /* using the pi_half_count, we can figure out how many 90 degrees.
+ * thru the sine wave we are looking at */
+ pi_half_count = pi_half_count%4;
+
+ /*
+ * balance is something between '0' and 'pi/2' - exactly what we need
+ * to use in the table however, this is 16 bits shifted and our table
+ * is a max of 12 bits - lets not forget to adjust but first we have
+ * to use the balance according to which 90' of the sine wave we are in
+ */
+
+ /* now we get the actual sine value of excess
+ * that's less than a quarter pi
+ * if quart_count = 0, then formula is = sine quarter # 1
+ * then formula is = answer = sin[(pi/2) - balance)] */
+ if(pi_half_count == 0) {
+ balance = pi_half - balance;
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ }
+
+ /* if quart_count = 1, then formula is = sine quarter # 2
+ * then formula is = answer = the negative of the case it being 0; */
+ else if(pi_half_count == 1){
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+
+ answer = 0 - answer;
+ }
+
+ /*if quart_count = 2, then formula is = sine quarter # 3
+ * then formula is = answer = the negative of the case it being 1; */
+ else if(pi_half_count == 2){
+ balance = pi_half - balance;
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ answer = 0 - answer;
+ }
+
+ /*if quart_count = 3, then formula is = sine quarter # 0
+ * now we get the actual sine value of excess that's
+ * less than a quarter pi then answer is direct from table;*/
+ else if(pi_half_count == 3){
+
+ balance = balance << 13;
+ /* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+ balance = balance / pi_half;
+ /* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+ balance = balance + 1; /* for round up */
+ balance = balance >> 1;
+ /* now balance should be a 13 bit number but */
+ /* bit 13 will never be '1' since balance was less than pi_half */
+
+ if(balance>4095) {
+ balance = 4095;
+ }
+
+ answer = wave_table[balance];
+ if(balance>4090) {
+ answer |= BIT16;
+ }
+ }
+
+ if(sign==1) {
+ answer = 0-answer;
+ }
+
+ return answer;
+ /*
+ * so return value is a signed short where bit_16 = integer and 16
+ * LSBits are FP
+ */
+}
+
+/*----------------------------------------------------------------------
+ * Function: ovl_set_coeff_reg()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_set_coeff_reg(
+ int * fpint_Coeff,
+ unsigned short wMantSize,
+ unsigned short * pCoeff,
+ unsigned short wPosition)
+{
+
+ /*
+ * fpint_Coeff is a pointer to signed int that follows
+ * MS 16 bits =integer, LS 16 bits =floating point for f.p. portion of
+ * scaling
+ */
+
+ unsigned short wRes;
+ unsigned short sign;
+ int coeff;
+ int maxVal;
+ int wCoeff_exp3;
+ int wCoeff_exp2;
+ int wCoeff_exp1;
+ int wCoeff_exp0;
+
+ sign = 0;
+ maxVal = 1 << wMantSize;
+ coeff = *fpint_Coeff;
+ if (coeff < 0) {
+ sign = 1;
+ coeff = - coeff;
+ }
+
+ wRes = 12 - wMantSize;
+
+ wCoeff_exp3 = coeff * 4;
+ wCoeff_exp2 = coeff * 2;
+ wCoeff_exp1 = coeff;
+ wCoeff_exp0 = coeff;
+ wCoeff_exp0 += BIT0;
+ wCoeff_exp0 = wCoeff_exp0 >> 1;
+
+ wCoeff_exp3 = wCoeff_exp3 + (1 << (16 - wMantSize -1));
+ /* round coeff to the nearest bit X */
+ /* where X is the last MS bit that will
+ * be left out of the mantissa*/
+ wCoeff_exp3 = wCoeff_exp3 >> (16 - wMantSize);
+ /* now wCoeff is a unsigned short where */
+ /* FP portion matched maxVal */
+
+ wCoeff_exp2 = wCoeff_exp2 + (1 << (16 - wMantSize -1));
+ /* round coeff to the nearest bit X */
+ /* where X is the last MS bit that will
+ * be left out of the mantissa */
+
+ wCoeff_exp2 = wCoeff_exp2 >> (16 - wMantSize);
+ /* now wCoeff is a unsigned short where */
+ /* FP portion matched maxVal */
+
+ wCoeff_exp1 = wCoeff_exp1 + (1 << (16 - wMantSize -1));
+ /* round coeff to the nearest bit X */
+ /* where X is the last MS bit that will
+ * be left out of the mantissa */
+
+ wCoeff_exp1 = wCoeff_exp1 >> (16 - wMantSize);
+ /* now wCoeff is a unsigned short where */
+ /* FP portion matched maxVal */
+
+ wCoeff_exp0 = wCoeff_exp0 + (1 << (16 - wMantSize -1));
+ /* round coeff to the nearest bit X */
+ /* where X is the last MS bit that will
+ * be left out of the mantissa */
+
+ wCoeff_exp0 = wCoeff_exp0 >> (16 - wMantSize);
+ /* now wCoeff is a unsigned short where */
+ /* FP portion matched maxVal */
+
+ pCoeff[wPosition] = 0;
+
+ if ( wCoeff_exp3 < maxVal ) {
+ pCoeff[wPosition] |= (3 << 12);/*exponent */
+ pCoeff[wPosition] |= (wCoeff_exp3 << wRes);/*mantissa*/
+
+ *fpint_Coeff = wCoeff_exp3 << (16 - wMantSize);
+ *fpint_Coeff += BIT1;
+ *fpint_Coeff = *fpint_Coeff >> 2;
+ } else if ( wCoeff_exp2 < maxVal ) {
+ pCoeff[wPosition] |= (2 << 12);/*.exponent */
+ pCoeff[wPosition] |= (wCoeff_exp2 << wRes);/*mantissa*/
+
+ *fpint_Coeff = wCoeff_exp2 << (16 - wMantSize);
+ *fpint_Coeff += BIT0;
+ *fpint_Coeff = *fpint_Coeff >> 1;
+ } else if ( wCoeff_exp1 < maxVal ) {
+ pCoeff[wPosition] |= (1 << 12);/*.exponent */
+ pCoeff[wPosition] |= (wCoeff_exp1 << wRes);/*mantissa*/
+
+ *fpint_Coeff = wCoeff_exp1 << (16 - wMantSize);
+ } else if ( wCoeff_exp0 < maxVal ) {
+ pCoeff[wPosition] |= (wCoeff_exp0 << wRes);/*mantissa*/
+
+ *fpint_Coeff = wCoeff_exp0 << (16 - wMantSize);
+ *fpint_Coeff = *fpint_Coeff * 2;
+ } else {
+ return 0; /*Coeff out of range*/
+ }
+
+ if(sign) {
+ pCoeff[wPosition] |= BIT15;/*sign */
+ }
+
+ if (sign) {
+ *fpint_Coeff = -(*fpint_Coeff);
+ }
+
+ return 1;
+
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_coeff_regs()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+int ddCoeff[17][5];
+unsigned short wTapAdjust[5];
+void ovl_update_coeff_regs(
+ unsigned short wTaps,
+ int fpint_cutoff,
+ unsigned short bHor,
+ unsigned short bY,
+ unsigned short * pCoeff)
+{
+
+ unsigned short i, j, j1, num, pos, wMantSize;
+ unsigned short bVandC;
+
+ int val, sinc, window, sum, x, y;
+ int dCoeff[5*32];
+ int dDiff;
+ unsigned short wTap2Fix;
+
+ const int pi = 0x3243f; /* = 3.141586 << 16 */
+ /*+- 3.1415926535; */
+
+ /* H Scale */
+ if (bHor==1)
+ wMantSize = 7;
+ else
+ wMantSize = 6;
+
+ /*vertal & Chroma */
+ if(bHor==0 && bY==0)
+ bVandC = 1;
+ else
+ bVandC = 0;
+
+ /*
+ * 1 - let's make this fixed point number smaller by 4 bits,
+ * since it will be a denominator later
+ */
+ /* 2 - dont forget to round it at the 3rd bit */
+ fpint_cutoff += BIT3;
+ fpint_cutoff = fpint_cutoff >> 4; /* 16 bits of FP (reduced from 20) */
+
+ num = wTaps * 16;
+ for (i = 0; i < num*2; i++) {
+ /* fpint cutoff is 16 bits */
+ val = ((1 << 30)/fpint_cutoff);
+ /*14 bits of FP (after dividing the fpint_cutoff */
+ val += BIT3;
+ val = val >> 4; /* val is now 10 bits of FP */
+ val = val * wTaps * pi;
+ /*now 26 bits of FP (increase from 10 after multiply pi)*/
+ val += BIT5;
+ val = val >> 6; /*20 bits of FP (reduced from 26 bits)*/
+ val = val * (((i - num) << 8)/(2*num)); /*28 bits of FP now*/
+ if(val<0) {
+ val -= BIT11;
+ } else {
+ val += BIT11;
+ }
+ val = val >> 12; /* 16 bits of FP (reduced from 22 bits)*/
+
+ if (val == 0) {
+ sinc = (1 << 16); /*sinc = 1.0;*/
+ } else {
+ sinc = ovl_util_sine(val);
+ /* dont forget val has 14 bits of FP to it */
+ sinc = sinc << 12; /* sinc now has 28 bit FP */
+ if(val<0) {
+ val -= BIT3;
+ } else {
+ val += BIT3;
+ }
+ val = val >> 4; /* val now has 12 bit FP */
+ sinc = sinc / val; /* the new sinc is back to 16 bit FP */
+ }
+
+ /* hanning window */
+ window = (pi << 12)/num; /* 16 bits increased to 28 bits FP */
+ window += BIT11;
+ window = window >> 12;
+ window = i * window;
+ window = ovl_util_cosine(window);
+ /* note cosine param is 16 bits FP to it */
+ window += 1;
+ window = window >> 1; /* divided by 2 */
+ window = ((1 << 15) /*0.5*/ - window);
+
+ if(window<0) {
+ window -= BIT3;
+ } else {
+ window += BIT3;
+ }
+ window = window >> 4; /* now window is with 12 bit FP*/
+ if(sinc<0) {
+ sinc -= BIT3;
+ } else {
+ sinc += BIT3;
+ }
+ sinc = sinc >> 4; /* now sinc is with 12 bit FP */
+
+ dCoeff[i] = sinc * window;
+ /* dCoeff item is with 24 bit FP --> lets reduce to 16*/
+ if(dCoeff[i]<0) {
+ dCoeff[i] -= BIT7;
+ } else {
+ dCoeff[i] += BIT7;
+ }
+ dCoeff[i] = dCoeff[i] >> 8;
+
+ }
+
+ for (i = 0; i < 17; i++) {
+ /* normalize the coefficient */
+ sum = 0;
+ for (j = 0; j < wTaps; j++) {
+ pos = i + j * 32;
+ sum += dCoeff[pos];
+ /* sum takes from dCeoff so it also has 16bit FP to it */
+ }
+ for (j = 0; j < wTaps; j++) {
+ pos = i + j * 32;
+ x = dCoeff[pos] << 11; /* x now has (16+11)=27 fp to it */
+ y = sum;
+ if(y<0)
+ y -= BIT7;
+ else
+ y += BIT7;
+ y = y >> 8; /* y now has (16-8)=8 fp to it */
+ ddCoeff[i][j] = x/y; /* ddCoeff has 27-8 = 19 fp to it */
+ if(ddCoeff[i][j] < 0)
+ ddCoeff[i][j] -= BIT2;
+ else
+ ddCoeff[i][j] += BIT2;
+ ddCoeff[i][j] = ddCoeff[i][j] >> 3;
+ /*ddCoeff is back to 16 bit fp (19-3) */
+ }
+
+ /*
+ * set the coefficient registers and get the data in floating
+ * point format
+ */
+ for (j = 0; j < wTaps; j++) {
+ pos = j + i * wTaps;
+ if ( (j == (wTaps - 1)/2) && (!bVandC) ) {
+ ovl_set_coeff_reg(&ddCoeff[i][j],
+ (unsigned short)(wMantSize + 2),pCoeff,pos);
+ } else {
+ ovl_set_coeff_reg(&ddCoeff[i][j],
+ (unsigned short)wMantSize,pCoeff,pos);
+ }
+ }
+
+ wTapAdjust[0] = (wTaps - 1)/2;
+ for (j = 1, j1 = 1; j <= wTapAdjust[0]; j++, j1++) {
+ wTapAdjust[j1] = wTapAdjust[0] - j;
+ wTapAdjust[++j1] = wTapAdjust[0] + j;
+ }
+
+ /* adjust the coefficient */
+ sum = 0;
+ for (j = 0; j < wTaps; j++) {
+ sum += ddCoeff[i][j]; /*sum is now 16 bit fp to it*/
+ }
+
+ if (sum != (1 << 16)) {
+ /* if sum != 1.0 */
+ for (j1 = 0; j1 < wTaps; j1++) {
+ wTap2Fix = wTapAdjust[j1];
+ dDiff = (1 << 16) - sum; /*dDiff is also 16 bit FP to it*/
+ ddCoeff[i][wTap2Fix] += dDiff;
+ pos = wTap2Fix + i * wTaps;
+ if ( (wTap2Fix == (wTaps - 1)/2) && (!bVandC) ) {
+ ovl_set_coeff_reg(&ddCoeff[i][wTap2Fix],
+ (unsigned short)(wMantSize + 2),pCoeff,pos);
+ } else {
+ ovl_set_coeff_reg(&ddCoeff[i][wTap2Fix],
+ (unsigned short)wMantSize,pCoeff,pos);
+ }
+ sum = 0;
+ for (j = 0; j < wTaps; j++) {
+ sum += ddCoeff[i][j]; /*sum is now 16 bit FP to it*/
+ }
+ if (sum == (1 << 16 )) {
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
new file mode 100644
index 0000000..60cadb7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
@@ -0,0 +1,45 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_coeff.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVL_COEFF_H
+#define _OVL_COEFF_H
+
+extern void ovl_update_coeff_regs(
+ unsigned short wTaps,
+ int fpint_cutoff,
+ unsigned short bHor,
+ unsigned short bY,
+ unsigned short * pCoeff);
+
+#endif /* _OVL_COEFF_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
new file mode 100644
index 0000000..4487071
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
@@ -0,0 +1,57 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_dispatch.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVERLAY_DISPATCH_H
+#define _OVERLAY_DISPATCH_H
+
+typedef struct _ovl_dispatch {
+ int (*blend_surf_needed)(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags,
+ igd_surface_t *blend_surf,
+ igd_rect_t *blend_rect);
+ int (*alter_ovl)(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+ int (*query_ovl)(igd_display_h display_h,
+ unsigned int flags);
+ int (*query_max_size_ovl)(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+} ovl_dispatch_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
new file mode 100644
index 0000000..daadbe6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
@@ -0,0 +1,107 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_virt.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVL_VIRT_H
+#define _OVL_VIRT_H
+
+/* None of the IALs use the OVL_SUPPORT_*. Exclude it for now. */
+/* None of the IALs use the OVL_RULE_MUST_*. Exclude it for now. */
+
+/* Overlay HW range of values for color control and gamma correction*/
+#define OVL_HW_DEF_BRIGHT 750L
+#define OVL_HW_MIN_BRIGHT 0L
+#define OVL_HW_MAX_BRIGHT 10000L
+
+#define OVL_HW_DEF_CONT 10000L
+#define OVL_HW_MIN_CONT 0L
+#define OVL_HW_MAX_CONT 20000L
+
+#define OVL_HW_DEF_SAT 10000L
+#define OVL_HW_MIN_SAT 0L
+#define OVL_HW_MAX_SAT 20000L
+
+#define OVL_HW_DEF_HUE 0L
+#define OVL_HW_MIN_HUE -180L
+#define OVL_MHW_AX_HUE 180L
+
+#define OVL_HW_DEF_GAMMA 1L
+#define OVL_HW_MAX_GAMMA 500L
+#define OVL_HW_MIN_GAMMA 1L
+
+#define OVL_REPROG_OP_NONE 0
+#define OVL_REPROG_OP_TURNON_PRIM 1
+#define OVL_REPROG_OP_TURNON_SECND 2
+#define OVL_REPROG_OP_TURNOFF_PRIM 3
+#define OVL_REPROG_OP_TURNOFF_SECND 4
+#define OVL_REPROG_OP_SWITCH_TO_PRIM 5
+#define OVL_REPROG_OP_SWITCH_TO_SECND 6
+#define OVL_REPROG_OP_REVERT_SECND 7
+#define OVL_REPROG_OP_REVERT_PRIM 8
+
+enum {
+ OVL_STATE_OFF = 0,
+ OVL_STATE_ON,
+};
+
+#define OVL_PRIMARY 0
+#define OVL_SECONDARY 1
+#define OVL_MAX_HW 2 /* Maximum number of overlays */
+
+/* Define the maximum number of blend surfaces which can be used */
+#define MAX_BLEND_SURF 3
+
+typedef struct _ovl_context{
+ ovl_dispatch_t (*dispatch)[]; /* Pointer to an array */
+ unsigned int state;
+ unsigned long reg_update_offset;
+ unsigned long reg_update_phys;
+ unsigned long sync;
+ unsigned long sync2;
+ unsigned int blend_surf_num[OVL_MAX_HW];
+ igd_surface_t blend_surf[OVL_MAX_HW][MAX_BLEND_SURF];
+ unsigned int ovl_buff;
+ unsigned int fb_blend_ovl;
+ unsigned short reg_allocated;
+ igd_surface_t *saved_src_surf;
+ igd_rect_t *saved_src_rect;
+ igd_rect_t *saved_dest_rect;
+ igd_ovl_info_t *saved_ovl_info;
+ unsigned int saved_flags;
+ igd_display_context_t * ovl_display_km[OVL_MAX_HW];
+ unsigned int ovl_display_swapped;
+} ovl_context_t;
+
+extern ovl_context_t ovl_context[];
+
+#endif /*_OVL_VIRT_H*/
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
new file mode 100644
index 0000000..c58e890
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
@@ -0,0 +1,1725 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_ovl_plb.c
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the second
+ * overlay with the bits to properly configure the overlay
+ * Also includes functions to execute the second overlay flip
+ * instruction, and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips second overlay
+ * capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <math_fix.h>
+#include <plb/cmd.h>
+#include "ovl_plb_cache.h"
+#include "ovl2_plb.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+
+extern unsigned long sprite_pixel_formats_plb[];
+
+extern unsigned int ovl2_check_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+int micro_alter_ovl2_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+#ifndef CONFIG_MICRO_OVERLAY
+#define OVL2_CHECK_PLB_RET(ret,a, b, c, d, e,f) ret = ovl2_check_plb(a ,b ,c ,d ,e ,f)
+#define QUERY_OVL2_PLB_RET(ret,a, b) ret = query_ovl2_plb(a, b)
+#else
+#define OVL2_CHECK_PLB_RET(ret,a, b, c, d, e,f) 0
+#define QUERY_OVL2_PLB_RET(ret,a, b) 0
+#endif
+
+ovl_dispatch_t ovl_micro_dispatch_plb[] = {
+ {
+ NULL,
+ micro_alter_ovl2_plb,
+ NULL,
+ NULL,
+ },
+};
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+unsigned int micro_spritec_update_src_plb(igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+ /* src surface */
+ spritec_regs_plb->start = src_surf->offset +
+ (src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp);
+
+ EMGD_WRITE32(src_surf->pitch,
+ MMIO(display) + 0x72188);
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ spritec_regs_plb->control |= OVL2_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ spritec_regs_plb->control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+ break;
+ case IGD_PF_ARGB32_8888:
+ spritec_regs_plb->control |= OVL2_CMD_ARGB_8888;
+ break;
+ case IGD_PF_xRGB32_8888:
+ spritec_regs_plb->control |= OVL2_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ spritec_regs_plb->control |= OVL2_CMD_RGB_565;
+ break;
+ case IGD_PF_xRGB16_555:
+ case IGD_PF_ARGB16_1555:
+ spritec_regs_plb->control |= OVL2_CMD_RGB_555;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ spritec_regs_plb->control |= OVL2_CMD_RGB_8;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ spritec_regs_plb->control |= (1<<19);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: spritec_update_video_quality_plb()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+
+ EMGD_WRITE32(OVL2_RGB_COLOR_DEF_CONT_BRGHT,
+ MMIO(display) + 0x721D0);
+ EMGD_WRITE32(OVL2_RGB_COLOR_DEF_SATN_HUE,
+ MMIO(display) + 0x721D4);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xFFFFFF00) |
+ (calc_brightness & 0xFF),
+ MMIO(display) + 0x721D0);
+
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xF803FFFF) |
+ ((calc_contrast & 0x1FF) << 18),
+ MMIO(display) + 0x721D0);
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D4) & 0xFFFFFC00) |
+ (calc_saturation & 0x3FF),
+ MMIO(display) + 0x721D4);
+
+
+ /*************************************************************************
+ * Hue
+ *************************************************************************/
+ /* Hue is always set to the default value. It is based on the saturation
+ * value, and having a separate hue is of minimal value. */
+ EMGD_WRITE32(EMGD_READ32(MMIO(display) + 0x721D4) & 0xF800FFFF,
+ MMIO(display) + 0x721D4);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_plb()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ igd_ovl_gamma_info_t * ovl_gamma)
+{
+ const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+ const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+ OVL2_REG_ADDR_GAMMA0,
+ OVL2_REG_ADDR_GAMMA1,
+ OVL2_REG_ADDR_GAMMA2,
+ OVL2_REG_ADDR_GAMMA3,
+ OVL2_REG_ADDR_GAMMA4,
+ OVL2_REG_ADDR_GAMMA5
+ };
+ const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+ };
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled or the display is an 8 bit mode
+ * (second overay can not support gamma in an 8 bit mode),
+ * set it to the default */
+ if (((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) ||
+ (PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* turn overlay off (TBD) */
+
+ /* program register */
+ EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+ /* turn overlay on (TBD) */
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#endif // End if caching is not enabled.
+
+static unsigned int convert_color_key_to_hw (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ case IGD_PF_ARGB8_INDEXED:
+ default:
+ output = input;
+ break;
+ case IGD_PF_RGB16_565:
+ output =
+ ((((input & 0xf800)>>11)<<3)<<16) |
+ ((((input & 0x07e0)>>5 )<<2)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ case IGD_PF_ARGB16_1555:
+ output =
+ ((((input & 0x7c00)>>10)<<3)<<16) |
+ ((((input & 0x03e0)>>5 )<<3)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ }
+
+ return output;
+}
+static unsigned int convert_color_key_to_mask (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ default:
+ output = 0x00ffffff;
+ break;
+ case IGD_PF_RGB16_565:
+ output = 0x00f8fcf8;
+ break;
+ case IGD_PF_ARGB16_1555:
+ output = 0x00f8f8f8;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ output = 0x000000ff;
+ break;
+ }
+
+ return output;
+}
+
+/* Convert YUV to UVY for YUV pixel formats.
+ * Do not convert RGB pixel formats */
+static unsigned int yuv_to_uvy(
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ if (IGD_PF_TYPE(pf) & PF_TYPE_YUV) {
+ output =
+ ((input & 0x00ff0000) >> 16) |
+ ((input & 0x0000ff00) << 8) |
+ ((input & 0x000000ff) << 8);
+ } else {
+ output = input;
+ }
+
+ return output;
+}
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+
+static unsigned int micro_spritec_update_regs_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ unsigned int plane_control, plane_start;
+ unsigned int pipe_num;
+ unsigned int ckey_low, ckey_high;
+ int ret;
+
+
+ EMGD_TRACE_ENTER;
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ /* Turn off the plane control key enable and the second overlay
+ * control. */
+ plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ if ((plane_control & (3<<22)) != 0) {
+ plane_control &= ~(3<<22);
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 4);
+ }
+
+ /* Turn the overlay Off.
+ * Ensure we are using the correct Pipe. */
+ pipe_num = PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(pipe_num, MMIO(display) + 0x72180);
+ EMGD_WRITE32(0, MMIO(display) + 0x72184);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /***********************************************************************
+ * Copy the information passed in to the HW overlay structure
+ **********************************************************************/
+ /* Zero the control, since they will be OR'ed in with data
+ * below */
+ spritec_regs_plb->control = 0;
+
+ /* Interleaved/progressive and Odd/Even if interleaved */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ EMGD_ERROR("Overlay2 does not support Interleaved");
+ }
+
+ /* Dest rect information */
+ EMGD_WRITE32((dest_rect->y1<<16) | (dest_rect->x1),
+ MMIO(display) + 0x7218C);
+ EMGD_WRITE32(((dest_rect->y2 - dest_rect->y1 - 1)<<16) |
+ (dest_rect->x2 - dest_rect->x1 - 1),
+ MMIO(display) + 0x72190);
+
+ /* Src rect and surface information */
+ ret = micro_spritec_update_src_plb(display, spritec_regs_plb, src_surf, src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ return ret;
+ }
+
+ /* Color control information */
+ if (!(flags & IGD_OVL_OSD_ON_SPRITEC)) {
+ ret = micro_spritec_update_video_quality_plb(display, src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 video quality failed");
+ return ret;
+ }
+ ret = micro_spritec_update_gamma_plb(display, spritec_regs_plb, &ovl_info->gamma);
+ if (ret) {
+ EMGD_ERROR("Overlay2 gamma failed");
+ return ret;
+ }
+ }
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the different
+ * pixel formats */
+ EMGD_WRITE32(convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest),
+ MMIO(display) + PLANE(display)->plane_reg + 0x14);
+ EMGD_WRITE32(convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest),
+ MMIO(display) + PLANE(display)->plane_reg + 0x18);
+
+ /* Both the plane control key enable and the second overlay
+ * control order must be enabled to turn on destination color
+ * key. Also rewrite the plane_start which is the trigger for
+ * Plane A/B */
+ plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ if ((plane_control & (3<<22)) != (3<<22)) {
+ plane_control |= (3<<22);
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 4);
+
+ /* Note: On a 915GM (maybe other platforms as well), the dest
+ * color key is not always enabled when the plane A/B and
+ * plane C are both modified in the same vblank. So, ensure
+ * they occur on a different vblank. This should be fine,
+ * since this will only occur the first time when enabling
+ * the dest color key. */
+ display->context->dispatch.wait_vblank((igd_display_h)display);
+ }
+
+ if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+ /* Sprite C should be below plane and above overlay. */
+ spritec_regs_plb->control |= 1;
+ } else {
+ /* Sprite C should be on the bottom of the Z order.
+ * Plane B should be above Sprite C */
+ spritec_regs_plb->control |= 6;
+ }
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ if ((plane_control & (3<<22)) != 0) {
+ plane_control &= ~(3<<22);
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 4);
+ }
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+
+ ckey_high = convert_color_key_to_hw(src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ckey_high = yuv_to_uvy(src_surf->pixel_format,
+ ckey_high);
+
+ ckey_low = convert_color_key_to_hw(src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ckey_low = yuv_to_uvy(src_surf->pixel_format,
+ ckey_low);
+
+ EMGD_WRITE32(ckey_low, MMIO(display) + 0x72194);
+ EMGD_WRITE32(ckey_high, MMIO(display) + 0x721a0);
+ EMGD_WRITE32(7, MMIO(display) + 0x72198);
+ spritec_regs_plb->control |= (1<<22);
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ EMGD_WRITE32(0, MMIO(display) + 0x72198);
+ }
+
+ /* General overlay information. Turn the second overlay on.
+ * The trigger register is the start register which causes the
+ * overlay to update. The trigger register is written in send_instr */
+ spritec_regs_plb->control |= (1<<31);
+ spritec_regs_plb->control |= PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(spritec_regs_plb->control, MMIO(display) + 0x72180);
+ /*EMGD_WRITE32(ovl2_regs_plb->start, MMIO(display) + 0x72184);*/
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#else /* OVL_PLB_CACHE_QUICK_SWAP is enabled. */
+
+/* Poulsbo overlay cache structure */
+static ovl_plb_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_ptr_plb()
+ *
+ * Description:
+ * This function updates the source offset
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_ptr_plb(igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format) / 8;
+
+ /* src surface */
+ ovl_cache.ovl2_regs.start =
+ src_surf->offset +
+ (src_rect->y1 * src_surf->pitch) +
+ (src_rect->x1 * src_Bpp);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_plb()
+ *
+ * Description:
+ * This function updates the source pitch and pixel format
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_plb(igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ EMGD_TRACE_ENTER;
+
+ ovl_cache.ovl2_regs.pitch = src_surf->pitch;
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+ break;
+ case IGD_PF_ARGB32_8888:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_ARGB_8888;
+ break;
+ case IGD_PF_xRGB32_8888:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_565;
+ break;
+ case IGD_PF_xRGB16_555:
+ case IGD_PF_ARGB16_1555:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_555;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ ovl_cache.ovl2_regs.control |= (1<<19);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_video_quality_plb()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_plb(
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+
+ ovl_cache.ovl2_regs.cont_bright = OVL2_RGB_COLOR_DEF_CONT_BRGHT;
+ ovl_cache.ovl2_regs.satn_hue = OVL2_RGB_COLOR_DEF_SATN_HUE;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ ovl_cache.ovl2_regs.cont_bright =
+ (ovl_cache.ovl2_regs.cont_bright & 0xFFFFFF00) |
+ (calc_brightness & 0xFF);
+
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ ovl_cache.ovl2_regs.cont_bright =
+ (ovl_cache.ovl2_regs.cont_bright & 0xF803FFFF ) |
+ ((calc_contrast & 0x1FF) << 18);
+
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ ovl_cache.ovl2_regs.satn_hue =
+ (ovl_cache.ovl2_regs.satn_hue & 0xFFFFFC00 ) |
+ (calc_saturation & 0x3FF);
+
+ /*************************************************************************
+ * Hue
+ *************************************************************************/
+ /* Hue is always set to the default value. It is based on the saturation
+ * value, and having a separate hue is of minimal value. */
+ ovl_cache.ovl2_regs.satn_hue =
+ (ovl_cache.ovl2_regs.satn_hue & 0xF800FFFF);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+static const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+static const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+ OVL2_REG_ADDR_GAMMA0,
+ OVL2_REG_ADDR_GAMMA1,
+ OVL2_REG_ADDR_GAMMA2,
+ OVL2_REG_ADDR_GAMMA3,
+ OVL2_REG_ADDR_GAMMA4,
+ OVL2_REG_ADDR_GAMMA5
+};
+static const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+};
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_plb()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_plb(
+ igd_display_context_t *display,
+ igd_ovl_gamma_info_t *ovl_gamma)
+{
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled or the display is an 8 bit mode
+ * (second overay can not support gamma in an 8 bit mode),
+ * set it to the default */
+ if (((ovl_gamma->flags&IGD_OVL_GAMMA_ENABLE)==IGD_OVL_GAMMA_DISABLE) ||
+ (PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ ovl_cache.ovl2_regs.gamma_regs[i] = gamma_def[i];
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* program register */
+ ovl_cache.ovl2_regs.gamma_regs[i] = gamma_reg;
+
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_disable_ovl_plb()
+ *
+ * Description:
+ * Write the registers needed to turn off the overlay.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_disable_ovl_plb(
+ igd_display_context_t *display )
+{
+ unsigned int pipe_num;
+ unsigned int plane_control, plane_start;
+
+ /* Turn off the plane control key enable and the second overlay
+ * control. */
+ plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ if ((plane_control & (3<<22)) != 0) {
+ plane_control &= ~(3<<22);
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start =
+ EMGD_READ32(MMIO(display) +
+ PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 4);
+ }
+
+ /* Turn the overlay Off.
+ * Ensure we are using the correct Pipe. */
+ pipe_num = PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(pipe_num, MMIO(display) + 0x72180);
+ EMGD_WRITE32(0, MMIO(display) + 0x72184);
+
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_clear_cache_plb()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_clear_cache_plb(
+ igd_display_context_t *display,
+ unsigned int flags)
+{
+ /* Force every cache check to miss */
+ OS_MEMSET(&ovl_cache, 0, sizeof(ovl_plb_cache_t));
+
+ /* We just set our cached flags to 0, which might accidently
+ * match up with "OFF" for some important incoming flag
+ * bits, causing us to think we already handled them when
+ * we didn't. So set our cached flags to the exact
+ * opposite of the incoming flags, which will force
+ * us to test and handle every single bit, regardless
+ * of whether it is on or off. */
+ ovl_cache.flags = ~flags;
+
+ /* init our cached registers */
+ ovl_cache.ovl2_regs.plane_control =
+ EMGD_READ32(MMIO(display) +
+ PLANE(display)->plane_reg);
+ ovl_cache.ovl2_regs.plane_start =
+ EMGD_READ32(MMIO(display) +
+ PLANE(display)->plane_reg + 4);
+
+ /* initialization complete */
+ ovl_cache_needs_init = FALSE;
+
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_colorkey_plb()
+ *
+ * Description:
+ * This function sets the colorkey values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static void micro_spritec_update_colorkey_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_ovl_info_t *ovl_info)
+{
+ unsigned int ckey_low, ckey_high;
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the
+ * different pixel formats */
+ ovl_cache.ovl2_regs.colorkey_hw =
+ convert_color_key_to_hw
+ (PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+
+ ovl_cache.ovl2_regs.colorkey_mask =
+ convert_color_key_to_mask
+ (PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ /*
+ * Both the plane control key enable and the second
+ * overlay control order must be enabled to turn on
+ * destination color key. Also rewrite the
+ * plane_start which is the trigger for Plane A/B
+ */
+ if ( (ovl_cache.ovl2_regs.plane_control & (3<<22)) !=
+ (3<<22)) {
+ ovl_cache.ovl2_regs.plane_control |= (3<<22);
+ }
+
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ if ((ovl_cache.ovl2_regs.plane_control & (3<<22)) != 0) {
+ ovl_cache.ovl2_regs.plane_control &= ~(3<<22);
+ }
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+
+ ckey_high = convert_color_key_to_hw
+ (src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ckey_high = yuv_to_uvy(src_surf->pixel_format,
+ ckey_high);
+
+ ckey_low = convert_color_key_to_hw
+ (src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ckey_low = yuv_to_uvy(src_surf->pixel_format,
+ ckey_low);
+
+ ovl_cache.ovl2_regs.ckey_low = ckey_low;
+ ovl_cache.ovl2_regs.ckey_high = ckey_high;
+ ovl_cache.ovl2_regs.ckey_enable = 7;
+ ovl_cache.ovl2_regs.control |= (1<<22);
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ ovl_cache.ovl2_regs.ckey_enable = 0;
+ }
+
+}
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_write_cache_plb()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_write_cache_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ igd_ovl_info_t *ovl_info,
+ int cache_changed)
+{
+ int i;
+
+ /*
+ * Now write all the changed registers to the HW
+ * TODO: Or should we write all the registers, regardless of
+ * if they have changed?
+ * TODO: It may be beneficial to turn off overlay while
+ * updateing the regs?
+ */
+
+ /* Write source information */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+ IGD_OVL_PLB_UPDATE_SRC ) ) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.pitch,
+ MMIO(display) + MMIO_OFFSET_PLB2_PITCH);
+ }
+
+ /* Write dest rect information */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+ EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_x1y1,
+ MMIO(display) + MMIO_OFFSET_PLB2_DEST_RECT_X1Y1);
+ EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_x2y2,
+ MMIO(display) + MMIO_OFFSET_PLB2_DEST_RECT_X2Y2);
+ }
+
+ /* write the quality information */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ |
+ IGD_OVL_PLB_UPDATE_SURF ) ) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.cont_bright,
+ MMIO(display) + MMIO_OFFSET_PLB2_CONT_BRIGHT);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.satn_hue,
+ MMIO(display) + MMIO_OFFSET_PLB2_SATN_HUE);
+ }
+
+ /* Write the gamma */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(ovl_cache.ovl2_regs.gamma_regs[i],
+ MMIO(display) + gamma_reg_offset[i]);
+ }
+ }
+
+ /* Write the colorkey data */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+
+ /* Dest color key */
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+ /* Write the regs needed to turn it on */
+ EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_hw,
+ MMIO(display) +
+ PLANE(display)->plane_reg +
+ MMIO_OFFSET_PLB2_COLORKEY_HW);
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_mask,
+ MMIO(display) +
+ PLANE(display)->plane_reg +
+ MMIO_OFFSET_PLB2_COLORKEY_MASK);
+ }
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.plane_start,
+ MMIO(display) + PLANE(display)->plane_reg+4);
+
+ /*
+ * Note: On a 915GM (maybe other platforms as well),
+ * the dest color key is not always enabled when the
+ * plane A/B and plane C are both modified in the
+ * same vblank. So, ensure they occur on a different
+ * vblank. This should be fine, since this will only
+ * occur the first time when enabling the dest color
+ * key.
+ */
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ display->context->dispatch.
+ wait_vblank((igd_display_h)display);
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_low,
+ MMIO(display) + MMIO_OFFSET_PLB2_CKEY_LOW);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_high,
+ MMIO(display) + MMIO_OFFSET_PLB2_CKEY_HIGH);
+ }
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_enable,
+ MMIO(display) + MMIO_OFFSET_PLB2_CKEY_ENABLE);
+ }
+
+ /* Write the control register, but not the start register.
+ The trigger register is the start register
+ which causes the overlay to update. The trigger
+ register is written in send_instr */
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.control,
+ MMIO(display) + MMIO_OFFSET_PLB2_CONTROL);
+
+ spritec_regs_plb->start = ovl_cache.ovl2_regs.start;
+ spritec_regs_plb->control = ovl_cache.ovl2_regs.control;
+
+}
+
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_regs_plb()
+ *
+ * Description:
+ * Examine the incoming overlay parameters, and update the overlay hardware
+ * regs according to what changed.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_update_regs_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ // unsigned int ckey_low, ckey_high;
+ // int i,
+ int ret;
+ int cache_changed;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Fast path for turning off overlay. No need for cache */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ ret = micro_spritec_disable_ovl_plb(display);
+
+ /* Reset the cache */
+ ovl_cache_needs_init = TRUE;
+
+ return ret;
+ }
+
+ /* Init the cache if needed */
+ if (ovl_cache_needs_init) {
+ micro_spritec_clear_cache_plb(display, flags);
+ }
+
+ /* See what has changed in the cache */
+ cache_changed = get_cache_changes_plb (src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags,
+ &ovl_cache);
+
+ /*
+ * Perhaps the biggest challenge of caching the overlay
+ * state is what to do with the command and config regs.
+ * Normally we would clear command and config to 0 here,
+ * and let the update process set only the bits that are
+ * needed. But doing this would invalidate our cache.
+ * Instead we are relying on the above call to
+ * get_cache_changes() to clear those bits in command
+ * and config that will be changing */
+
+
+ /* Normally we would set interleave parameters here,
+ * but the secondary overlay does not support interleave.*/
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ EMGD_ERROR("Overlay2 does not support Interleaved");
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Has our destination rectangle changed? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+
+ ovl_cache.ovl2_regs.dest_rect_x1y1 =
+ ( (dest_rect->y1 << 16) | dest_rect->x1 );
+ ovl_cache.ovl2_regs.dest_rect_x2y2 =
+ ( (dest_rect->y2 - dest_rect->y1 - 1) << 16) |
+ (dest_rect->x2 - dest_rect->x1 - 1) ;
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Always update the source pointers every frame. */
+ ret = micro_spritec_update_src_ptr_plb(src_surf,
+ src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ return ret;
+ }
+
+
+ /* ----------------------------------------------------------*/
+ /* Did either the Src rect or surface change? */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+ IGD_OVL_PLB_UPDATE_SRC ) ) {
+ ret = micro_spritec_update_src_plb(src_surf,
+ src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ return ret;
+ }
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the quality information change? */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ |
+ IGD_OVL_PLB_UPDATE_SURF ) ) {
+ ret = micro_spritec_update_video_quality_plb
+ (src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 video quality failed");
+ return ret;
+ }
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the gamma change? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+ ret = micro_spritec_update_gamma_plb(display, &ovl_info->gamma);
+ if (ret) {
+ EMGD_ERROR("Overlay2 gamma failed");
+ return ret;
+ }
+
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the color key change? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+ micro_spritec_update_colorkey_plb(display,
+ src_surf,
+ ovl_info);
+ }
+
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+ ovl_cache.ovl2_regs.control |= 1;
+ } else {
+ /* Sprite C should be on the bottom of the Z order.
+ * Plane B should be above Sprite C */
+ ovl_cache.ovl2_regs.control |= 6;
+ }
+ }
+
+ /* General overlay information. Turn the second overlay on. */
+ ovl_cache.ovl2_regs.control |= (1<<31);
+ ovl_cache.ovl2_regs.control |= PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+
+ /*
+ * Now write all the changes to the part
+ */
+ micro_spritec_write_cache_plb(display,
+ spritec_regs_plb,
+ ovl_info,
+ cache_changed);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#endif
+
+
+
+unsigned int micro_spritec_send_instr_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ unsigned int flags)
+{
+ EMGD_TRACE_ENTER;
+
+ /* Send a load register instruction to write the Plane C sprite address
+ * which is the trigger register.
+ * This is an instruction, so it happens after blend, and since it
+ * is an instruction, we do not have to poll waiting for it. */
+
+#ifdef OVL_PLB_CACHE_QUICK_SWAP /* If caching is enabled */
+ EMGD_WRITE32(ovl_cache.ovl2_regs.start, MMIO(display) +
+ MMIO_OFFSET_PLB2_START);
+
+#else
+ EMGD_WRITE32(spritec_regs_plb->start, MMIO(display) + 0x72184);
+#endif
+
+ ovl_context->sync2 = 0;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int micro_prepare_ovl2_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ unsigned int flags)
+{
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Check to ensure the overlay can be used given the current mode as
+ * well as what the IAL is asking for. If not return an error. */
+
+ if( (OVL2_CHECK_PLB_RET(ret,display, src_surf, src_rect,
+ dest_rect, ovl_info,flags)) ) {
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 Check failed");
+ return ret;
+ }
+ }
+
+ /* Check if last flip is still pending.
+ * This is necessary for the following reasons:
+ * - If the previous instructions have not been processed, then the
+ * spritec_regs_plb is still in use and can not be overwritten.
+ */
+ if (PIPE(display)){
+ if( (QUERY_OVL2_PLB_RET(ret,(igd_display_h)display,
+ IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) ){
+ if ((FALSE == ret) &&
+ (flags & IGD_OVL_ALTER_ON)) {
+ /* Only return an error if the overlay is on. If turning it off,
+ * allow it to continue, since something may have failed and we
+ * should try our best to turn the overlay off. */
+ return -IGD_ERROR_HWERROR;
+ }
+ }
+ }
+
+ /* Update all Overlay Update Registers */
+ ret = micro_spritec_update_regs_plb(display, spritec_regs_plb,
+ src_surf, src_rect, dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Sprite C update Registers failed");
+ return ret;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+int micro_alter_ovl2_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl2_reg_plb_t spritec_regs_plb;
+ int ret=0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Dump overlay parameters for debugging */
+ /*
+ if (src_surf && src_rect && dest_rect && ovl_info) {
+ printk (KERN_ERR " micro_alter_ovl2_plb Entry."
+ "offset=0x%X "
+ "pitch=%d "
+ "width=%d "
+ "height=%d \n"
+ "pixel_format=0x%X "
+ "flags=0x%X "
+ "virt_addr=0x%X "
+ "pvr2d_mem_info=0x%X "
+ "pvr2d_context_h=0x%X "
+ "hPVR2DFlipChain=0x%X \n"
+ "src_x1=%d "
+ "src_x2=%d "
+ "src_y1=%d "
+ "src_y2=%d "
+ "src width=%d "
+ "src height=%d \n"
+ "dest_x1=%d "
+ "dest_x2=%d "
+ "dest_y1=%d "
+ "dest_y2=%d "
+ "dest width=%d "
+ "dest height=%d \n"
+ "color_key.src_lo=0x%X "
+ "color_key.src_hi=0x%X "
+ "color_key.dest=0x%X "
+ "color_key.flags=0x%X "
+ "flags=0x%X "
+ ,
+ (unsigned int) src_surf->offset ,
+ (unsigned int) src_surf->pitch ,
+ (unsigned int) src_surf->width ,
+ (unsigned int) src_surf->height ,
+ (unsigned int) src_surf->pixel_format ,
+ (unsigned int) src_surf->flags ,
+ (unsigned int) src_surf->virt_addr ,
+ (unsigned int) src_surf->pvr2d_mem_info ,
+ (unsigned int) src_surf->pvr2d_context_h ,
+ (unsigned int) src_surf->hPVR2DFlipChain ,
+ (unsigned int) src_rect->x1,
+ (unsigned int) src_rect->x2,
+ (unsigned int) src_rect->y1,
+ (unsigned int) src_rect->y2,
+ (unsigned int) (src_rect->x2 - src_rect->x1),
+ (unsigned int) (src_rect->y2 - src_rect->y1),
+ (unsigned int) dest_rect->x1,
+ (unsigned int) dest_rect->x2,
+ (unsigned int) dest_rect->y1,
+ (unsigned int) dest_rect->y2,
+ (unsigned int) (dest_rect->x2 - dest_rect->x1),
+ (unsigned int) (dest_rect->y2 - dest_rect->y1),
+ (unsigned int) ovl_info->color_key.src_lo,
+ (unsigned int) ovl_info->color_key.src_hi,
+ (unsigned int) ovl_info->color_key.dest,
+ (unsigned int) ovl_info->color_key.flags,
+ (unsigned int) flags
+ );
+ }
+ */
+ /* Initialize structure so compilers don't complain */
+ OS_MEMSET(&spritec_regs_plb, 0, sizeof(ovl2_reg_plb_t));
+
+ if (micro_prepare_ovl2_plb(display, src_surf, src_rect, dest_rect,
+ ovl_info, &spritec_regs_plb, flags)) {
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Directlt write the register to update 2nd overlay */
+ ret = micro_spritec_send_instr_plb(display, &spritec_regs_plb, flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
new file mode 100644
index 0000000..816c3ab
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
@@ -0,0 +1,542 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_plb.c
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the second
+ * overlay with the bits to properly configure the overlay
+ * Also includes functions to execute the second overlay flip
+ * instruction, and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips second overlay
+ * capabilities
+ *-----------------------------------------------------------------------------
+ */
+/* Referenced from Napa. Need change later */
+
+#define MODULE_NAME hal.overlay
+
+#include "ovl_plb_cache.h"
+#include <plb/regs.h>
+#include <plb/cmd.h>
+#include <plb/context.h>
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+#include "ovl2_regs_plb.h"
+
+extern unsigned long sprite_pixel_formats_plb[];
+extern int micro_prepare_ovl2_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ unsigned int flags);
+
+/*----------------------------------------------------------------------
+ * Function: ovl2_check_pf_plb()
+ * Parameters: unsigned int requested_pixel_format -
+ * according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ * TRUE on Success
+ * FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl2_check_pf_plb(
+ igd_display_context_t *display,
+ unsigned int requested_pixel_format)
+{
+ unsigned long *spr_pf = sprite_pixel_formats_plb;
+ int temp_loop = 0;
+
+ while(spr_pf[temp_loop]) {
+ if(spr_pf[temp_loop] == requested_pixel_format) {
+ return TRUE;
+ }
+ ++temp_loop;
+ }
+
+ return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+unsigned int ovl2_check_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_timing_info_t *timing;
+ unsigned int min_w, min_h;
+
+ EMGD_TRACE_ENTER;
+
+ if (!display){
+ EMGD_ERROR_EXIT("display is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!PIPE(display)){
+ EMGD_ERROR_EXIT("PIPE(display) is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ timing = PIPE(display)->timing;
+
+ if(!timing) {
+ EMGD_ERROR_EXIT("timing is null\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* The following parameters are only valid if the overlay is on, so
+ * return success if the overlay is being turned off. */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Ensure the framebuffer dotclock does not exceed the board SKU
+ * max dotclock
+ **************************************************************************/
+ /* Make it chipset-specific */
+ /* DCT-PC99TA crashes with dotclock > 300MHz */
+ if(timing->dclk >= 340000){
+ EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the overlay surface is ok and can be properly displayed.
+ * This ensures the following is valid:
+ * - Ensure x1, x2, y1, y2 are pixel aligned
+ * - 2 pixels or greater in width and height
+ * - Pixel format is supported by the overlay
+ * - Pitch is <= 8KB
+ * - Based on the pixel format, the width is supported
+ *************************************************************************/
+ if (!src_surf){
+ EMGD_ERROR_EXIT("src_surf is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!src_rect){
+ EMGD_ERROR_EXIT("src_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ /* Get the minimum size of 1 pixel in width and height for y, u, and v.
+ */
+ min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+ min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+ if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+ ((src_rect->y2 - src_rect->y1) < min_h*2)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 source width or height is < 2 pixels (%dx%d)\n",
+ src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (FALSE == ovl2_check_pf_plb(display, src_surf->pixel_format)) {
+ EMGD_ERROR_EXIT("Overlay2 source pixel format unsupported (pf:0x%lx)",
+ src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ if (src_surf->pitch > 8192) {
+ EMGD_ERROR_EXIT("Overlay2 source pitch (%d) > 8KB",
+ src_surf->pitch);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the location on the framebuffer is ok and can be properly
+ * displayed
+ * This ensures the following is valid:
+ * - Greater than 1 pixel width and height
+ * - Will be displayed on screen (not panned off)
+ *************************************************************************/
+ if (!dest_rect){
+ EMGD_ERROR_EXIT("dest_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+ ((dest_rect->y2 - dest_rect->y1) <= 1)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 dest width or height is single pixel (%dx%d)\n",
+ dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((dest_rect->x1 >= timing->width) ||
+ (dest_rect->y1 >= timing->height)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 dest is panned off the screen (%d,%d)\n",
+ dest_rect->x1, dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+unsigned int ovl2_send_instr_plb(
+ igd_display_context_t *display,
+ ovl2_reg_plb_t *spritec_regs_plb,
+ unsigned int flags)
+{
+ unsigned char * mmio = MMIO(display);
+ unsigned long tmp;
+ inter_module_dispatch_t *md;
+ platform_context_plb_t * platform;
+ unsigned int pipe_num;
+ unsigned long pipe_reg;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* We dont need the CMD_WAIT_OVL2_PLB instruction coz
+ * our alter_ovl code already querried status
+ * for last flip completion before getting here. See
+ * micro_prepare_ovl2_plb called by alter_ovl2_plb.
+ * It calls query overlay before the next flip
+ */
+
+
+ /*
+ * If Overlay + FB Blend is requested and the FB is xRGB
+ * turn on the ARGB format.
+ */
+ if(ovl_context->fb_blend_ovl) {
+ if ((flags & IGD_OVL_ALTER_ON) != IGD_OVL_ALTER_ON) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x1c000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+ OS_SLEEP(100);
+ }
+ } else {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x18000000) {
+ EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+ }
+ }
+ }
+
+
+ /* Send a load register instruction to write the Plane C sprite address
+ * which is the trigger register.
+ * This is an instruction, so it happens after blend, and since it
+ * is an instruction, we do not have to poll waiting for it. */
+ EMGD_WRITE32(spritec_regs_plb->start, mmio + 0x72184);
+
+ md = &display->context->mod_dispatch;
+ platform = (platform_context_plb_t *)display->context->
+ platform_context;
+
+ pipe_num = PIPE(display)->pipe_num;
+
+ if(pipe_num){
+ pipe_reg = 0x71024;
+ } else {
+ pipe_reg = 0x70024;
+ }
+
+ if(md && md->set_flip_pending){
+ /* For second overlay, Poulsbo has no ISR bit
+ * to reflect the flip pending for Display
+ * Sprite C. So we use Pipe-B vblank status
+ * as a substitute
+ */
+ ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+ md->set_flip_pending(MMIO(display), pipe_reg);
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ }
+
+ ovl_context->sync2 = 0;
+
+ display->context->dispatch.sync(display,
+ IGD_PRIORITY_NORMAL,
+ &ovl_context->sync2,
+ IGD_SYNC_NONBLOCK);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int alter_ovl2_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl2_reg_plb_t spritec_regs_plb;
+ int ret=0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Dump overlay parameters for debugging */
+ /*
+ if (src_surf && src_rect && dest_rect && ovl_info) {
+ printk (KERN_ERR " alter_ovl2_plb Entry."
+ "offset=0x%X "
+ "pitch=%d "
+ "width=%d "
+ "height=%d \n"
+ "pixel_format=0x%X "
+ "flags=0x%X "
+ "virt_addr=0x%X "
+ "pvr2d_mem_info=0x%X "
+ "pvr2d_context_h=0x%X "
+ "hPVR2DFlipChain=0x%X \n"
+ "src_x1=%d "
+ "src_x2=%d "
+ "src_y1=%d "
+ "src_y2=%d "
+ "src width=%d "
+ "src height=%d \n"
+ "dest_x1=%d "
+ "dest_x2=%d "
+ "dest_y1=%d "
+ "dest_y2=%d "
+ "dest width=%d "
+ "dest height=%d \n"
+ "color_key.src_lo=0x%X "
+ "color_key.src_hi=0x%X "
+ "color_key.dest=0x%X "
+ "color_key.flags=0x%X "
+ "flags=0x%X "
+ ,
+ (unsigned int) src_surf->offset ,
+ (unsigned int) src_surf->pitch ,
+ (unsigned int) src_surf->width ,
+ (unsigned int) src_surf->height ,
+ (unsigned int) src_surf->pixel_format ,
+ (unsigned int) src_surf->flags ,
+ (unsigned int) src_surf->virt_addr ,
+ (unsigned int) src_surf->pvr2d_mem_info ,
+ (unsigned int) src_surf->pvr2d_context_h ,
+ (unsigned int) src_surf->hPVR2DFlipChain ,
+ (unsigned int) src_rect->x1,
+ (unsigned int) src_rect->x2,
+ (unsigned int) src_rect->y1,
+ (unsigned int) src_rect->y2,
+ (unsigned int) (src_rect->x2 - src_rect->x1),
+ (unsigned int) (src_rect->y2 - src_rect->y1),
+ (unsigned int) dest_rect->x1,
+ (unsigned int) dest_rect->x2,
+ (unsigned int) dest_rect->y1,
+ (unsigned int) dest_rect->y2,
+ (unsigned int) (dest_rect->x2 - dest_rect->x1),
+ (unsigned int) (dest_rect->y2 - dest_rect->y1),
+ (unsigned int) ovl_info->color_key.src_lo,
+ (unsigned int) ovl_info->color_key.src_hi,
+ (unsigned int) ovl_info->color_key.dest,
+ (unsigned int) ovl_info->color_key.flags,
+ (unsigned int) flags
+ );
+ }
+ */
+ /* Initialize structure so compilers don't complain */
+ OS_MEMSET(&spritec_regs_plb, 0, sizeof(ovl2_reg_plb_t));
+
+ if (micro_prepare_ovl2_plb(display, src_surf, src_rect, dest_rect,
+ ovl_info, &spritec_regs_plb, flags)) {
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Send the instructions to the command queue */
+ ret = ovl2_send_instr_plb(display, &spritec_regs_plb, flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+int query_ovl2_plb(igd_display_h display_h,
+ unsigned int flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_h;
+ inter_module_dispatch_t *md;
+ platform_context_plb_t * platform;
+ os_alarm_t timeout;
+ int ret;
+ unsigned int pipe_num;
+ unsigned long pipe_reg;
+
+ EMGD_TRACE_ENTER;
+
+ switch (flags) {
+ case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+ /* This is the second overlay, so HW overlay is not supported */
+ break;
+
+ case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+ /* If there no sync to wait on, then the last flip is done, and the
+ * Register Update has occured, simply return TRUE (Flip done).
+ */
+ /*if (!ovl_context->sync2) {
+ EMGD_DEBUG("Overlay already synced");
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }*/
+
+ /* Wait for vblank */
+ /* Check to see if the plane C flip is pending. If is is pending
+ * return FALSE (Flip not done). */
+ /*if(display->context->dispatch.sync(
+ display,
+ IGD_PRIORITY_NORMAL,
+ &ovl_context->sync2,
+ IGD_SYNC_NONBLOCK)) {
+ EMGD_DEBUG("Overlay Sync Check - Flip not done");
+ return FALSE;
+ }*/
+ /* According to the PBL B-spec, there doesnt seem to exist any bit
+ * for Sprite C Flip-Pending status. Testing 0x20AC in code during
+ * virt queue's REG write shows nothing changed for Bit8. Thus, we
+ * are using state of the VBLANK ISR bit as ovl2 flip status.
+ * Assumption is that if were running 2nd overlay, its either clone
+ * display or VEXT in WinCE. In either case, were not doing full screen
+ * FB flipping, so this check should be 'statefully' accurate
+ */
+
+ if (PIPE(display)){
+ pipe_num = PIPE(display)->pipe_num;
+
+ if(pipe_num){
+ pipe_reg = 0x71024;
+ } else {
+ pipe_reg = 0x70024;
+ }
+
+ md = &display->context->mod_dispatch;
+ platform = (platform_context_plb_t *)display->context->
+ platform_context;
+ if(md && md->check_flip_pending){
+ ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+ if(md->check_flip_pending(MMIO(display), pipe_reg)){
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ EMGD_DEBUG("Overlay2 Sync done but Flip not done");
+ return FALSE;
+ }
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ }
+
+ } else {
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+ /* Now that we know the last flip is done and the register update is
+ * complete, set the sync to 0 and return TRUE (Flip done). */
+ ovl_context->sync2 = 0;
+ break;
+ case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+ /* Wait for 200 milliseconds for the last flip to complete. If not
+ * done in that time, there is likely a hardware problem so return
+ * FALSE. */
+ timeout = OS_SET_ALARM(200);
+ do {
+ if (TRUE ==
+ query_ovl2_plb(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+ } while (!OS_TEST_ALARM(timeout));
+ EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+ return FALSE;
+ break;
+ case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+ return TRUE;
+ break;
+ case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+ return TRUE;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+
+
+int query_max_size_ovl2_plb(
+ igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height)
+{
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: Should this be size of FB? */
+ *max_width = 2048;
+ *max_height = 2048;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
new file mode 100644
index 0000000..dca46bc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for napa overlay engine. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_PLB_H
+#define _OVL2_PLB_H
+extern int blend2_surf_needed_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags,
+ igd_surface_t *blend_surf,
+ igd_rect_t *blend_rect);
+extern int alter_ovl2_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+extern int query_ovl2_plb(igd_display_h display_h,
+ unsigned int flags);
+extern int query_max_size_ovl2_plb(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+#endif /* _OVL2_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
new file mode 100644
index 0000000..6460560
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_regs_plb.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for napa overlay engine. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_REGS_PLB_H
+#define _OVL2_REGS_PLB_H
+/* Second Overlay Structure.
+ * These registers are the trigger registers and should be written
+ * last. */
+typedef struct _ovl2_reg_plb{
+ unsigned int control;
+ unsigned int start;
+} ovl2_reg_plb_t;
+
+/* Color Correction */
+#define OVL2_RGB_COLOR_DEF_CONT_BRGHT 0x1000000
+#define OVL2_RGB_COLOR_DEF_SATN_HUE 0x0000080
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL2_CMD_YVYU 0x00020000
+#define OVL2_CMD_UYVY 0x00010000
+#define OVL2_CMD_VYUY 0x00030000
+
+/* Source Format */
+#define OVL2_CMD_ARGB_8888 0x1C000000
+#define OVL2_CMD_RGB_8888 0x18000000
+#define OVL2_CMD_RGB_565 0x14000000
+#define OVL2_CMD_RGB_555 0x10000000
+#define OVL2_CMD_RGB_8 0x08000000
+#define OVL2_CMD_YUV_422 0x00000000 /*packed YUV422*/
+#define OVL2_CMD_SRC_FMT_MASK 0x3C000000 /*mask for above*/
+
+#define OVL2_REG_ADDR_GAMMA5 0x721E0
+#define OVL2_REG_ADDR_GAMMA4 0x721E4
+#define OVL2_REG_ADDR_GAMMA3 0x721E8
+#define OVL2_REG_ADDR_GAMMA2 0x721EC
+#define OVL2_REG_ADDR_GAMMA1 0x721F0
+#define OVL2_REG_ADDR_GAMMA0 0x721F4
+#define OVL2_TOTAL_GAMMA_REG 6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+ than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV 0x43//4a
+#define MID_SATURATION_YUV 0x91//92
+#define MID_BRIGHTNESS_YUV -5
+#endif /* _OVL2_REGS_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
new file mode 100644
index 0000000..42d4a01
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
@@ -0,0 +1,2188 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_plb.c
+ * $Revision: 1.30 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the overlay
+ * register back buffer with the bits to properly configure
+ * the overlay
+ * Also includes functions to execute the overlay flip instruction,
+ * and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips overlay capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <math_fix.h>
+#include <plb/cmd.h>
+#include "ovl_plb_cache.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+#include "../cmn/ovl_coeff.h"
+#include "ovl2_plb.h"
+
+/*-----------------------------------------------------------------------------
+ * Common dispatch functions
+ *---------------------------------------------------------------------------*/
+static int alter_ovl_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+static int query_ovl_plb(igd_display_h display_h,
+ unsigned int flags);
+static int query_max_size_ovl_plb(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+
+
+ovl_dispatch_t ovl_dispatch_plb[] = {
+ /* Dispatch for the hardware overlay */
+ {
+ NULL, /*blend_surf_needed_plb,*/
+ alter_ovl_plb,
+ query_ovl_plb,
+ query_max_size_ovl_plb,
+ },
+ /* Dispatch for the software overlay */
+ {
+ NULL, /*blend2_surf_needed_plb,*/
+ alter_ovl2_plb,
+ query_ovl2_plb,
+ query_max_size_ovl2_plb,
+ },
+};
+
+
+typedef struct _ovl_chipset_plb {
+ unsigned int num_linebuf;
+ unsigned int pixel_format;
+ unsigned int max_width;
+ unsigned int max_height;
+} ovl_chipset_plb_t;
+
+static ovl_chipset_plb_t ovl_chipset_plb[] = {
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1280, 1080},
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1024, 1080},
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_32 | PF_TYPE_ARGB), 640, 1080},
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_32 | PF_TYPE_RGB), 640, 1080},
+
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1920, 1088},
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1920, 1088},
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_32 | PF_TYPE_ARGB), 960, 1080},
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_32 | PF_TYPE_RGB), 960, 1080},
+ {OVL_CONFIG_NO_LINE_BUFF, 0, 0, 0}
+};
+
+#ifdef DEBUG_BUILD_TYPE
+
+static void ovl_dump_regs_plb(
+ ovl_reg_image_plb_t *ovl_regs_plb)
+{
+ return;
+
+ printk (KERN_ERR "************************************************\n");
+ printk (KERN_ERR "OVERLAY REGISTER LISTING\n");
+
+ printk (KERN_ERR "OVL REGS AT = 0x%x \n", (unsigned int)ovl_regs_plb);
+ if(ovl_regs_plb->buffer0_yrgb_ptr)
+ printk (KERN_ERR "RGB POINTER 0 = 0x%x \n",
+ ovl_regs_plb->buffer0_yrgb_ptr);
+ if(ovl_regs_plb->buffer1_yrgb_ptr)
+ printk (KERN_ERR "RGB POINTER 1 = 0x%x \n",
+ ovl_regs_plb->buffer1_yrgb_ptr);
+ if(ovl_regs_plb->buffer0_u_ptr)
+ printk (KERN_ERR "U POINTER 0 = 0x%x \n",
+ ovl_regs_plb->buffer0_u_ptr);
+ if(ovl_regs_plb->buffer0_v_ptr)
+ printk (KERN_ERR "V POINTER 0 = 0x%x \n",
+ ovl_regs_plb->buffer0_v_ptr);
+ if(ovl_regs_plb->buffer1_u_ptr)
+ printk (KERN_ERR "U POINTER 1 = 0x%x \n",
+ ovl_regs_plb->buffer1_u_ptr);
+ if(ovl_regs_plb->buffer1_v_ptr)
+ printk (KERN_ERR "V POINTER 1 = 0x%x \n",
+ ovl_regs_plb->buffer1_v_ptr);
+
+ printk (KERN_ERR "RGB STRIDE = 0x%x \n",
+ ovl_regs_plb->yrgb_stride);
+ printk (KERN_ERR "UV STRIDE = 0x%x \n",
+ ovl_regs_plb->uv_stride);
+ printk (KERN_ERR "DST POS X = %d \n",
+ ovl_regs_plb->dest_pos_x_left);
+ printk (KERN_ERR "DST POS Y = %d \n",
+ ovl_regs_plb->dest_pos_y_top);
+ printk (KERN_ERR "DST WIDTH = %d \n",
+ ovl_regs_plb->dest_width_x);
+ printk (KERN_ERR "DST HEIGHT = %d \n",
+ ovl_regs_plb->dest_height_y);
+ printk (KERN_ERR "SRC WIDTH = %d \n",
+ ovl_regs_plb->source_yrgb_width);
+ printk (KERN_ERR "SRC SWWIDTH = 0x%x \n",
+ ovl_regs_plb->source_yrgb_width_swords);
+ printk (KERN_ERR "SRC HEIGHT = %d \n",
+ ovl_regs_plb->source_yrgb_height);
+ printk (KERN_ERR "UV SRC WIDTH = %d \n",
+ ovl_regs_plb->source_uv_width);
+ printk (KERN_ERR "UV SRC SWWIDTH = %d \n",
+ ovl_regs_plb->source_uv_width_swords);
+ printk (KERN_ERR "UV SRC HEIGHT = %d \n",
+ ovl_regs_plb->source_uv_height);
+ printk (KERN_ERR "RGB SCALE = 0x%x \n",
+ ovl_regs_plb->yrgb_scale);
+ printk (KERN_ERR "UV SCALE = 0x%x \n",
+ ovl_regs_plb->uv_scale);
+ printk (KERN_ERR "COL CTL BRT CON = 0x%x \n",
+ ovl_regs_plb->col_ctl_brt_con);
+ printk (KERN_ERR "COL CTL SAT HUE = 0x%x \n",
+ ovl_regs_plb->col_ctl_sat_hue);
+ printk (KERN_ERR "DST COLOR KEY = 0x%x \n",
+ ovl_regs_plb->dest_ckey_val);
+ printk (KERN_ERR "DST COLOR KEY MASK = 0x%x \n",
+ ovl_regs_plb->dest_ckey_mask);
+ printk (KERN_ERR "SRC COLOR KEY HI = 0x%x \n",
+ ovl_regs_plb->source_ckey_high);
+ printk (KERN_ERR "SRC COLOR KEY LO = 0x%x \n",
+ ovl_regs_plb->source_ckey_low);
+ printk (KERN_ERR "SRC COLOR KEY MASK = 0x%x \n",
+ ovl_regs_plb->source_ckey_mask);
+ printk (KERN_ERR "OVL CONFIG = 0x%x \n", ovl_regs_plb->config);
+ printk (KERN_ERR "OVL CMD = 0x%x \n", ovl_regs_plb->command);
+ printk (KERN_ERR "FAST_V_DSCALE = 0x%x \n",
+ ovl_regs_plb->vert_downscale);
+ printk (KERN_ERR "************************************************\n");
+}
+#endif
+
+/*----------------------------------------------------------------------
+ * Function: ovl_check_pf_plb()
+ * Parameters: unsigned int requested_pixel_format -
+ * according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ * TRUE on Success
+ * FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_check_pf_plb(
+ igd_display_context_t *display,
+ unsigned int requested_pixel_format)
+{
+ unsigned long *overlay_pfs;
+ int temp_loop = 0;
+
+ display->context->dispatch.get_pixelformats(
+ (igd_display_h)display, NULL, NULL, &overlay_pfs, NULL, NULL);
+
+ while(overlay_pfs[temp_loop]) {
+ if(overlay_pfs[temp_loop] == requested_pixel_format) {
+ return TRUE;
+ }
+ ++temp_loop;
+ }
+
+ return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int ovl_check_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_timing_info_t *timing;
+ ovl_chipset_plb_t *ovl_chip;
+ unsigned int min_w, min_h;
+
+ EMGD_TRACE_ENTER;
+
+ if (!display){
+ EMGD_ERROR_EXIT("display is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!PIPE(display)){
+ EMGD_ERROR_EXIT("PIPE(display) is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ timing = PIPE(display)->timing;
+
+ /* DCT-PC99TA crashes with dotclock > 300MHz */
+ if(timing->dclk >= 340000){
+ EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* The following parameters are only valid if the overlay is on, so
+ * return success if the overlay is being turned off. */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Ensure the overlay surface is ok and can be properly displayed.
+ * This ensures the following is valid:
+ * - Ensure x1, x2, y1, y2 are pixel aligned
+ * - 2 pixels or greater in width and height
+ * - Pixel format is supported by the overlay
+ * - Pitch is <= 8KB
+ * - Based on the pixel format, the width is supported
+ *************************************************************************/
+ if (!src_surf){
+ EMGD_ERROR_EXIT("src_surf is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!src_rect){
+ EMGD_ERROR_EXIT("src_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get the minimum size of 1 pixel in width and height for y, u, and v.
+ */
+ min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+ min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+ if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+ ((src_rect->y2 - src_rect->y1) < min_h*2)) {
+ EMGD_ERROR_EXIT(
+ "Overlay source width or height is < 2 pixels (%dx%d)\n",
+ src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (FALSE == ovl_check_pf_plb(display, src_surf->pixel_format)) {
+ EMGD_ERROR_EXIT("Overlay source pixel format unsupported (pf:0x%lx)",
+ src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ if (src_surf->pitch > 8192) {
+ EMGD_ERROR_EXIT("Overlay source pitch (%d) > 8KB",
+ src_surf->pitch);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ ovl_chip = ovl_chipset_plb;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((src_surf->pixel_format & IGD_PF_MASK) ==
+ ovl_chip->pixel_format) &&
+ (src_surf->width <= ovl_chip->max_width)) {
+ break;
+ }
+ ovl_chip++;
+ }
+ if (ovl_chip->num_linebuf == OVL_CONFIG_NO_LINE_BUFF) {
+ EMGD_ERROR_EXIT("Overlay source width (%d) > max supported",
+ src_surf->width);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the location on the framebuffer is ok and can be properly
+ * displayed
+ * This ensures the following is valid:
+ * - Greater than 1 pixel width and height
+ * - Will be displayed on screen (not panned off)
+ *************************************************************************/
+ if (!dest_rect){
+ EMGD_ERROR_EXIT("dest_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+ ((dest_rect->y2 - dest_rect->y1) <= 1)) {
+ EMGD_ERROR_EXIT(
+ "Overlay dest width or height is single pixel (%dx%d)\n",
+ dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((dest_rect->x1 >= timing->width) ||
+ (dest_rect->y1 >= timing->height)) {
+ EMGD_ERROR_EXIT(
+ "Overlay dest is panned off the screen (%d,%d)\n",
+ dest_rect->x1, dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+static unsigned int ovl_update_src_plb(igd_display_context_t *display,
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ ovl_chipset_plb_t *ovl_chip;
+ unsigned int src_Bpp;
+ unsigned int src_uv_shift_x, src_uv_shift_y;
+ unsigned short src_w;
+ unsigned short src_h;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+ src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+ src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+ src_w = src_rect->x2 - src_rect->x1;
+ src_h = src_rect->y2 - src_rect->y1;
+
+ ovl_regs_plb->yrgb_stride = (unsigned short)src_surf->pitch;
+ ovl_regs_plb->uv_stride = (unsigned short)src_surf->u_pitch;
+
+ /* src width */
+ ovl_regs_plb->source_yrgb_width = src_w;
+ ovl_regs_plb->source_uv_width = src_w >> src_uv_shift_x;
+
+ /* src width swords - This equation follows the B-Spec */
+ ovl_regs_plb->source_yrgb_width_swords =
+ ((((((ovl_regs_plb->buffer0_yrgb_ptr +
+ (ovl_regs_plb->source_yrgb_width * src_Bpp) +
+ 0x3F) >> 6) -
+ (ovl_regs_plb->buffer0_yrgb_ptr >> 6)) << 1) - 1) << 2);
+ ovl_regs_plb->source_uv_width_swords =
+ ((((((ovl_regs_plb->buffer0_u_ptr +
+ (ovl_regs_plb->source_uv_width * src_Bpp) +
+ 0x3F) >> 6) -
+ (ovl_regs_plb->buffer0_u_ptr >> 6)) << 1) - 1) << 2 );
+
+
+ /* src height */
+ ovl_regs_plb->source_yrgb_height = src_h;
+ ovl_regs_plb->source_uv_height = src_h >> src_uv_shift_y;
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ ovl_regs_plb->command |= OVL_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ ovl_regs_plb->command |= OVL_CMD_YUV_422 | OVL_CMD_Y_SWAP;
+ break;
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ ovl_regs_plb->command |= OVL_CMD_YUV_420P;
+ break;
+ case IGD_PF_YUV420_PLANAR_YV12:
+ ovl_regs_plb->command |= OVL_CMD_YUV_420P | OVL_CMD_UV_SWAP;
+ break;
+ case IGD_PF_YUV420_PLANAR_NV12:
+ ovl_regs_plb->command |= OVL_CMD_YUV_NV12;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ ovl_regs_plb->command |= OVL_CMD_YUV_410P;
+ break;
+ case IGD_PF_ARGB32_8888:
+ case IGD_PF_xRGB32_8888:
+ ovl_regs_plb->command |= OVL_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ ovl_regs_plb->command |= OVL_CMD_RGB_565;
+ break;
+ case IGD_PF_xRGB16_555:
+ case IGD_PF_ARGB16_1555:
+ ovl_regs_plb->command |= OVL_CMD_RGB_555;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ ovl_regs_plb->config |= (1<<4);
+ }
+
+ ovl_chip = ovl_chipset_plb;
+ ovl_regs_plb->config &= ~OVL_CONFIG_LINE_BUFF_MASK;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((src_surf->pixel_format & IGD_PF_MASK) ==
+ ovl_chip->pixel_format) &&
+ (src_w <= ovl_chip->max_width)) {
+ ovl_regs_plb->config |= ovl_chip->num_linebuf;
+ break;
+ }
+ ovl_chip++;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+static unsigned int ovl_update_src_ptr_plb(igd_display_context_t *display,
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+ unsigned int src_uv_shift_x, src_uv_shift_y;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+ src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+ src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+ /* src surface */
+ ovl_regs_plb->buffer0_yrgb_ptr =
+ ovl_regs_plb->buffer1_yrgb_ptr =
+ src_surf->offset +
+ (src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp);
+
+ /*
+ * The NV12 format has the UV pixels interleaved so the total
+ * width of the UV portion of the surface is the same as the
+ * Y width. Thus, don't do any shifting of the UV plane in the
+ * X direction.
+ */
+ if (src_surf->pixel_format == IGD_PF_YUV420_PLANAR_NV12) {
+ ovl_regs_plb->buffer0_u_ptr =
+ ovl_regs_plb->buffer1_u_ptr =
+ src_surf->u_offset +
+ ((src_rect->y1>>src_uv_shift_y) * src_surf->u_pitch) +
+ src_rect->x1;
+
+ ovl_regs_plb->buffer0_v_ptr =
+ ovl_regs_plb->buffer1_v_ptr =
+ src_surf->v_offset +
+ ((src_rect->y1>>src_uv_shift_y) * src_surf->v_pitch) +
+ src_rect->x1;
+ } else {
+ ovl_regs_plb->buffer0_u_ptr =
+ ovl_regs_plb->buffer1_u_ptr =
+ src_surf->u_offset +
+ ((src_rect->y1>>src_uv_shift_y) * src_surf->u_pitch) +
+ (src_rect->x1>>src_uv_shift_x);
+
+ ovl_regs_plb->buffer0_v_ptr =
+ ovl_regs_plb->buffer1_v_ptr =
+ src_surf->v_offset +
+ ((src_rect->y1>>src_uv_shift_y) * src_surf->v_pitch) +
+ (src_rect->x1>>src_uv_shift_x);
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+static unsigned int ovl_update_phase_plb(
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Set the Vertical/Horizontal Phase Registers. Both Field0
+ * and Field1 are set, although Field1 is only used when
+ * interleaved.
+ */
+ switch (src_surf->pixel_format) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ /* YUV 422 */
+ ovl_regs_plb->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;
+ ovl_regs_plb->uv_vert_phase_field0 = 0;
+ ovl_regs_plb->uv_vert_phase_field1 = 0;
+ } else {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+ ovl_regs_plb->uv_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x8000; /*.5*/
+ }
+
+ /* Horizontal Phase */
+ if (!(src_rect->x1 & 1)) {
+ ovl_regs_plb->yrgb_hphase = 0;
+ ovl_regs_plb->uv_hphase = 0;
+ } else {
+ ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_plb->yrgb_hphase = 0; /*1*/
+ ovl_regs_plb->uv_hphase = 0x8000; /*.5*/
+ }
+ break;
+
+ case IGD_PF_YUV420_PLANAR_I420:
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ /* YUV 420 */
+ ovl_regs_plb->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ if (!(src_rect->y1 & 1)) {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*0*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*-.25*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+ } else {
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*0*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*-.25*/
+ }
+ } else {
+ if (!(src_rect->y1 & 1)) {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*.75*/
+ } else {
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*.75*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+ }
+ }
+
+ /* Horizontal Phase */
+ if (!(src_rect->x1 & 1)) {
+ ovl_regs_plb->yrgb_hphase = 0;
+ ovl_regs_plb->uv_hphase = 0;
+ } else {
+ ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_plb->yrgb_hphase = 0; /*1*/
+ ovl_regs_plb->uv_hphase = 0x8000; /*.5*/
+ }
+ break;
+
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ /* YUV 410 */
+ ovl_regs_plb->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ switch (src_rect->y1 & 3) {
+ default:
+ case 0:
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*0*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field0 = 0xa000; /*-.375*/
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field1 = 0xe000; /*-.125*/
+ break;
+
+ case 1:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field0 = 0xe000; /*-.125*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x2000; /*.125*/
+ break;
+
+ case 2:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x2000; /*.125*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x6000; /*.375*/
+ break;
+
+ case 3:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*0*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x6000; /*.375*/
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field1 = 0xa000; /*-.375*/
+ break;
+ }
+ } else {
+ switch (src_rect->y1 & 3) {
+ default:
+ case 0:
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*-.25*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0; /*0*/
+ break;
+
+ case 1:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x0; /*0*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+ break;
+
+ case 2:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_plb->uv_vert_phase_field1 = 0x8000; /*.5*/
+ break;
+
+ case 3:
+ ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+ ovl_regs_plb->uv_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*-.25*/
+ break;
+ }
+ }
+
+ /* Horizontal Phase */
+ switch (src_rect->x1 & 3) {
+ default:
+ case 0:
+ ovl_regs_plb->yrgb_hphase = 0;
+ ovl_regs_plb->init_phase_shift |= UV_HPP_MINUS1;
+ ovl_regs_plb->uv_hphase = 0xa000; /*-.375*/
+ break;
+
+ case 1:
+ ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_plb->yrgb_hphase = 0; /*1*/
+ ovl_regs_plb->init_phase_shift |= UV_HPP_MINUS1;
+ ovl_regs_plb->uv_hphase = 0xe000; /*-.125*/
+ break;
+
+ case 2:
+ ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS2;
+ ovl_regs_plb->yrgb_hphase = 0; /*2*/
+ ovl_regs_plb->uv_hphase = 0x2000; /*.125*/
+ break;
+
+ case 3:
+ ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS2;
+ ovl_regs_plb->yrgb_hphase = 0xffff; /*3*/
+ ovl_regs_plb->uv_hphase = 0x6000; /*.375*/
+ break;
+ }
+ break;
+
+ default:
+ /* RGB format */
+ ovl_regs_plb->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0;
+ ovl_regs_plb->uv_vert_phase_field0 = 0;
+ ovl_regs_plb->uv_vert_phase_field1 = 0;
+ } else {
+ ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;
+ ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;
+ ovl_regs_plb->uv_vert_phase_field0 = 0x8000;
+ ovl_regs_plb->uv_vert_phase_field1 = 0x8000;
+ }
+
+ /* Horizontal Phase */
+ ovl_regs_plb->yrgb_hphase = 0;
+ ovl_regs_plb->uv_hphase = 0;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_scale_plb()
+ *
+ * Description: Will update only the scaling registers for the plb core
+ *
+ * Returns:
+ * N/A
+ *----------------------------------------------------------------------*/
+
+static unsigned int ovl_update_scale_plb(
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags)
+{
+ unsigned int uv_shift;
+ unsigned int xscale, xscale_int, xscale_fract;
+ unsigned int yscale, yscale_int, yscale_fract;
+ unsigned int xscale_int_uv, xscale_fract_uv;
+ unsigned int yscale_int_uv, yscale_fract_uv;
+
+ EMGD_TRACE_ENTER;
+
+ xscale = ((src_rect->x2 - src_rect->x1)<<12) /
+ (dest_rect->x2 - dest_rect->x1);
+ yscale = ((src_rect->y2 - src_rect->y1)<<12) /
+ (dest_rect->y2 - dest_rect->y1);
+
+ /* In interleaved mode, the y scale is /2 */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ yscale >>= 1;
+ }
+
+ xscale_int = (xscale & 0x3000) >> 12;
+ xscale_fract = xscale & 0xfff;
+ yscale_int = (yscale & 0x7ff000) >> 12;
+ yscale_fract = yscale & 0xfff;
+
+ uv_shift = get_uv_shift_x(src_surf->pixel_format);
+ xscale_int_uv = ((xscale>>uv_shift) & 0x3000) >> 12;
+ xscale_fract_uv = (xscale>>uv_shift) & 0xfff;
+
+ uv_shift = get_uv_shift_y(src_surf->pixel_format);
+ yscale_int_uv = ((yscale>>uv_shift) & 0x7ff000) >> 12;
+ yscale_fract_uv = (yscale>>uv_shift) & 0xfff;
+
+ ovl_regs_plb->yrgb_scale =
+ (yscale_fract << 20) | /* Vert Scale Fraction */
+ (xscale_int << 16) | /* Horiz Scale Int */
+ (xscale_fract << 3); /* Horiz Scale Fraction */
+
+ ovl_regs_plb->uv_scale =
+ (yscale_fract_uv << 20) | /* UV Vert Scale Fraction */
+ (xscale_int_uv << 16) | /* UV Horiz Scale Int */
+ (xscale_fract_uv << 3 ); /* UV Horiz Scale Fraction */
+ ovl_regs_plb->vert_downscale =
+ (yscale_int << 16) | /* Vert Scale Factor */
+ yscale_int_uv; /* UV Vert Scale Factor */
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_video_quality_plb()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int ovl_update_video_quality_plb(
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+
+ ovl_regs_plb->col_ctl_brt_con = OVL_RGB_COLOR_DEF_CONT_BRGHT;
+ ovl_regs_plb->col_ctl_sat_hue = OVL_RGB_COLOR_DEF_SATN_HUE;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ ovl_regs_plb->col_ctl_brt_con =
+ (ovl_regs_plb->col_ctl_brt_con & 0xFFFFFF00) |
+ (calc_brightness & 0xFF);
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ ovl_regs_plb->col_ctl_brt_con =
+ (ovl_regs_plb->col_ctl_brt_con & 0xF803FFFF) |
+ ((calc_contrast & 0x1FF) << 18);
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ ovl_regs_plb->col_ctl_sat_hue =
+ (ovl_regs_plb->col_ctl_sat_hue & 0xFFFFFC00) |
+ (calc_saturation & 0x3FF);
+
+ /*************************************************************************
+ * Hue
+ *************************************************************************/
+ /* Hue is always set to the default value. It is based on the saturation
+ * value, and having a separate hue is of minimal value. */
+ ovl_regs_plb->col_ctl_sat_hue =
+ (ovl_regs_plb->col_ctl_sat_hue & 0xF800FFFF);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+static void check_gamma(unsigned int *gamma)
+{
+
+ if (*gamma < IGD_OVL_GAMMA_MIN) {
+ EMGD_ERROR("Gamma to small (0x%x in 24i.8f format), "
+ "changing to Min Gamma (0.6)",
+ *gamma);
+ *gamma = IGD_OVL_GAMMA_MIN;
+ }
+ if (*gamma > IGD_OVL_GAMMA_MAX) {
+ EMGD_ERROR("Gamma to large (0x%x in 24i.8f format), "
+ "changing to Max Gamma (6.0)",
+ *gamma);
+ *gamma = IGD_OVL_GAMMA_MAX;
+ }
+
+ return;
+}
+
+
+
+/*-----------------------------------------------------------------------------
+ * Function: ovl_update_gamma_plb()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int ovl_update_gamma_plb(
+ igd_display_context_t *display,
+ igd_ovl_gamma_info_t * ovl_gamma)
+{
+ const int gamma_reg_input[OVL_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+ const int gamma_reg_offset[OVL_TOTAL_GAMMA_REG] = {
+ OVL_REG_ADDR_GAMMA0,
+ OVL_REG_ADDR_GAMMA1,
+ OVL_REG_ADDR_GAMMA2,
+ OVL_REG_ADDR_GAMMA3,
+ OVL_REG_ADDR_GAMMA4,
+ OVL_REG_ADDR_GAMMA5
+ };
+ const unsigned int gamma_def[OVL_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+ };
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled, set it to the default */
+ if ((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) {
+ for (i = 0; i < OVL_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /* Ensure the gamma values are between MIN and MAX */
+ check_gamma(&new_gamma_red_24i_8f);
+ check_gamma(&new_gamma_green_24i_8f);
+ check_gamma(&new_gamma_blue_24i_8f);
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* turn overlay off (TBD) */
+
+ /* program register */
+ EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+ /* turn overlay on (TBD) */
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_coeff_plb()
+ * Description: Function to calculate the filter coeffcient
+ * registers for plb
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_update_coeff_plb(
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags)
+{
+ unsigned int scale_int, scale_fpint;
+
+ unsigned int dest_h = dest_rect->y2 - dest_rect->y1;
+ unsigned int dest_w = dest_rect->x2 - dest_rect->x1;
+ unsigned int src_h = src_rect->y2 - src_rect->y1;
+ unsigned int src_w = src_rect->x2 - src_rect->x1;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The coeff values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* In interleaved mode, the src_h is /2 */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ src_h >>= 1;
+ }
+
+ /* Y Horizontal */
+ scale_int = ((ovl_regs_plb->yrgb_scale) >> 16) & 0x7;
+
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+ }
+ ovl_update_coeff_regs(5, scale_fpint, 1, 1,
+ (unsigned short *)ovl_regs_plb->y_horz_coeff_single);
+
+ /* Y Vertical */
+ scale_int = ((ovl_regs_plb->vert_downscale) >> 16) & 0x7ff;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+ }
+ ovl_update_coeff_regs(3, scale_fpint, 0, 1,
+ (unsigned short *)ovl_regs_plb->y_vert_coeff_single);
+
+ /* UV Horizontal */
+ scale_int = ((ovl_regs_plb->uv_scale) >> 16) & 0x7;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+ scale_fpint >>= get_uv_shift_x(src_surf->pixel_format);
+ }
+ ovl_update_coeff_regs(3, scale_fpint , 1, 0,
+ (unsigned short *)ovl_regs_plb->uv_horz_coeff_single);
+
+ /* UV Vertical */
+ scale_int = (ovl_regs_plb->vert_downscale) & 0x7ff;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+ scale_fpint >>= get_uv_shift_y(src_surf->pixel_format);
+ }
+ ovl_update_coeff_regs(3, scale_fpint, 0, 0,
+ (unsigned short *)ovl_regs_plb->uv_vert_coeff_single);
+
+ /* Adjust for 2-line Vertical Buffer */
+ if((ovl_regs_plb->config & OVL_CONFIG_LINE_BUFF_MASK)==
+ OVL_CONFIG_TWO_LINE_BUFF){
+ ovl_update_coeff_regs(2, 0x10, 0, 1,
+ (unsigned short *)ovl_regs_plb->y_vert_coeff_single);
+ ovl_update_coeff_regs(2, 0x10, 0, 0,
+ (unsigned short *)ovl_regs_plb->uv_vert_coeff_single);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static unsigned int convert_color_key_to_hw (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ case IGD_PF_ARGB8_INDEXED:
+ default:
+ output = input;
+ break;
+ case IGD_PF_RGB16_565:
+ output =
+ ((((input & 0xf800)>>11)<<3)<<16) |
+ ((((input & 0x07e0)>>5 )<<2)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ case IGD_PF_ARGB16_1555:
+ output =
+ ((((input & 0x7c00)>>10)<<3)<<16) |
+ ((((input & 0x03e0)>>5 )<<3)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ }
+
+ return output;
+}
+static unsigned int convert_color_key_to_mask (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ default:
+ output = 0x00000000;
+ break;
+ case IGD_PF_RGB16_565:
+ output = 0x00070307;
+ break;
+ case IGD_PF_ARGB16_1555:
+ output = 0x00070707;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ output = 0x00ffff00;
+ break;
+ }
+
+ return output;
+}
+
+/* Convert RGB to GBR for 32bpp and 16bpp pixel formats.
+ * Do not convert YUV surfaces or RGB indexed pixel formats */
+static unsigned int rgb_to_gbr(
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ if (((pf & IGD_PF_TYPE_MASK) == PF_TYPE_ARGB) &&
+ ((pf & IGD_PF_DEPTH_MASK) != PF_DEPTH_8)) {
+ output =
+ ((input & 0x00ff0000) >> 16) |
+ ((input & 0x0000ff00) << 8) |
+ ((input & 0x000000ff) << 8);
+ } else {
+ output = input;
+ }
+
+ return output;
+}
+
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP /* If no OVL_PLB_CACHE_QUICK_SWAP */
+
+static unsigned int ovl_update_regs_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl_reg_image_plb_t *ovl_regs_plb, *ovl_cache_plb ;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ ovl_regs_plb = phys_to_virt(ovl_context->reg_update_phys);
+ ovl_cache_plb = OS_ALLOC(sizeof(ovl_reg_image_plb_t));
+ OS_MEMSET(ovl_cache_plb, 0, sizeof(ovl_reg_image_plb_t));
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ /* Turn the overlay Off */
+ ovl_regs_plb->command = 0;
+ /* Always use buf 0 when turning the overlay off. */
+ ovl_context->ovl_buff = 0;
+ OS_FREE(ovl_cache_plb);
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* Force value of y1 to even due hardware expects even number */
+ dest_rect->y1 &= ~1;
+ dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+ dest_rect->x1 &= ~1;
+ dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+ /*************************************************************************
+ * Copy the information passed in to the HW overlay structure
+ *************************************************************************/
+ /* Zero the config and command, since they will be OR'ed in with data
+ * below */
+ ovl_cache_plb->config = 0;
+ ovl_cache_plb->command = 0;
+
+ /* Set overlay to the proper pipe */
+ if (1 == PIPE(display)->pipe_num) {
+ /* This is pipe B */
+ ovl_cache_plb->config |= 1 << 18;
+ }
+
+ /* Interleaved/progressive and Odd/Even if interleaved */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ ovl_cache_plb->command |= OVL_CMD_FIELD_MODE;
+ /* Need to enable FIELD SYNC OVERLAY FLIP in field mode. */
+ ovl_cache_plb->command |= OVL_CMD_FIELD_SYNC_FLIP;
+ /* HSD# 203821 Mplayer outputs single one buffer including both even and odd fields */
+ if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+ ovl_cache_plb->command |= OVL_CMD_ACT_FLD1;
+ /* HSD# 203821 To display odd field, starts from first odd field. */
+ if (0 == src_rect->y1 & 1) {
+ src_rect->y1 += 1;
+ }
+ } else {
+ ovl_cache_plb->command |= OVL_CMD_ACT_FLD0;
+ /* HSD# 203821 To display even field, starts from first even field. */
+ if (0 != src_rect->y1 & 1) {
+ src_rect->y1 += 1;
+ }
+ }
+ } else {
+ ovl_cache_plb->command |= OVL_CMD_FRAME_MODE;
+ }
+
+ /* Dest rect information */
+ ovl_cache_plb->dest_pos_x_left = (unsigned short)dest_rect->x1;
+ ovl_cache_plb->dest_pos_y_top = (unsigned short)dest_rect->y1;
+ ovl_cache_plb->dest_width_x =
+ (unsigned short)(dest_rect->x2 - dest_rect->x1);
+ ovl_cache_plb->dest_height_y =
+ (unsigned short)(dest_rect->y2 - dest_rect->y1);
+
+ /* Src rect and surface information */
+
+ ret = ovl_update_src_ptr_plb(display, ovl_cache_plb, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay updating src pointers failed");
+ return ret;
+ }
+
+ ret = ovl_update_src_plb(display, ovl_cache_plb, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay updating src failed");
+ return ret;
+ }
+
+ /* Scaling information including Vertical downscaling.
+ * Scaling should be guaranteed to work, since if the scale is not
+ * supported, it should have already been blended to a supported scale. */
+ ret = ovl_update_scale_plb(ovl_cache_plb, src_surf, src_rect, dest_rect,
+ flags);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay updating scaling failed");
+ return ret;
+ }
+
+ /* Color control information */
+ ret = ovl_update_video_quality_plb(ovl_cache_plb, src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay video quality failed");
+ return ret;
+ }
+ ret = ovl_update_gamma_plb(display, &ovl_info->gamma);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay gamma failed");
+ return ret;
+ }
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the different
+ * pixel formats */
+ ovl_cache_plb->dest_ckey_val = convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_plb->dest_ckey_mask = convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_plb->dest_ckey_mask |= 0x80000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ ovl_cache_plb->dest_ckey_mask = 0x00000000;
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+ ovl_cache_plb->source_ckey_high = convert_color_key_to_hw(
+ src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ovl_cache_plb->source_ckey_high = rgb_to_gbr(
+ src_surf->pixel_format,
+ ovl_cache_plb->source_ckey_high);
+
+ ovl_cache_plb->source_ckey_low = convert_color_key_to_hw(
+ src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ovl_cache_plb->source_ckey_low = rgb_to_gbr(
+ src_surf->pixel_format,
+ ovl_cache_plb->source_ckey_low);
+
+ ovl_cache_plb->source_ckey_mask = 0x07000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ ovl_cache_plb->source_ckey_mask = 0x00000000;
+ }
+
+ /* Coefficients - Must be after Scaling */
+ ret = ovl_update_coeff_plb(ovl_cache_plb, src_surf, src_rect, dest_rect, flags);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay updating coefficient failed");
+ return ret;
+ }
+
+ /* Phase information - Must be after Coefficients */
+ ret = ovl_update_phase_plb(ovl_cache_plb, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_plb);
+ EMGD_ERROR_EXIT("Overlay updating phase failed");
+ return ret;
+ }
+
+ /* General overlay information. Turn the overlay on and alternate
+ * between Buffer 0 and Buffer 1. */
+ ovl_cache_plb->command = (ovl_cache_plb->command & 0xfffffff3) |
+ ovl_context->ovl_buff | 1;
+ ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+ /* Dump out the Overlay Update Registers if debugging */
+ EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_plb(ovl_regs_plb));
+
+ OS_MEMCPY(ovl_regs_plb, ovl_cache_plb, sizeof(ovl_reg_image_plb_t));
+ OS_FREE(ovl_cache_plb);
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#else /* Else OVL_PLB_CACHE_QUICK_SWAP */
+
+/* Poulsbo overlay cache structure */
+static ovl_plb_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+static unsigned int ovl_update_regs_plb(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl_reg_image_plb_t *ovl_regs_plb,
+ *ovl_cache_regs;
+ unsigned int cache_changed;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* get the pointers to the real regs, and our cached copy of them */
+ ovl_regs_plb = phys_to_virt(ovl_context->reg_update_phys);
+ ovl_cache_regs = &ovl_cache.ovl_regs;
+
+ /* Fast path for turning off overlay. No need for cache */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+
+ /* Turn the overlay Off */
+ ovl_regs_plb->command = 0;
+
+ /* if we were using the cache, turn it off there too */
+ if (!ovl_cache_needs_init) {
+ ovl_cache.ovl_regs.command = 0;
+ }
+
+ /* Reset the cache */
+ ovl_cache_needs_init = TRUE;
+
+ /* Always use buf 0 when turning the overlay off. */
+ ovl_context->ovl_buff = 0;
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* Force value to even due hardware expects even number */
+ dest_rect->y1 &= ~1;
+ dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+ dest_rect->x1 &= ~1;
+ dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+ /* Init the cache if necessary */
+ if (ovl_cache_needs_init) {
+
+
+ /* Force every cache check to miss */
+ OS_MEMSET(&ovl_cache, 0, sizeof(ovl_plb_cache_t));
+
+ /* We just set our cached flags to 0, which might accidently
+ * match up with "OFF" for some important incoming flag
+ * bits, causing us to think we already handled them when
+ * we didn't. So set our cached flags to the exact
+ * opposite of the incoming flags, which will force
+ * us to test and handle every single bit, regardless
+ * of whether it is on or off. */
+ ovl_cache.flags = ~flags;
+
+ /* init our cached registers */
+ OS_MEMCPY(ovl_cache_regs,
+ ovl_regs_plb,
+ sizeof(ovl_reg_image_plb_t));
+
+ /* initialization complete */
+ ovl_cache_needs_init = FALSE;
+ }
+
+ /* See what has changed in the cache */
+ cache_changed = get_cache_changes_plb (src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags,
+ &ovl_cache);
+
+ /* Perhaps the biggest challenge of caching the overlay
+ * state is what to do with the command and config regs.
+ * Normally we would clear command and config to 0 here,
+ * and let the update process set only the bits that are
+ * needed. But doing this would invalidate our cache.
+ * Instead we are relying on the above call to
+ * get_cache_changes() to clear those bits in command
+ * and config that will be changing */
+
+ /* Set overlay to the proper pipe */
+ /* it is cheaper to just set this, than to test it and set it. */
+ if (1 == PIPE(display)->pipe_num) {
+ /* This is pipe B */
+ ovl_cache_regs->config |= 1 << 18;
+ } else {
+ ovl_cache_regs->config &= ~(1 << 18);
+ }
+
+ if (cache_changed & IGD_OVL_PLB_UPDATE_FLAGS) {
+
+ /* Interleaved/progressive and Odd/Even if interleaved. */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ ovl_cache_regs->command |= OVL_CMD_FIELD_MODE;
+ /* enable FIELD SYNC OVERLAY FLIP in field mode. */
+ ovl_cache_regs->command |= OVL_CMD_FIELD_SYNC_FLIP;
+ /* HSD# 203821 Mplayer outputs single one buffer including both even and odd fields */
+ if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+ ovl_cache_regs->command |= OVL_CMD_ACT_FLD1;
+ /* HSD# 203821 To display odd field, starts from first odd field. */
+ if (0 == (src_rect->y1 & 1)) {
+ src_rect->y1 += 1;
+ }
+ } else {
+ ovl_cache_regs->command |= OVL_CMD_ACT_FLD0;
+ /* HSD# 203821 To display even field, starts from first even field. */
+ if (0 != (src_rect->y1 & 1)) {
+ src_rect->y1 += 1;
+ }
+ }
+ } else {
+ ovl_cache_regs->command |= OVL_CMD_FRAME_MODE;
+ }
+ }
+
+ /* Has our destination rectangle changed? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+ ovl_cache_regs->dest_pos_x_left =
+ (unsigned short) dest_rect->x1;
+ ovl_cache_regs->dest_pos_y_top =
+ (unsigned short) dest_rect->y1;
+ ovl_cache_regs->dest_width_x =
+ (unsigned short) (dest_rect->x2 - dest_rect->x1);
+ ovl_cache_regs->dest_height_y =
+ (unsigned short) (dest_rect->y2 - dest_rect->y1);
+
+ }
+
+ /* Always update the source pointers every frame */
+ ret = ovl_update_src_ptr_plb(display,
+ ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating src pointers failed");
+ return ret;
+ }
+
+ /* Did either the Src rect or surface change? */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+ IGD_OVL_PLB_UPDATE_SRC ) ) {
+
+ ret = ovl_update_src_plb(display,
+ ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating src failed");
+ return ret;
+ }
+ }
+
+ /* Scaling information including Vertical downscaling.
+ * Scaling should be guaranteed to work, since if the scale
+ * is not supported, it should have already been blended
+ * to a supported scale. */
+ if ( cache_changed & (IGD_OVL_PLB_UPDATE_SRC |
+ IGD_OVL_PLB_UPDATE_SURF |
+ IGD_OVL_PLB_UPDATE_DEST |
+ IGD_OVL_PLB_UPDATE_FLAGS) ) {
+
+ ret = ovl_update_scale_plb(ovl_cache_regs,
+ src_surf,
+ src_rect,
+ dest_rect,
+ flags);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating scaling failed");
+ return ret;
+ }
+ }
+
+ /* Did video quality change? */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ |
+ IGD_OVL_PLB_UPDATE_SURF ) ) {
+ /* Color control information */
+
+ ret = ovl_update_video_quality_plb(ovl_cache_regs, src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay video quality failed");
+ return ret;
+ }
+ }
+
+ /* Did gamma change? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+
+ ret = ovl_update_gamma_plb(display, &ovl_info->gamma);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay gamma failed");
+ return ret;
+ }
+ }
+
+ /* Did color key change? */
+ if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the
+ * different pixel formats */
+ ovl_cache_regs->dest_ckey_val =
+ convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_regs->dest_ckey_mask =
+ convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_regs->dest_ckey_mask |= 0x80000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ ovl_cache_regs->dest_ckey_mask = 0x00000000;
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+ ovl_cache_regs->source_ckey_high =
+ convert_color_key_to_hw(
+ src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ovl_cache_regs->source_ckey_high =
+ rgb_to_gbr(src_surf->pixel_format,
+ ovl_cache_regs->source_ckey_high);
+
+ ovl_cache_regs->source_ckey_low =
+ convert_color_key_to_hw(
+ src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ovl_cache_regs->source_ckey_low =
+ rgb_to_gbr(src_surf->pixel_format,
+ ovl_cache_regs->source_ckey_low);
+
+ ovl_cache_regs->source_ckey_mask = 0x07000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ ovl_cache_regs->source_ckey_mask = 0x00000000;
+ }
+ } /* end color key changes */
+
+
+ /* Coefficients - Must be after Scaling */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_SRC |
+ IGD_OVL_PLB_UPDATE_SURF |
+ IGD_OVL_PLB_UPDATE_DEST |
+ IGD_OVL_PLB_UPDATE_FLAGS ) ) {
+
+ ret = ovl_update_coeff_plb(ovl_cache_regs,
+ src_surf,
+ src_rect,
+ dest_rect,
+ flags);
+ if (ret) {
+ /* Not good. Invalidate entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay update coefficient failed");
+ return ret;
+ }
+ }
+
+ /* Phase information - Must be after Coefficients */
+ if (cache_changed & (IGD_OVL_PLB_UPDATE_SRC |
+ IGD_OVL_PLB_UPDATE_SURF ) ) {
+
+ ret = ovl_update_phase_plb(ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating phase failed");
+ return ret;
+ }
+ }
+
+ /* General overlay information. Turn the overlay on and alternate
+ * between Buffer 0 and Buffer 1. */
+ ovl_cache_regs->command = (ovl_cache_regs->command & 0xfffffff3) |
+ ovl_context->ovl_buff | 1;
+ ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+ /* Dump out the Overlay Update Registers if debugging */
+ EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_plb(ovl_regs_plb));
+
+ /* Finally, transfer the cached regs to the real regs */
+ OS_MEMCPY(ovl_regs_plb,
+ ovl_cache_regs,
+ sizeof(ovl_reg_image_plb_t));
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#endif /* End if OVL_PLB_CACHE_QUICK_SWAP */
+
+static unsigned int ovl_send_instr_plb(
+ igd_display_context_t *display,
+ unsigned int flags)
+{
+ unsigned char * mmio = MMIO(display);
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) {
+
+ ovl_context->state = OVL_STATE_ON;
+ /*
+ * If Overlay + FB Blend is requested and the FB is xRGB
+ * turn on the ARGB format.
+ */
+ if(ovl_context->fb_blend_ovl) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x18000000) {
+ EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+ }
+ }
+
+ } else {
+
+ if (ovl_context->fb_blend_ovl) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x1c000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+ OS_SLEEP(100);
+ }
+ }
+
+ OS_SLEEP(1);
+
+ /* if overlay is being turned OFF - ensure it's ON first */
+ if (ovl_context->state == OVL_STATE_OFF) {
+ /* Overlay is already off, no need to turn it off again */
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ ovl_context->state = OVL_STATE_OFF;
+ }
+
+ /* Write the address of the memory buffer to the Overlay Update
+ * Address Register causes the HW to load the new values from the
+ * memory on the next VBLANK */
+ EMGD_WRITE32((ovl_context->reg_update_phys | 0x1), mmio + 0x30000);
+
+ ovl_context->sync = 0;
+
+ display->context->dispatch.sync(display,
+ IGD_PRIORITY_NORMAL,
+ &ovl_context->sync,
+ IGD_SYNC_NONBLOCK);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+
+static int alter_ovl_plb(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ /* Dump overlay parameters for debugging */
+ /*
+ printk (KERN_ERR " alter_ovl_plb Entry."
+ "offset=0x%X "
+ "pitch=%d "
+ "width=%d "
+ "height=%d \n"
+ "pixel_format=0x%X "
+ "flags=0x%X "
+ "virt_addr=0x%X "
+ "pvr2d_mem_info=0x%X "
+ "pvr2d_context_h=0x%X "
+ "hPVR2DFlipChain=0x%X \n"
+ "src_x1=%d "
+ "src_x2=%d "
+ "src_y1=%d "
+ "src_y2=%d "
+ "src width=%d "
+ "src height=%d \n"
+ "dest_x1=%d "
+ "dest_x2=%d "
+ "dest_y1=%d "
+ "dest_y2=%d "
+ "dest width=%d "
+ "dest height=%d \n"
+ "color_key.src_lo=0x%X "
+ "color_key.src_hi=0x%X "
+ "color_key.dest=0x%X "
+ "color_key.flags=0x%X "
+ "flags=0x%X "
+ ,
+ (unsigned int) src_surf->offset ,
+ (unsigned int) src_surf->pitch ,
+ (unsigned int) src_surf->width ,
+ (unsigned int) src_surf->height ,
+ (unsigned int) src_surf->pixel_format ,
+ (unsigned int) src_surf->flags ,
+ (unsigned int) src_surf->virt_addr ,
+ (unsigned int) src_surf->pvr2d_mem_info ,
+ (unsigned int) src_surf->pvr2d_context_h ,
+ (unsigned int) src_surf->hPVR2DFlipChain ,
+ (unsigned int) src_rect->x1,
+ (unsigned int) src_rect->x2,
+ (unsigned int) src_rect->y1,
+ (unsigned int) src_rect->y2,
+ (unsigned int) (src_rect->x2 - src_rect->x1),
+ (unsigned int) (src_rect->y2 - src_rect->y1),
+ (unsigned int) dest_rect->x1,
+ (unsigned int) dest_rect->x2,
+ (unsigned int) dest_rect->y1,
+ (unsigned int) dest_rect->y2,
+ (unsigned int) (dest_rect->x2 - dest_rect->x1),
+ (unsigned int) (dest_rect->y2 - dest_rect->y1),
+ (unsigned int) ovl_info->color_key.src_lo,
+ (unsigned int) ovl_info->color_key.src_hi,
+ (unsigned int) ovl_info->color_key.dest,
+ (unsigned int) ovl_info->color_key.flags,
+ (unsigned int) flags
+ );
+ */
+ /* Dump overlay surface contents, for debugging */
+ /*
+ if (flags & IGD_OVL_ALTER_ON)
+ {
+ int i;
+ unsigned char *ptr = src_surf->virt_addr;
+
+ for (i = 0; i<10; ++i) {
+ printk(KERN_ERR
+ "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+ "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+ "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+ "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
+ ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],
+ ptr[5],ptr[6],ptr[7],ptr[8],ptr[9],
+ ptr[10],ptr[11],ptr[12],ptr[13],ptr[14],
+ ptr[15],ptr[16],ptr[17],ptr[18],ptr[19],
+ ptr[20],ptr[21],ptr[22],ptr[23],ptr[24],
+ ptr[25],ptr[26],ptr[27],ptr[28],ptr[29],
+ ptr[30],ptr[31],ptr[32],ptr[33],ptr[34],
+ ptr[35],ptr[36],ptr[37],ptr[38],ptr[39]);
+ ptr += src_surf->pitch;
+ }
+ }
+ */
+
+ /* Check to ensure the overlay can be used given the current mode as
+ * well as what the IAL is asking for. If not return an error. */
+ ret = ovl_check_plb(display, src_surf, src_rect, dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay Check failed");
+ return ret;
+ }
+
+ /* Check if last flip is still pending.
+ * This is necessary for the following reasons:
+ * - If the previous instructions have not been processed, then the
+ * ovl_regs_plb is still in use and can not be overwritten.
+ */
+ if ((FALSE == query_ovl_plb(
+ (igd_display_h)display,
+ IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) &&
+ (flags & IGD_OVL_ALTER_ON)) {
+ /* Only return an error if the overlay is on. If turning it off,
+ * allow it to continue, since something may have failed and we
+ * should try our best to turn the overlay off. */
+ EMGD_ERROR_EXIT("Query Overlay failed");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Update all Overlay Update Registers */
+ ret = ovl_update_regs_plb(display, src_surf, src_rect,
+ dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay Update Registers failed");
+ return ret;
+ }
+
+ /* Send the instructions to the command queue */
+ ret = ovl_send_instr_plb(display, flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+static int query_ovl_plb(igd_display_h display_h,
+ unsigned int flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_h;
+ os_alarm_t timeout;
+
+ EMGD_TRACE_ENTER;
+
+ switch (flags) {
+
+ case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+ /* This is the first overlay, so HW overlay is supported */
+ break;
+
+ case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+ /* If there no sync to wait on, then the last flip is done, and the
+ * Register Update has occured, simply return TRUE (Flip done).
+ */
+ /*if (!(ovl_context->sync)) {
+ return TRUE;
+ }*/
+
+ /* Check to see if the last flip instruction has been executed. If not
+ * return FALSE (Flip not done). */
+ /*if(display->context->dispatch.sync(
+ display,
+ IGD_PRIORITY_NORMAL,
+ &ovl_context->sync,
+ IGD_SYNC_NONBLOCK)) {
+ EMGD_DEBUG("Overlay Sync Check - Flip not done");
+ return FALSE;
+ }*/
+
+ /* Check to see if the register update is complete. If not return
+ * FALSE (Flip not done). */
+ if(!(EMGD_READ32(MMIO(display) + 0x30008) & 0x80000000)) {
+ EMGD_DEBUG("Overlay Status Check - Register Update not done");
+ return FALSE;
+ }
+
+ /* Now that we know the last flip is done and the register update is
+ * complete, set the sync to 0 and return TRUE (Flip done). */
+ ovl_context->sync = 0;
+ break;
+
+ case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+ /* Wait for 200 milliseconds for the last flip to complete. If not
+ * done in that time, there is likely a hardware problem so return
+ * FALSE. */
+ timeout = OS_SET_ALARM(200);
+ do {
+ if (TRUE ==
+ query_ovl_plb(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+ } while (!OS_TEST_ALARM(timeout));
+ EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+ return FALSE;
+ break;
+ case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+ return TRUE;
+ break;
+ case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+ return TRUE;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+static int query_max_size_ovl_plb(
+ igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height)
+{
+ ovl_chipset_plb_t *ovl_chip;
+
+ EMGD_TRACE_ENTER;
+
+ ovl_chip = ovl_chipset_plb;
+ *max_width = 0;
+ *max_height = 0;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((pf & IGD_PF_MASK) == ovl_chip->pixel_format) &&
+ (ovl_chip->max_width > *max_width)) {
+ *max_width = ovl_chip->max_width;
+ *max_height = ovl_chip->max_height;
+ }
+ ovl_chip++;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
new file mode 100755
index 0000000..8258de9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
@@ -0,0 +1,323 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_plb_cache.c
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Support functions for overlay caching.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.overlay
+
+#include "ovl_plb_cache.h"
+
+/*
+ * Caching helper functions. Implemented in ovl_plb.c, but used by
+ * the ovl2 and micro_ovl modules as well.
+ */
+
+/* Tells if a rectangle has changed */
+int is_changed_rect(
+ igd_rect_t *old_rect,
+ igd_rect_t *new_rect)
+{
+ return ((old_rect->x1 != new_rect->x1) ||
+ (old_rect->x2 != new_rect->x2) ||
+ (old_rect->y1 != new_rect->y1) ||
+ (old_rect->y2 != new_rect->y2) );
+}
+
+/* Tells if a surface has changed */
+int is_changed_surf(
+ igd_surface_t *old_surf,
+ igd_surface_t *new_surf)
+{
+ return( (old_surf->pitch != new_surf-> pitch) ||
+ (old_surf->width != new_surf-> width) ||
+ (old_surf->height != new_surf-> height) ||
+ (old_surf->pixel_format != new_surf-> pixel_format) ||
+ (old_surf->u_pitch != new_surf-> u_pitch) ||
+ (old_surf->v_pitch != new_surf-> v_pitch) ||
+ (old_surf->palette_info != new_surf-> palette_info) ||
+ (old_surf->flags != new_surf-> flags) ||
+ (old_surf->logic_ops != new_surf-> logic_ops) ||
+ (old_surf->render_ops != new_surf-> render_ops) ||
+ (old_surf->alpha != new_surf-> alpha) ||
+ (old_surf->diffuse != new_surf-> diffuse) ||
+ (old_surf->chroma_high != new_surf-> chroma_high) ||
+ (old_surf->chroma_low != new_surf-> chroma_low) );
+
+}
+
+/* Tells if the color key has changed */
+ int is_changed_color_key(
+ igd_ovl_info_t *old_info,
+ igd_ovl_info_t *new_info)
+{
+ return ( (old_info->color_key.src_lo != new_info->color_key.src_lo) ||
+ (old_info->color_key.src_hi != new_info->color_key.src_hi) ||
+ (old_info->color_key.dest != new_info->color_key.dest) ||
+ (old_info->color_key.flags != new_info->color_key.flags) );
+
+}
+
+/* Tells if the video quality has changed */
+int is_changed_vq(
+ igd_ovl_info_t *old_info,
+ igd_ovl_info_t *new_info)
+{
+ return ( (old_info->video_quality.contrast !=
+ new_info->video_quality.contrast) ||
+ (old_info->video_quality.brightness !=
+ new_info->video_quality.brightness) ||
+ (old_info->video_quality.saturation !=
+ new_info->video_quality.saturation) ||
+ (old_info->video_quality.hue !=
+ new_info->video_quality.hue) );
+
+}
+
+/* Tells if the gamma has changed */
+int is_changed_gamma(
+ igd_ovl_info_t *old_info,
+ igd_ovl_info_t *new_info)
+{
+ return ((old_info->gamma.red != new_info->gamma.red) ||
+ (old_info->gamma.green != new_info->gamma.green) ||
+ (old_info->gamma.blue != new_info->gamma.blue) ||
+ (old_info->gamma.flags != new_info->gamma.flags) );
+
+}
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_plb(igd_rect_t *src_rect, povl_plb_cache_t ovl_cache)
+{
+ if (src_rect) {
+ OS_MEMCPY(&ovl_cache->src_rect,
+ src_rect,
+ sizeof(igd_rect_t));
+ } else {
+ OS_MEMSET(&ovl_cache->src_rect,
+ 0,
+ sizeof(igd_rect_t));
+ }
+}
+
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_plb( igd_rect_t *dest_rect, povl_plb_cache_t ovl_cache)
+{
+ if (dest_rect) {
+ OS_MEMCPY(&ovl_cache->dest_rect,
+ dest_rect,
+ sizeof(igd_rect_t));
+ } else {
+ OS_MEMSET(&ovl_cache->dest_rect,
+ 0,
+ sizeof(igd_rect_t));
+ }
+}
+
+
+/* Copies a surface to the cache */
+void copy_surf_plb(igd_surface_t *src_surf, povl_plb_cache_t ovl_cache)
+{
+ if (src_surf) {
+ OS_MEMCPY(&ovl_cache->src_surf,
+ src_surf,
+ sizeof(igd_surface_t));
+ } else {
+ OS_MEMSET(&ovl_cache->src_surf,
+ 0,
+ sizeof(igd_surface_t));
+ }
+}
+
+
+/* Copies the color key to the cache */
+void copy_color_key_plb( igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.color_key,
+ &(ovl_info->color_key),
+ sizeof(igd_ovl_color_key_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.color_key,
+ 0,
+ sizeof(igd_ovl_color_key_info_t));
+ }
+}
+
+
+/* Copies the video quality info to the cache */
+void copy_vq_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.video_quality,
+ &(ovl_info->video_quality),
+ sizeof(igd_ovl_video_quality_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.video_quality,
+ 0,
+ sizeof(igd_ovl_video_quality_info_t));
+ }
+}
+
+
+/* Copies the gamma to the cache */
+void copy_gamma_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.gamma,
+ &(ovl_info->gamma),
+ sizeof(igd_ovl_gamma_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.gamma,
+ 0,
+ sizeof(igd_ovl_gamma_info_t));
+ }
+}
+
+
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_plb(
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags,
+ povl_plb_cache_t ovl_cache)
+{
+ unsigned int cache_changed = 0;
+
+ ovl_cache->ovl2_regs.control = 0;
+
+ /* Have the flags changed? */
+ if (ovl_cache->flags != flags) {
+
+ /* NOTE that we did not check which flags changed.
+ Currently if any flag changes, we invalidate all
+ the flags. We could further optimize caching if
+ we tested for individual flag changes, but I don't
+ think it will really help much. Once a movie starts
+ playing, it pretty much uses the same flags
+ for its entire duration, unless the user is mucking
+ about with it as it plays, in which case it's going
+ to be slow anyway. */
+
+ ovl_cache->flags = flags;
+ cache_changed |= IGD_OVL_PLB_UPDATE_FLAGS;
+
+ /* Invalidating the flags cache will cause the following
+ * bits to be re-calculated. Clear them in preparation for
+ * re-calculation. */
+ ovl_cache->ovl_regs.command &= ~ (OVL_CMD_FRAME_MODE |
+ OVL_CMD_FIELD_MODE |
+ OVL_CMD_FIELD_SYNC_FLIP |
+ OVL_CMD_ACT_FLD1 |
+ OVL_CMD_ACT_FLD0 );
+ }
+
+ /* Do a comparison to source surface */
+ if (is_changed_surf(&ovl_cache->src_surf, src_surf)) {
+ cache_changed |= IGD_OVL_PLB_UPDATE_SURF;
+ copy_surf_plb(src_surf, ovl_cache);
+
+ /* invalidating the source surface will cause the driver
+ * to recalculate the following bits in command */
+ ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422 |
+ OVL_CMD_YUV_420P |
+ OVL_CMD_YUV_410P |
+ OVL_CMD_YUV_NV12 |
+ OVL_CMD_Y_SWAP |
+ OVL_CMD_UV_SWAP |
+ OVL_CMD_RGB_8888 |
+ OVL_CMD_RGB_565 |
+ OVL_CMD_RGB_555 );
+
+ /* Invalidating the source surface will cause the driver
+ * to recalculate the following bits in config */
+ ovl_cache->ovl_regs.config &= ~ ( (1<<4) |
+ OVL_CONFIG_LINE_BUFF_MASK );
+
+ }
+
+ /* Do a comparison to source rectangle */
+ if (is_changed_rect(&ovl_cache->src_rect, src_rect)) {
+ cache_changed |= IGD_OVL_PLB_UPDATE_SRC;
+ copy_src_rect_plb(src_rect, ovl_cache);
+
+ /* invalidating the source rectangle will cause the driver
+ * to recalculate the following bits in command */
+ ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422 |
+ OVL_CMD_YUV_420P |
+ OVL_CMD_YUV_410P |
+ OVL_CMD_YUV_NV12 |
+ OVL_CMD_Y_SWAP |
+ OVL_CMD_UV_SWAP |
+ OVL_CMD_RGB_8888 |
+ OVL_CMD_RGB_565 |
+ OVL_CMD_RGB_555 );
+
+ /* Invalidating the source rectangle will cause the driver
+ * to recalculate the following bits in config */
+ ovl_cache->ovl_regs.config &= ~ ( (1<<4) |
+ OVL_CONFIG_LINE_BUFF_MASK );
+
+
+ }
+
+ /* Has our destination rectangle changed? */
+ if (is_changed_rect(&ovl_cache->dest_rect, dest_rect)) {
+ cache_changed |= IGD_OVL_PLB_UPDATE_DEST;
+ copy_dest_rect_plb(dest_rect, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info color key */
+ if (is_changed_color_key(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= (IGD_OVL_PLB_UPDATE_INFO |
+ IGD_OVL_PLB_UPDATE_COLORKEY);
+ copy_color_key_plb(ovl_info, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info video quality */
+ if (is_changed_vq(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= ( IGD_OVL_PLB_UPDATE_INFO |
+ IGD_OVL_PLB_UPDATE_VQ);
+ copy_vq_plb(ovl_info, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info gamma */
+ if (is_changed_gamma(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= ( IGD_OVL_PLB_UPDATE_INFO |
+ IGD_OVL_PLB_UPDATE_GAMMA);
+ copy_gamma_plb(ovl_info, ovl_cache);
+ }
+
+ return cache_changed;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
new file mode 100644
index 0000000..b8bb2ef
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
@@ -0,0 +1,161 @@
+/*
+ *----------------------------------------------------------------------------
+ * Filename: ovl_plb_cache.h
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay caching. It should be not be
+ * by any other module besides the overlay module itself.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL_PLB_CACHE_H
+#define _OVL_PLB_CACHE_H
+
+#include <rb.h>
+#include "ovl_regs_plb.h"
+#include "ovl2_regs_plb.h"
+
+/* Turns the overlay cache on and off. */
+#define OVL_PLB_CACHE_QUICK_SWAP
+
+
+/*
+ * In order to cache the overlay registers we need a structure
+ * that defines and wraps them. We already have one for the primary
+ * display, called ovl_reg_image_plb_t.
+ * Here we define a structure for the secondary display
+ */
+
+typedef struct _ovl2_reg_plb_cache{
+ unsigned int control;
+ unsigned int start;
+ unsigned int plane_control;
+ unsigned int plane_start;
+
+ unsigned int pitch;
+ unsigned int dest_rect_x1y1;
+ unsigned int dest_rect_x2y2;
+ unsigned int cont_bright;
+ unsigned int satn_hue;
+ unsigned int gamma_regs[OVL2_TOTAL_GAMMA_REG];
+ unsigned int colorkey_hw;
+ unsigned int colorkey_mask;
+ unsigned int ckey_high;
+ unsigned int ckey_low;
+ unsigned int ckey_enable;
+
+} ovl2_reg_plb_cache_t;
+
+#define MMIO_OFFSET_PLB2_PITCH 0x72188
+#define MMIO_OFFSET_PLB2_DEST_RECT_X1Y1 0x7218C
+#define MMIO_OFFSET_PLB2_DEST_RECT_X2Y2 0x72190
+#define MMIO_OFFSET_PLB2_CONT_BRIGHT 0x721D0
+#define MMIO_OFFSET_PLB2_SATN_HUE 0x721D4
+#define MMIO_OFFSET_PLB2_COLORKEY_HW 0x14
+#define MMIO_OFFSET_PLB2_COLORKEY_MASK 0x18
+#define MMIO_OFFSET_PLB2_CKEY_LOW 0x72194
+#define MMIO_OFFSET_PLB2_CKEY_HIGH 0x721a0
+#define MMIO_OFFSET_PLB2_CKEY_ENABLE 0x72198
+#define MMIO_OFFSET_PLB2_CONTROL 0x72180
+#define MMIO_OFFSET_PLB2_START 0x72184
+
+
+/*
+ * This stucture caches the overlay state, so we don't have to
+ * re-program everything for every single frame
+ */
+typedef struct _ovl_plb_cache {
+ igd_surface_t src_surf;
+ igd_rect_t src_rect;
+ igd_rect_t dest_rect;
+ igd_ovl_info_t ovl_info;
+ unsigned int flags;
+ ovl_reg_image_plb_t ovl_regs;
+ ovl2_reg_plb_cache_t ovl2_regs;
+} ovl_plb_cache_t, *povl_plb_cache_t;
+
+
+/* Flags for things that might have changed in the cache */
+#define IGD_OVL_PLB_UPDATE_DEST (1 << 0)
+#define IGD_OVL_PLB_UPDATE_SRC (1 << 1)
+#define IGD_OVL_PLB_UPDATE_SURF (1 << 2)
+#define IGD_OVL_PLB_UPDATE_INFO (1 << 3)
+#define IGD_OVL_PLB_UPDATE_FLAGS (1 << 4)
+#define IGD_OVL_PLB_UPDATE_VQ (1 << 5)
+#define IGD_OVL_PLB_UPDATE_GAMMA (1 << 6)
+#define IGD_OVL_PLB_UPDATE_COLORKEY (1 << 7)
+
+
+/*
+ * Caching helper functions. Implemented in ovl_plb.c, but used by
+ * the ovl2 and micro_ovl modules as well.
+ */
+
+/* Tells if a rectangle has changed */
+int is_changed_rect(igd_rect_t *old_rect, igd_rect_t *new_rect);
+
+/* Tells if a surface has changed */
+int is_changed_surf(igd_surface_t *old_surf, igd_surface_t *new_surf);
+
+/* Tells if the color key has changed */
+ int is_changed_color_key(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info) ;
+
+/* Tells if the video quality has changed */
+int is_changed_vq(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the gamma has changed */
+int is_changed_gamma(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_plb(igd_rect_t *src_rect, povl_plb_cache_t ovl_cache);
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_plb(igd_rect_t *dest_rect, povl_plb_cache_t ovl_cache);
+
+/* Copies a surface to the cache */
+void copy_surf_plb(igd_surface_t *src_surf, povl_plb_cache_t ovl_cache);
+
+/* Copies the color key to the cache */
+void copy_color_key_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Copies the video quality info to the cache */
+void copy_vq_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Copies the gamma to the cache */
+void copy_gamma_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_plb(
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags,
+ povl_plb_cache_t ovl_cache);
+
+
+
+#endif /* _OVL_PLB_CACHE_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
new file mode 100644
index 0000000..34b24c4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
@@ -0,0 +1,185 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_regs_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized register dependant information including
+ * values, structures and addresses specifically for the Napa core
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef OVL_REGS_PLB_H_
+#define OVL_REGS_PLB_H_
+
+/* Overlay Update Register Image Structure.*/
+typedef struct _ovl_reg_image_plb{
+
+ volatile unsigned int buffer0_yrgb_ptr;
+ volatile unsigned int buffer1_yrgb_ptr;
+ volatile unsigned int buffer0_u_ptr;
+ volatile unsigned int buffer0_v_ptr;
+ volatile unsigned int buffer1_u_ptr;
+ volatile unsigned int buffer1_v_ptr;
+ volatile unsigned short yrgb_stride;
+ volatile unsigned short uv_stride;
+ volatile unsigned short yrgb_vert_phase_field0;
+ volatile unsigned short yrgb_vert_phase_field1;
+ volatile unsigned short uv_vert_phase_field0;
+ volatile unsigned short uv_vert_phase_field1;
+ volatile unsigned short yrgb_hphase;
+ volatile unsigned short uv_hphase;
+ volatile unsigned int init_phase_shift;
+ volatile unsigned short dest_pos_x_left;
+ volatile unsigned short dest_pos_y_top;
+ volatile unsigned short dest_width_x;
+ volatile unsigned short dest_height_y;
+ volatile unsigned short source_yrgb_width;
+ volatile unsigned short source_uv_width;
+ volatile unsigned short source_yrgb_width_swords;
+ volatile unsigned short source_uv_width_swords;
+ volatile unsigned short source_yrgb_height;
+ volatile unsigned short source_uv_height;
+ volatile unsigned int yrgb_scale;
+ volatile unsigned int uv_scale;
+ volatile unsigned int col_ctl_brt_con;
+ volatile unsigned int col_ctl_sat_hue;
+ volatile unsigned int dest_ckey_val;
+ volatile unsigned int dest_ckey_mask;
+ volatile unsigned int source_ckey_high;
+ volatile unsigned int source_ckey_low;
+ volatile unsigned int source_ckey_mask;
+ volatile unsigned int config;
+ volatile unsigned int command;
+ volatile unsigned int reserved1;
+ volatile unsigned short alpha_pos_x_left;
+ volatile unsigned short alpha_pos_y_top;
+ volatile unsigned short alpha_width_x;
+ volatile unsigned short alpha_height_y;
+ volatile unsigned int reserved2;
+ volatile unsigned int reserved3;
+ volatile unsigned int reserved4;
+ volatile unsigned int reserved5;
+ volatile unsigned int reserved6;
+ volatile unsigned int reserved7;
+ volatile unsigned int reserved8;
+ volatile unsigned int reserved9;
+ volatile unsigned int reserved10;
+ volatile unsigned int reserved11;
+ volatile unsigned int reserved11a; /*ovl_fast_horz_downscale;*/
+ volatile unsigned int vert_downscale;
+ volatile unsigned int reserved12[86];
+ volatile unsigned short y_vert_coeff_single[52]; /*offset 0x200 --> 3*17/2 + 1*/
+ volatile unsigned int reserved13[38];
+ volatile unsigned short y_horz_coeff_single[86]; /*offset 0x300 --> 5*17/2 + 1*/
+ volatile unsigned int reserved14[85];
+ volatile unsigned short uv_vert_coeff_single[52]; /*offset 0x500 --> 3*17/2 + 1*/
+ volatile unsigned int reserved15[38];
+ volatile unsigned short uv_horz_coeff_single[52]; /*offset 0x600 --> 3*17/2 + 1*/
+ volatile unsigned int reserved16[38];
+
+} ovl_reg_image_plb_t;
+
+/* Color Correction */
+#define OVL_YUV_COLOR_DEF_CONT_BRGHT 0x10c00fb
+#define OVL_YUV_COLOR_DEF_SATN_HUE 0x0000091
+#define OVL_RGB_COLOR_DEF_CONT_BRGHT 0x1000000
+#define OVL_RGB_COLOR_DEF_SATN_HUE 0x0000080
+
+/* Overlay Config */
+#define OVL_CONFIG_NO_LINE_BUFF 0xffffffff
+#define OVL_CONFIG_TWO_LINE_BUFF 0x00000000
+#define OVL_CONFIG_THREE_LINE_BUFF 0x00000001
+#define OVL_CONFIG_LINE_BUFF_MASK 0x00000001
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL_CMD_UV_SWAP 0x00004000
+#define OVL_CMD_Y_SWAP 0x00008000
+#define OVL_CMD_YUV_SWAP 0x0000C000
+
+/* Source Format */
+#define OVL_CMD_RGB_8888 0x00000400
+#define OVL_CMD_RGB_565 0x00000C00
+#define OVL_CMD_RGB_555 0x00000800
+#define OVL_CMD_YUV_NV12Alt 0x00001C00 /*planar NV12, Alternate?*/
+#define OVL_CMD_YUV_NV12 0x00002C00 /*planar NV12*/
+#define OVL_CMD_YUV_422 0x00002000 /*packed YUV422*/
+#define OVL_CMD_YUV_411 0x00002400 /*packed YUV411*/
+#define OVL_CMD_YUV_420P 0x00003000 /*planar YUV420*/
+#define OVL_CMD_YUV_422P 0x00003400 /*planar YUV422*/
+#define OVL_CMD_YUV_410P 0x00003800 /*planar YUV410*/
+#define OVL_CMD_YUV_444P 0x00003C00 /*planar YUV444*/
+#define OVL_CMD_SRC_FMT_MASK 0x00003C00 /*mask for above*/
+
+/* Flip Type */
+#define OVL_CMD_FRAME_MODE 0x00000000
+#define OVL_CMD_FIELD_MODE 0x00000020
+
+/* Field Sync Flip Enable */
+#define OVL_CMD_FIELD_SYNC_FLIP 0x00000080
+
+/* Buffer and Field */
+#define OVL_CMD_ACT_BUF0 0x00000000
+#define OVL_CMD_ACT_BUF1 0x00000004
+#define OVL_CMD_ACT_FLD0 0x00000000
+#define OVL_CMD_ACT_FLD1 0x00000002
+
+/* Initial phase register */
+#define Y_VPP_FLD0_PLUS1 0x100000
+#define Y_VPP_FLD0_PLUS2 0x200000
+#define Y_VPP_FLD0_MINUS1 0xF00000
+#define Y_VPP_FLD1_PLUS1 0x010000
+#define Y_VPP_FLD1_PLUS2 0x020000
+#define Y_VPP_FLD1_MINUS1 0x0F0000
+#define Y_HPP_PLUS1 0x001000
+#define Y_HPP_PLUS2 0x002000
+#define Y_HPP_MINUS1 0x00F000
+#define UV_VPP_FLD0_PLUS1 0x000100
+#define UV_VPP_FLD0_PLUS2 0x000200
+#define UV_VPP_FLD0_MINUS1 0x000F00
+#define UV_VPP_FLD1_PLUS1 0x000010
+#define UV_VPP_FLD1_PLUS2 0x000020
+#define UV_VPP_FLD1_MINUS1 0x0000F0
+#define UV_HPP_PLUS1 0x000001
+#define UV_HPP_PLUS2 0x000002
+#define UV_HPP_MINUS1 0x00000F
+
+#define OVL_REG_ADDR_GAMMA5 0x30010
+#define OVL_REG_ADDR_GAMMA4 0x30014
+#define OVL_REG_ADDR_GAMMA3 0x30018
+#define OVL_REG_ADDR_GAMMA2 0x3001C
+#define OVL_REG_ADDR_GAMMA1 0x30020
+#define OVL_REG_ADDR_GAMMA0 0x30024
+#define OVL_TOTAL_GAMMA_REG 6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+ than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV 0x43//4a
+#define MID_SATURATION_YUV 0x91//92
+#define MID_BRIGHTNESS_YUV -5
+
+#endif /* OVL_REGISTER_IMAGE_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
new file mode 100755
index 0000000..c13a791
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
@@ -0,0 +1,1822 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_ovl_tnc.c
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the second
+ * overlay with the bits to properly configure the overlay
+ * Also includes functions to execute the second overlay flip
+ * instruction, and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips second overlay
+ * capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <io.h>
+#include <memory.h>
+#include <intelpci.h>
+#include <math_fix.h>
+
+
+#include <igd_mode.h>
+#include <utils.h>
+#include <general.h>
+#include <context.h>
+#include <rb.h>
+#include <mode.h>
+
+#include <tnc/instr.h>
+#include <tnc/regs.h>
+#include <tnc/cmd.h>
+#include "ovl_tnc_cache.h"
+#include "ovl2_tnc.h"
+#include "ovl2_regs_tnc.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+
+extern unsigned long sprite_pixel_formats_tnc[];
+
+extern unsigned int ovl2_check_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+int micro_alter_ovl2_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+unsigned int micro_spritec_send_instr_tnc(
+ igd_display_context_t *display,
+ unsigned long regs,
+ unsigned long value);
+extern ovl_context_t ovl_context[1];
+
+#ifndef CONFIG_MICRO_OVERLAY
+#define OVL2_CHECK_TNC_RET(ret,a, b, c, d, e,f) ret = ovl2_check_tnc(a ,b ,c ,d ,e ,f)
+#define QUERY_OVL2_TNC_RET(ret,a, b) ret = query_ovl2_tnc(a, b)
+#else
+#define OVL2_CHECK_TNC_RET(ret,a, b, c, d, e,f) 0
+#define QUERY_OVL2_TNC_RET(ret,a, b) 0
+#endif
+
+ovl_dispatch_t ovl_micro_dispatch_tnc[] = {
+ {
+ NULL,
+ micro_alter_ovl2_tnc,
+ NULL,
+ NULL,
+ },
+};
+
+#ifndef OVL_TNC_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+
+unsigned int micro_spritec_update_src_tnc(igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+ igd_surface_t blt_surf;
+ igd_rect_t blt_rect_dest;
+ igd_coord_t blt_coord_src;
+ igd_chroma_t chroma;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+ /* src surface */
+ spritec_regs_tnc->start = src_surf->offset;
+
+ /* DSPCLINOFF - Display C/Sprite Linear Offset Register */
+ EMGD_WRITE32(
+ (src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp),
+ MMIO(display) + 0x72184);
+
+ /* DSPCTILEOFF - Display C Tiled Offset Reg */
+ EMGD_WRITE32(0,
+ MMIO(display) + 0x721a4);
+
+ /* DSPCSTRIDE - Display C/Sprite Stride Register */
+ EMGD_WRITE32(src_surf->pitch,
+ MMIO(display) + 0x72188);
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ spritec_regs_tnc->control |= OVL2_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ spritec_regs_tnc->control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+ break;
+ case IGD_PF_ARGB32_8888:
+ spritec_regs_tnc->control |= OVL2_CMD_ARGB_8888;
+ break;
+ case IGD_PF_xRGB32_8888:
+ spritec_regs_tnc->control |= OVL2_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ spritec_regs_tnc->control |= OVL2_CMD_RGB_565;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ spritec_regs_tnc->control |= OVL2_CMD_RGB_8;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ spritec_regs_tnc->control |= (1<<19);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: spritec_update_video_quality_tnc()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+ unsigned int calc_hue_tmp = 0;
+ unsigned int calc_hue = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+ if (video_quality->hue != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+ EMGD_WRITE32(OVL2_RGB_COLOR_DEF_CONT_BRGHT,
+ MMIO(display) + 0x721D0);
+ EMGD_WRITE32(OVL2_RGB_COLOR_DEF_SATN_HUE,
+ MMIO(display) + 0x721D4);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xFFFFFF00) |
+ (calc_brightness & 0xFF),
+ MMIO(display) + 0x721D0);
+
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xF803FFFF) |
+ ((calc_contrast & 0x1FF) << 18),
+ MMIO(display) + 0x721D0);
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D4) & 0xFFFFFC00) |
+ (calc_saturation & 0x3FF),
+ MMIO(display) + 0x721D4);
+
+ /*************************************************************************
+ * hue
+ *************************************************************************/
+ if (video_quality->hue == 0x8000) {
+ calc_hue = 0;
+ } else if (video_quality->hue < 0x8000) {
+ /* we have here a hue that is less than the middle value
+ * get 2's complement value decrease from 0x3ff to 0 */
+
+ calc_hue_tmp = 0x8000 - video_quality->hue;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ /* 2's complement negative value equal the corresponding
+ * positive value reverse every bits then plus 1
+ * and add signed bit, then the calc_hue is from -0x3ff to 0 */
+
+ calc_hue = (~calc_hue + 1) & 0x7ff;
+ } else {
+ /* we have here a saturation that is more than the middle value
+ * get 2's complement value increase from 0 to 0x3ff */
+
+ calc_hue_tmp = video_quality->hue - 0x8000;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ }
+ /* set 11bits hue value to register */
+ EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D4) & 0xF800FFFF) |
+ (calc_hue & 0x7FF) << 16,
+ MMIO(display) + 0x721D4);
+
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_tnc()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_tnc(
+ igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ igd_ovl_gamma_info_t * ovl_gamma)
+{
+ const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+ const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+ OVL2_REG_ADDR_GAMMA0,
+ OVL2_REG_ADDR_GAMMA1,
+ OVL2_REG_ADDR_GAMMA2,
+ OVL2_REG_ADDR_GAMMA3,
+ OVL2_REG_ADDR_GAMMA4,
+ OVL2_REG_ADDR_GAMMA5
+ };
+ const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+ };
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled or the display is an 8 bit mode
+ * (second overay can not support gamma in an 8 bit mode),
+ * set it to the default */
+ if (((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) ||
+ (PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* turn overlay off (TBD) */
+
+ /* program register */
+ EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+ /* turn overlay on (TBD) */
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#endif // End if caching is not enabled.
+
+static unsigned int convert_color_key_to_hw (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ case IGD_PF_ARGB8_INDEXED:
+ default:
+ output = input;
+ break;
+ case IGD_PF_RGB16_565:
+ output =
+ ((((input & 0xf800)>>11)<<3)<<16) |
+ ((((input & 0x07e0)>>5 )<<2)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ }
+
+ return output;
+}
+static unsigned int convert_color_key_to_mask (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ default:
+ output = 0x00ffffff;
+ break;
+ case IGD_PF_RGB16_565:
+ output = 0x00f8fcf8;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ output = 0x000000ff;
+ break;
+ }
+
+ return output;
+}
+
+/* Convert YUV to UVY for YUV pixel formats.
+ * Do not convert RGB pixel formats */
+static unsigned int yuv_to_uvy(
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ if (IGD_PF_TYPE(pf) & PF_TYPE_YUV) {
+ output =
+ ((input & 0x00ff0000) >> 16) |
+ ((input & 0x0000ff00) << 8) |
+ ((input & 0x000000ff) << 8);
+ } else {
+ output = input;
+ }
+
+ return output;
+}
+
+#ifndef OVL_TNC_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+
+static unsigned int micro_spritec_update_regs_tnc(
+ igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ unsigned int plane_control, orig_plane_control, plane_start;
+ unsigned int pipe_num;
+ unsigned int ckey_low, ckey_high;
+ int ret;
+
+
+ EMGD_TRACE_ENTER;
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ /* Turn off the plane control key enable and the second overlay
+ * control. */
+ plane_control = EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ orig_plane_control = plane_control;
+
+ if ((plane_control & (3<<22)) != 0) {
+ plane_control &= ~(3<<22);
+ }
+ if((plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) {
+ plane_control &= ~0x04000000;
+ }
+ if(plane_control != orig_plane_control) {
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+ }
+
+ /* Turn the overlay Off.
+ * Ensure we are using the correct Pipe. */
+ pipe_num = PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(pipe_num, MMIO(display) + MMIO_OFFSET_TNC2_CONTROL);
+ EMGD_WRITE32(0, MMIO(display) + MMIO_OFFSET_TNC2_LINEAR_OFF);
+ EMGD_WRITE32(0, MMIO(display) + MMIO_OFFSET_TNC2_SURF_ADDR);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Copy the information passed in to the HW overlay structure
+ *************************************************************************/
+ /* Zero the control, since they will be OR'ed in with data
+ * below */
+ spritec_regs_tnc->control = 0;
+
+ /* Interleaved/progressive and Odd/Even if interleaved */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ EMGD_ERROR("Overlay2 does not support Interleaved");
+ }
+
+ /* Dest rect information */
+ EMGD_WRITE32((dest_rect->y1<<16) | (dest_rect->x1),
+ MMIO(display) + 0x7218C);
+ EMGD_WRITE32(((dest_rect->y2 - dest_rect->y1 - 1)<<16) |
+ (dest_rect->x2 - dest_rect->x1 - 1),
+ MMIO(display) + 0x72190);
+
+ /* Src rect and surface information */
+ ret = micro_spritec_update_src_tnc(display, spritec_regs_tnc, src_surf, src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ return ret;
+ }
+
+ /* Color control information */
+ if (!(flags & IGD_OVL_OSD_ON_SPRITEC)) {
+ ret = micro_spritec_update_video_quality_tnc(display, src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 video quality failed");
+ return ret;
+ }
+ ret = micro_spritec_update_gamma_tnc(display, spritec_regs_tnc, &ovl_info->gamma);
+ if (ret) {
+ EMGD_ERROR("Overlay2 gamma failed");
+ return ret;
+ }
+ }
+
+ /* Destination color key */
+ plane_control = EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ orig_plane_control = plane_control;
+
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the different
+ * pixel formats */
+ EMGD_WRITE32(convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format, ovl_info->color_key.dest),
+ MMIO(display) + PLANE(display)->plane_reg +
+ MMIO_OFFSET_TNC2_COLORKEY_HW);
+ EMGD_WRITE32(convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format, ovl_info->color_key.dest),
+ MMIO(display) + PLANE(display)->plane_reg +
+ MMIO_OFFSET_TNC2_COLORKEY_MASK);
+
+ /* Both the plane control key enable and the second overlay
+ * control order must be enabled to turn on destination color
+ * key. Also rewrite the plane_start which is the trigger for
+ * Plane A/B */
+ plane_control |= (3<<22);
+
+ if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+ /* Sprite C should be below plane and above first overlay */
+ spritec_regs_tnc->control |= 1;
+ } else {
+ /* Sprite C should be on the bottom of the Z order. */
+ spritec_regs_tnc->control |= 4;
+ }
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ plane_control &= ~(3<<22);
+ }
+
+ if(ovl_info->color_key.flags & IGD_OVL_DST_BLEND_ENABLE) {
+ /*
+ * If Overlay + FB Blend is requested and the FB is xRGB
+ * turn on the ARGB format.
+ */
+ if((plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_RGB_8888) {
+ plane_control |= DSPxCNTR_ARGB_8888;
+ }
+
+ /* Dest Blend requires Plane C on the bottom of the Z order */
+ spritec_regs_tnc->control |= 4;
+ } else {
+ if((plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) {
+ plane_control &= ~0x04000000;
+ }
+ }
+
+ if(plane_control != orig_plane_control) {
+ EMGD_WRITE32(plane_control, MMIO(display) + PLANE(display)->plane_reg);
+ plane_start = EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+
+ /* trigger registers must be updated using a command packet */
+ ret = micro_spritec_send_instr_tnc(display, PLANE(display)->plane_reg +
+ 0x1c, plane_start);
+
+ /* Note: On a 915GM (maybe other platforms as well), the dest
+ * color key is not always enabled when the plane A/B and
+ * plane C are both modified in the same vblank. So, ensure
+ * they occur on a different vblank. This should be fine,
+ * since this will only occur the first time when enabling
+ * the dest color key. */
+ display->context->dispatch.wait_vblank((igd_display_h)display);
+
+
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+
+ ckey_high = convert_color_key_to_hw(src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ckey_high = yuv_to_uvy(src_surf->pixel_format,
+ ckey_high);
+
+ ckey_low = convert_color_key_to_hw(src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ckey_low = yuv_to_uvy(src_surf->pixel_format,
+ ckey_low);
+
+ EMGD_WRITE32(ckey_low, MMIO(display) + 0x72194);
+ EMGD_WRITE32(ckey_high, MMIO(display) + 0x721a0);
+ EMGD_WRITE32(7, MMIO(display) + 0x72198);
+ spritec_regs_tnc->control |= (1<<22);
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ EMGD_WRITE32(0, MMIO(display) + 0x72198);
+ }
+
+ /* General overlay information. Turn the second overlay on.
+ * The trigger register is the start register which causes the
+ * overlay to update. The trigger register is written in send_instr */
+ spritec_regs_tnc->control |= (1<<31);
+ spritec_regs_tnc->control |= PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(spritec_regs_tnc->control,
+ MMIO(display) + MMIO_OFFSET_TNC2_CONTROL);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#else /* OVL_TNC_CACHE_QUICK_SWAP is enabled. */
+
+/* Atom E6xx overlay cache structure */
+static ovl_tnc_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_ptr_tnc()
+ *
+ * Description:
+ * This function updates the source offset
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_ptr_tnc(igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format) / 8;
+
+ /* src surface */
+ ovl_cache.ovl2_regs.start = src_surf->offset;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_tnc()
+ *
+ * Description:
+ * This function updates the source pitch and pixel format
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ EMGD_TRACE_ENTER;
+
+ ovl_cache.ovl2_regs.linear_offset =
+ (src_rect->y1 * src_surf->pitch) +
+ (src_rect->x1 * (IGD_PF_BPP(src_surf->pixel_format)/8));
+ ovl_cache.ovl2_regs.pitch = src_surf->pitch;
+ ovl_cache.ovl2_regs.tiled_offset = 0;
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+ break;
+ case IGD_PF_ARGB32_8888:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_ARGB_8888;
+ break;
+ case IGD_PF_xRGB32_8888:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_565;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ ovl_cache.ovl2_regs.control |= (1<<19);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_video_quality_tnc()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+ unsigned int calc_hue_tmp = 0;
+ unsigned int calc_hue = 0;
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+ if (video_quality->hue != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+ ovl_cache.ovl2_regs.cont_bright = OVL2_RGB_COLOR_DEF_CONT_BRGHT;
+ ovl_cache.ovl2_regs.satn_hue = OVL2_RGB_COLOR_DEF_SATN_HUE;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ ovl_cache.ovl2_regs.cont_bright =
+ (ovl_cache.ovl2_regs.cont_bright & 0xFFFFFF00) |
+ (calc_brightness & 0xFF);
+
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ ovl_cache.ovl2_regs.cont_bright =
+ (ovl_cache.ovl2_regs.cont_bright & 0xF803FFFF ) |
+ ((calc_contrast & 0x1FF) << 18);
+
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ ovl_cache.ovl2_regs.satn_hue =
+ (ovl_cache.ovl2_regs.satn_hue & 0xFFFFFC00 ) |
+ (calc_saturation & 0x3FF);
+
+ /*************************************************************************
+ * hue
+ *************************************************************************/
+ if (video_quality->hue == 0x8000) {
+ calc_hue = 0;
+ } else if (video_quality->hue < 0x8000) {
+ /* we have here a hue that is less than the middle value
+ * get 2's complement value decrease from 0x3ff to 0 */
+
+ calc_hue_tmp = 0x8000 - video_quality->hue;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ /* 2's complement negative value equal the corresponding
+ * positive value reverse every bits then plus 1
+ * and add signed bit, then the calc_hue is from -0x3ff to 0 */
+
+ calc_hue = (~calc_hue + 1) & 0x7ff;
+ } else {
+ /* we have here a saturation that is more than the middle value
+ * get 2's complement value increase from 0 to 0x3ff */
+
+ calc_hue_tmp = video_quality->hue - 0x8000;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ }
+
+ /* set 11bits hue value to register */
+ ovl_cache.ovl2_regs.satn_hue =
+ (ovl_cache.ovl2_regs.satn_hue & 0xF800FFFF ) |
+ ((calc_hue & 0x7FF) << 16);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+static const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+static const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+ OVL2_REG_ADDR_GAMMA0,
+ OVL2_REG_ADDR_GAMMA1,
+ OVL2_REG_ADDR_GAMMA2,
+ OVL2_REG_ADDR_GAMMA3,
+ OVL2_REG_ADDR_GAMMA4,
+ OVL2_REG_ADDR_GAMMA5
+};
+static const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+};
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_tnc()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_tnc(
+ igd_display_context_t *display,
+ igd_ovl_gamma_info_t *ovl_gamma)
+{
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled or the display is an 8 bit mode
+ * (second overay can not support gamma in an 8 bit mode),
+ * set it to the default */
+ if (((ovl_gamma->flags&IGD_OVL_GAMMA_ENABLE)==IGD_OVL_GAMMA_DISABLE) ||
+ (PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ ovl_cache.ovl2_regs.gamma_regs[i] = gamma_def[i];
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* program register */
+ ovl_cache.ovl2_regs.gamma_regs[i] = gamma_reg;
+
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_disable_ovl_tnc()
+ *
+ * Description:
+ * Write the registers needed to turn off the overlay.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_disable_ovl_tnc(
+ igd_display_context_t *display )
+{
+ unsigned int pipe_num;
+ unsigned int plane_control, orig_plane_control, plane_start;
+
+ EMGD_TRACE_ENTER;
+
+ /* Turn off the plane control key enable and the second overlay
+ * control. */
+ plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ orig_plane_control = plane_control;
+
+ if ((plane_control & (3<<22)) != 0) {
+ plane_control &= ~(3<<22);
+ }
+ if(((plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) &&
+ (!display->context->mod_dispatch.fb_blend_ovl_override)) {
+ /* Preserve the state of the register if FB blend +
+ * Ovl override is invoked */
+ plane_control &= ~0x04000000;
+ }
+ if(plane_control != orig_plane_control) {
+ EMGD_WRITE32(plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+ plane_start = EMGD_READ32(
+ MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+ }
+
+ /* Turn the overlay Off.
+ * Ensure we are using the correct Pipe. */
+ pipe_num = PIPE(display)->pipe_num ?
+ (1<<24)/*Pipe B*/ :
+ (0<<24)/*Pipe A*/;
+ EMGD_WRITE32(pipe_num, MMIO(display) + MMIO_OFFSET_TNC2_CONTROL);
+ EMGD_WRITE32(0, MMIO(display) + MMIO_OFFSET_TNC2_SURF_ADDR);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_clear_cache_tnc()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_clear_cache_tnc(
+ igd_display_context_t *display,
+ unsigned int flags)
+{
+ /* Force every cache check to miss */
+ OS_MEMSET(&ovl_cache, 0, sizeof(ovl_tnc_cache_t));
+
+ /* We just set our cached flags to 0, which might accidently
+ * match up with "OFF" for some important incoming flag
+ * bits, causing us to think we already handled them when
+ * we didn't. So set our cached flags to the exact
+ * opposite of the incoming flags, which will force
+ * us to test and handle every single bit, regardless
+ * of whether it is on or off. */
+ ovl_cache.flags = ~flags;
+
+ /* init our cached registers */
+ ovl_cache.ovl2_regs.plane_control =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+ ovl_cache.ovl2_regs.plane_start =
+ EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+
+ /* initialization complete */
+ ovl_cache_needs_init = FALSE;
+
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_colorkey_tnc()
+ *
+ * Description:
+ * This function sets the colorkey values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static void micro_spritec_update_colorkey_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_ovl_info_t *ovl_info)
+{
+ unsigned int ckey_low, ckey_high;
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the
+ * different pixel formats */
+ ovl_cache.ovl2_regs.colorkey_hw =
+ convert_color_key_to_hw
+ (PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+
+ ovl_cache.ovl2_regs.colorkey_mask =
+ convert_color_key_to_mask
+ (PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ /*
+ * Both the plane control key enable and the second
+ * overlay control order must be enabled to turn on
+ * destination color key. Also rewrite the
+ * plane_start which is the trigger for Plane A/B
+ */
+ ovl_cache.ovl2_regs.plane_control |= (3<<22);
+
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ ovl_cache.ovl2_regs.plane_control &= ~(3<<22);
+ }
+
+ if(ovl_info->color_key.flags & IGD_OVL_DST_BLEND_ENABLE) {
+ /*
+ * If Overlay + FB Blend is requested and the FB is xRGB
+ * turn on the ARGB format.
+ */
+ if((ovl_cache.ovl2_regs.plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_RGB_8888) {
+ ovl_cache.ovl2_regs.plane_control |= DSPxCNTR_ARGB_8888;
+ }
+ } else {
+ if(((ovl_cache.ovl2_regs.plane_control & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) &&
+ (!display->context->mod_dispatch.fb_blend_ovl_override)){
+ /* Preserve the state of the register if FB blend +
+ * Ovl override is invoked */
+ ovl_cache.ovl2_regs.plane_control &= ~0x04000000;
+ }
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+
+ ckey_high = convert_color_key_to_hw
+ (src_surf->pixel_format,
+ ovl_info->color_key.src_hi);
+ ckey_high = yuv_to_uvy(src_surf->pixel_format,
+ ckey_high);
+
+ ckey_low = convert_color_key_to_hw
+ (src_surf->pixel_format,
+ ovl_info->color_key.src_lo);
+ ckey_low = yuv_to_uvy(src_surf->pixel_format,
+ ckey_low);
+
+ ovl_cache.ovl2_regs.ckey_low = ckey_low;
+ ovl_cache.ovl2_regs.ckey_high = ckey_high;
+ ovl_cache.ovl2_regs.ckey_enable = 7;
+ ovl_cache.ovl2_regs.control |= (1<<22);
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ ovl_cache.ovl2_regs.ckey_enable = 0;
+ }
+
+}
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_write_cache_tnc()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_write_cache_tnc(
+ igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ igd_ovl_info_t *ovl_info,
+ int cache_changed)
+{
+ int i;
+
+ /*
+ * Now write all the changed registers to the HW
+ * TODO: Or should we write all the registers, regardless of
+ * if they have changed?
+ * TODO: It may be beneficial to turn off overlay while
+ * updateing the regs?
+ */
+
+
+ /* Write dest rect information */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_DEST) {
+ EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_x1y1,
+ MMIO(display) + MMIO_OFFSET_TNC2_DEST_RECT_X1Y1);
+ EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_w_h,
+ MMIO(display) + MMIO_OFFSET_TNC2_DEST_RECT_W_H);
+ }
+
+
+ /* Write source information */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_SURF |
+ IGD_OVL_TNC_UPDATE_SRC ) ) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.linear_offset,
+ MMIO(display) + MMIO_OFFSET_TNC2_LINEAR_OFF);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.pitch,
+ MMIO(display) + MMIO_OFFSET_TNC2_PITCH);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.tiled_offset,
+ MMIO(display) + MMIO_OFFSET_TNC2_DSPC_TILE_OFF);
+ }
+
+
+ /* write the quality information */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_VQ |
+ IGD_OVL_TNC_UPDATE_SURF ) ) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.cont_bright,
+ MMIO(display) + MMIO_OFFSET_TNC2_CONT_BRIGHT);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.satn_hue,
+ MMIO(display) + MMIO_OFFSET_TNC2_SATN_HUE);
+ }
+
+ /* Write the gamma */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_GAMMA) {
+ for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(ovl_cache.ovl2_regs.gamma_regs[i],
+ MMIO(display) + gamma_reg_offset[i]);
+ }
+ }
+
+ /* Write the colorkey data */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_COLORKEY) {
+
+ /* Dest color key */
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+ /* Write the regs needed to turn it on */
+ EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_hw,
+ MMIO(display) +
+ PLANE(display)->plane_reg +
+ MMIO_OFFSET_TNC2_COLORKEY_HW);
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_mask,
+ MMIO(display) +
+ PLANE(display)->plane_reg +
+ MMIO_OFFSET_TNC2_COLORKEY_MASK);
+ }
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.plane_control,
+ MMIO(display) + PLANE(display)->plane_reg);
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.plane_start,
+ MMIO(display) + PLANE(display)->plane_reg + 0x1c);
+
+ /*
+ * Note: On a 915GM (maybe other platforms as well),
+ * the dest color key is not always enabled when the
+ * plane A/B and plane C are both modified in the
+ * same vblank. So, ensure they occur on a different
+ * vblank. This should be fine, since this will only
+ * occur the first time when enabling the dest color
+ * key.
+ */
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ display->context->dispatch.
+ wait_vblank((igd_display_h)display);
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_low,
+ MMIO(display) + MMIO_OFFSET_TNC2_CKEY_LOW);
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_high,
+ MMIO(display) + MMIO_OFFSET_TNC2_CKEY_HIGH);
+ }
+ EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_enable,
+ MMIO(display) + MMIO_OFFSET_TNC2_CKEY_ENABLE);
+ }
+
+ /* Write the control register, but not the start register.
+ The trigger register is the start register
+ which causes the overlay to update. The trigger
+ register is written in send_instr */
+
+ EMGD_WRITE32(ovl_cache.ovl2_regs.control,
+ MMIO(display) + MMIO_OFFSET_TNC2_CONTROL);
+
+ spritec_regs_tnc->start = ovl_cache.ovl2_regs.start;
+ spritec_regs_tnc->control = ovl_cache.ovl2_regs.control;
+
+}
+
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_regs_tnc()
+ *
+ * Description:
+ * Examine the incoming overlay parameters, and update the overlay hardware
+ * regs according to what changed.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_update_regs_tnc(
+ igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ // unsigned int ckey_low, ckey_high;
+ // int i,
+ int ret;
+ int cache_changed;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* Fast path for turning off overlay. No need for cache */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ ret = micro_spritec_disable_ovl_tnc(display);
+
+ /* Reset the cache */
+ ovl_cache_needs_init = TRUE;
+
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+
+ /* Init the cache if needed */
+ if ((ovl_cache_needs_init) || (ovl_context->ovl_display_swapped)){
+ micro_spritec_clear_cache_tnc(display, flags);
+ ovl_context->ovl_display_swapped = 0;
+ }
+
+ /* See what has changed in the cache */
+ cache_changed = get_cache_changes_tnc (
+ src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags,
+ &ovl_cache);
+
+ /*
+ * Perhaps the biggest challenge of caching the overlay
+ * state is what to do with the command and config regs.
+ * Normally we would clear command and config to 0 here,
+ * and let the update process set only the bits that are
+ * needed. But doing this would invalidate our cache.
+ * Instead we are relying on the above call to
+ * get_cache_changes() to clear those bits in command
+ * and config that will be changing
+ */
+
+
+ /* Normally we would set interleave parameters here,
+ * but the secondary overlay does not support interleave.*/
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ EMGD_ERROR("Overlay2 does not support Interleaved");
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Has our destination rectangle changed? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_DEST) {
+ ovl_cache.ovl2_regs.dest_rect_x1y1 =
+ ( (dest_rect->y1 << 16) | dest_rect->x1 );
+ ovl_cache.ovl2_regs.dest_rect_w_h =
+ ( (dest_rect->y2 - dest_rect->y1 - 1) << 16) |
+ (dest_rect->x2 - dest_rect->x1 - 1) ;
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Always update the source pointers every frame. */
+ ret = micro_spritec_update_src_ptr_tnc(src_surf,
+ src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+
+
+ /* ----------------------------------------------------------*/
+ /* Did either the Src rect or surface change? */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_SURF |
+ IGD_OVL_TNC_UPDATE_SRC ) ) {
+ ret = micro_spritec_update_src_tnc(display,
+ src_surf,
+ src_rect);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 updating src failed");
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the quality information change? */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_VQ |
+ IGD_OVL_TNC_UPDATE_SURF ) ) {
+ ret = micro_spritec_update_video_quality_tnc(display,
+ src_surf, &ovl_info->video_quality);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay2 video quality failed");
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the gamma change? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_GAMMA) {
+ ret = micro_spritec_update_gamma_tnc(display, &ovl_info->gamma);
+ if (ret) {
+ EMGD_ERROR("Overlay2 gamma failed");
+ EMGD_TRACE_EXIT;
+ return ret;
+ }
+
+ }
+
+ /* ----------------------------------------------------------*/
+ /* Did the color key change? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_COLORKEY) {
+ micro_spritec_update_colorkey_tnc(display,
+ src_surf,
+ ovl_info);
+ }
+
+
+ if ((ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) ||
+ (ovl_info->color_key.flags & IGD_OVL_DST_BLEND_ENABLE)) {
+ if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+ ovl_cache.ovl2_regs.control |= 1;
+ } else {
+ /* Sprite C should be on the bottom of the Z order.
+ * Plane B should be above Sprite C */
+ ovl_cache.ovl2_regs.control |= 4;
+ }
+ }
+
+ /* General overlay information. Turn the second overlay on. */
+ ovl_cache.ovl2_regs.control |= (1<<31);
+ if (PIPE(display)->pipe_num == 1) {
+ ovl_cache.ovl2_regs.control |= (1<<24);/*Pipe B*/
+ } else {
+ ovl_cache.ovl2_regs.control &= ~(1<<24);/*Pipe A*/
+ }
+
+ /*
+ * Now write all the changes to the part
+ */
+ micro_spritec_write_cache_tnc(display,
+ spritec_regs_tnc,
+ ovl_info,
+ cache_changed);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#endif
+
+unsigned int micro_spritec_send_instr_tnc(
+ igd_display_context_t *display,
+ unsigned long regs,
+ unsigned long value)
+{
+ EMGD_TRACE_ENTER;
+
+ /* Send a load register instruction to write the Plane C sprite address
+ * which is the trigger register.
+ * This is an instruction, so it happens after blend, and since it
+ * is an instruction, we do not have to poll waiting for it. */
+
+ EMGD_WRITE32(value, MMIO(display) + regs);
+
+ ovl_context->sync2 = 0;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int micro_prepare_ovl2_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ unsigned int flags)
+{
+ int ret = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Check to ensure the overlay can be used given the current mode as
+ * well as what the IAL is asking for. If not return an error. */
+
+ if( (OVL2_CHECK_TNC_RET(ret,display, src_surf, src_rect,
+ dest_rect, ovl_info,flags)) )
+ {
+ if (ret) {
+ printk(KERN_ERR "Overlay2 Check failed\n");
+ return ret;
+ }
+ }
+
+ /* Check if last flip is still pending.
+ * This is necessary for the following reasons:
+ * - If the previous instructions have not been processed, then the
+ * spritec_regs_tnc is still in use and can not be overwritten.
+ */
+ if( (QUERY_OVL2_TNC_RET(ret,(igd_display_h)display,
+ IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) )
+ {
+ //printk(KERN_ERR "QEURY_OVL2_TNC_RET failedi\n");
+ if ((FALSE == ret) &&
+ (flags & IGD_OVL_ALTER_ON)) {
+ /* Only return an error if the overlay is on. If turning it off,
+ * allow it to continue, since something may have failed and we
+ * should try our best to turn the overlay off. */
+ return -IGD_ERROR_HWERROR;
+ }
+ }
+ /* Update all Overlay Update Registers */
+ ret = micro_spritec_update_regs_tnc(display, spritec_regs_tnc,
+ src_surf, src_rect, dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ printk(KERN_ERR "Sprite C update Registers failed");
+ return ret;
+ }
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+int micro_alter_ovl2_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl2_reg_tnc_t spritec_regs_tnc;
+ int ret=0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Initialize structure so compilers don't complain */
+ OS_MEMSET(&spritec_regs_tnc, 0, sizeof(ovl2_reg_tnc_t));
+
+ if (micro_prepare_ovl2_tnc(display, src_surf, src_rect, dest_rect,
+ ovl_info, &spritec_regs_tnc, flags)) {
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Directlt write the register to update 2nd overlay */
+#ifdef OVL_TNC_CACHE_QUICK_SWAP
+ ret = micro_spritec_send_instr_tnc(display,
+ MMIO_OFFSET_TNC2_SURF_ADDR,
+ ovl_cache.ovl2_regs.start);
+#else
+ ret = micro_spritec_send_instr_tnc(display,
+ MMIO_OFFSET_TNC2_SURF_ADDR,
+ spritec_regs_tnc.start);
+#endif
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
new file mode 100644
index 0000000..9f2ac10
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_regs_tnc.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for napa overlay engine. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_REGS_TNC_H
+#define _OVL2_REGS_TNC_H
+/* Second Overlay Structure.
+ * These registers are the trigger registers and should be written
+ * last. */
+typedef struct _ovl2_reg_tnc{
+ unsigned int control;
+ unsigned int start;
+} ovl2_reg_tnc_t;
+
+/* Color Correction */
+#define OVL2_RGB_COLOR_DEF_CONT_BRGHT 0x1000000
+#define OVL2_RGB_COLOR_DEF_SATN_HUE 0x0000080
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL2_CMD_YVYU 0x00020000
+#define OVL2_CMD_UYVY 0x00010000
+#define OVL2_CMD_VYUY 0x00030000
+
+/* Source Format */
+#define OVL2_CMD_ARGB_8888 0x1C000000
+#define OVL2_CMD_RGB_8888 0x18000000
+#define OVL2_CMD_RGB_565 0x14000000
+#define OVL2_CMD_RGB_555 0x10000000
+#define OVL2_CMD_RGB_8 0x08000000
+#define OVL2_CMD_YUV_422 0x00000000 /*packed YUV422*/
+#define OVL2_CMD_SRC_FMT_MASK 0x3C000000 /*mask for above*/
+
+#define OVL2_REG_ADDR_GAMMA5 0x721E0
+#define OVL2_REG_ADDR_GAMMA4 0x721E4
+#define OVL2_REG_ADDR_GAMMA3 0x721E8
+#define OVL2_REG_ADDR_GAMMA2 0x721EC
+#define OVL2_REG_ADDR_GAMMA1 0x721F0
+#define OVL2_REG_ADDR_GAMMA0 0x721F4
+#define OVL2_TOTAL_GAMMA_REG 6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+ than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV 0x43//4a
+#define MID_SATURATION_YUV 0x91//92
+#define MID_BRIGHTNESS_YUV -5
+#endif /* _OVL2_REGS_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
new file mode 100644
index 0000000..563dcda
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
@@ -0,0 +1,478 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_tnc.c
+ * $Revision: 1.23 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the second
+ * overlay with the bits to properly configure the overlay
+ * Also includes functions to execute the second overlay flip
+ * instruction, and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips second overlay
+ * capabilities
+ *-----------------------------------------------------------------------------
+ */
+/* Referenced from Napa. Need change later */
+
+#define MODULE_NAME hal.overlay
+
+#include <io.h>
+#include <memory.h>
+#include <intelpci.h>
+#include <math_fix.h>
+
+
+#include <igd_mode.h>
+
+#include <utils.h>
+#include <general.h>
+#include <context.h>
+#include <rb.h>
+#include <mode.h>
+
+#include <tnc/instr.h>
+#include <tnc/regs.h>
+#include <tnc/cmd.h>
+#include <tnc/context.h>
+
+#include "ovl2_tnc.h"
+#include "ovl2_regs_tnc.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+
+extern unsigned long sprite_pixel_formats_tnc[];
+extern int micro_prepare_ovl2_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ unsigned int flags);
+
+/*----------------------------------------------------------------------
+ * Function: ovl2_check_pf_tnc()
+ * Parameters: unsigned int requested_pixel_format -
+ * according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ * TRUE on Success
+ * FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl2_check_pf_tnc(
+ igd_display_context_t *display,
+ unsigned int requested_pixel_format)
+{
+ unsigned long *spr_pf = sprite_pixel_formats_tnc;
+ int temp_loop = 0;
+
+ while(spr_pf[temp_loop]) {
+ if(spr_pf[temp_loop] == requested_pixel_format) {
+ return TRUE;
+ }
+ ++temp_loop;
+ }
+
+ return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+unsigned int ovl2_check_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_timing_info_t *timing;
+ unsigned int min_w, min_h;
+
+ EMGD_TRACE_ENTER;
+
+ if (!display){
+ EMGD_ERROR_EXIT("display is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!PIPE(display)){
+ EMGD_ERROR_EXIT("PIPE(display) is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ timing = PIPE(display)->timing;
+
+ /* The following parameters are only valid if the overlay is on, so
+ * return success if the overlay is being turned off. */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ timing = PIPE(display)->timing;
+
+ if(!timing) {
+ EMGD_ERROR_EXIT("timing is null\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*************************************************************************
+ * Ensure the framebuffer dotclock does not exceed the board SKU
+ * max dotclock
+ *************************************************************************/
+ /* Make it chipset-specific */
+ /* DCT-PC99TA crashes with dotclock > 300MHz */
+ if(timing->dclk >= 340000){
+ EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the overlay surface is ok and can be properly displayed.
+ * This ensures the following is valid:
+ * - Ensure x1, x2, y1, y2 are pixel aligned
+ * - 2 pixels or greater in width and height
+ * - Pixel format is supported by the overlay
+ * - Pitch is <= 16KB
+ * - Based on the pixel format, the width is supported
+ *************************************************************************/
+ if (!src_surf){
+ EMGD_ERROR_EXIT("src_surf is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!src_rect){
+ EMGD_ERROR_EXIT("src_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ /* Get the minimum size of 1 pixel in width and height for y, u, and v.
+ */
+ min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+ min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+ if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+ ((src_rect->y2 - src_rect->y1) < min_h*2)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 source width or height is < 2 pixels (%dx%d)\n",
+ src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (FALSE == ovl2_check_pf_tnc(display, src_surf->pixel_format)) {
+ EMGD_ERROR_EXIT("Overlay2 source pixel format unsupported (pf:0x%lx)",
+ src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ if (src_surf->pitch > 16384) {
+ EMGD_ERROR_EXIT("Overlay2 source pitch (%d) > 16KB",
+ src_surf->pitch);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the location on the framebuffer is ok and can be properly
+ * displayed
+ * This ensures the following is valid:
+ * - Greater than 1 pixel width and height
+ * - Will be displayed on screen (not panned off)
+ *************************************************************************/
+ if (!dest_rect){
+ EMGD_ERROR_EXIT("dest_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+ ((dest_rect->y2 - dest_rect->y1) <= 1)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 dest width or height is single pixel (%dx%d)\n",
+ dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((dest_rect->x1 >= timing->width) ||
+ (dest_rect->y1 >= timing->height)) {
+ EMGD_ERROR_EXIT(
+ "Overlay2 dest is panned off the screen (%d,%d)\n",
+ dest_rect->x1, dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+unsigned int ovl2_send_instr_tnc(
+ igd_display_context_t *display,
+ ovl2_reg_tnc_t *spritec_regs_tnc,
+ unsigned int flags)
+{
+ unsigned char *mmio = MMIO(display);
+ unsigned long tmp, pipe_reg, pipe_num;
+ inter_module_dispatch_t *md;
+ platform_context_tnc_t * platform;
+
+
+ EMGD_TRACE_ENTER;
+
+ /* We dont need the CMD_WAIT_OVL2_TNC instruction coz
+ * our alter_ovl code already querried status
+ * for last flip completion before getting here. See
+ * micro_prepare_ovl2_tnc called by alter_ovl2_tnc.
+ * It calls query overlay before the next flip
+ */
+
+ /*If Overlay+FB Blend is requested and the FB is xRGB
+ *turn on the ARGB format. */
+ if(ovl_context->fb_blend_ovl) {
+ if((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x18000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg);
+ EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
+ }
+ } else {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x1c000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg);
+ EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
+ OS_SLEEP(100);
+ }
+ }
+ }
+
+ /* Send a load register instruction to write the Plane C sprite address
+ * which is the trigger register.
+ * This is an instruction, so it happens after blend, and since it
+ * is an instruction, we do not have to poll waiting for it. */
+ EMGD_WRITE32(spritec_regs_tnc->start, mmio + 0x7219C);
+
+ /* Since the ISR bit 0x100 actually doesnt work,
+ * we need to setup a trigger for a VBLANK event
+ * on Pipe-B to guarantee that the Sprite-C had
+ * actually completed its last flip.
+ * (ISR bit was tested on Poulsbo D2 by capturing
+ * timestamps of quick successive alter_overlays..
+ * checked ISR bit directly after the write to Sprite
+ * C Address register in process_vqueue handling..
+ * the ISR bit never changed
+ */
+
+ md = &display->context->mod_dispatch;
+ platform = (platform_context_tnc_t *)display->context->
+ platform_context;
+
+ pipe_num = PIPE(display)->pipe_num;
+
+ if(pipe_num){
+ pipe_reg = PIPEB_STAT;
+ } else {
+ pipe_reg = PIPEA_STAT;
+ }
+
+ if(md && md->set_flip_pending){
+ OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+ md->set_flip_pending(MMIO(display), pipe_reg);
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ }
+
+ ovl_context->sync2 = WAIT_FOR_FLIP;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+int alter_ovl2_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl2_reg_tnc_t spritec_regs_tnc;
+ int ret=0;
+
+ EMGD_TRACE_ENTER;
+
+ /* Initialize structure so compilers don't complain */
+ OS_MEMSET(&spritec_regs_tnc, 0, sizeof(ovl2_reg_tnc_t));
+
+ if (micro_prepare_ovl2_tnc(display, src_surf, src_rect, dest_rect,
+ ovl_info, &spritec_regs_tnc, flags)) {
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Send the instructions to the command queue */
+ ret = ovl2_send_instr_tnc(display, &spritec_regs_tnc, flags);
+ EMGD_DEBUG("Sprite C= %s",flags & IGD_OVL_ALTER_ON?"ON":"OFF");
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+int query_ovl2_tnc(igd_display_h display_h,
+ unsigned int flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_h;
+ inter_module_dispatch_t *md;
+ platform_context_tnc_t * platform;
+ os_alarm_t timeout;
+ int ret;
+ unsigned long pipe_reg, pipe_num;
+
+ EMGD_TRACE_ENTER;
+
+ switch (flags) {
+ case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+ /* This is the second overlay, so HW overlay is not supported */
+ break;
+
+ case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+ /* If there no sync to wait on, then the last flip is done, and the
+ * Register Update has occured, simply return TRUE (Flip done).
+ */
+ if (!ovl_context->sync2) {
+ EMGD_DEBUG("Overlay already synced");
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+
+ /* According to the PBL B-spec, there doesnt seem to exist any bit
+ * for Sprite C Flip-Pending status. Testing 0x20AC in code during
+ * virt queue's REG write shows nothing changed for Bit8. Thus, we
+ * are using state of the VBLANK ISR bit as ovl2 flip status.
+ * Assumption is that if were running 2nd overlay, its either clone
+ * display or VEXT in WinCE. In either case, were not doing full screen
+ * FB flipping, so this check should be 'statefully' accurate
+ */
+ md = &display->context->mod_dispatch;
+ platform = (platform_context_tnc_t *)display->context->
+ platform_context;
+
+ pipe_num = PIPE(display)->pipe_num;
+ if(pipe_num){
+ pipe_reg = PIPEB_STAT;
+ } else {
+ pipe_reg = PIPEA_STAT;
+ }
+
+ if(md && md->check_flip_pending){
+ ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+ if(md->check_flip_pending(MMIO(display), pipe_reg)){
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ EMGD_DEBUG("Overlay2 Sync done but Flip not done");
+ return FALSE;
+ }
+ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+ }
+
+ /* Now that we know the last flip is done and the register update is
+ * complete, set the sync to 0 and return TRUE (Flip done). */
+ ovl_context->sync2 = FLIP_DONE;
+ break;
+ case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+ /* Wait for 200 milliseconds for the last flip to complete. If not
+ * done in that time, there is likely a hardware problem so return
+ * FALSE. */
+ timeout = OS_SET_ALARM(200);
+ do {
+ if (TRUE ==
+ query_ovl2_tnc(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+ } while (!OS_TEST_ALARM(timeout));
+ EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+ return FALSE;
+ break;
+ case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+ return TRUE;
+ break;
+ case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+ return TRUE;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+
+
+int query_max_size_ovl2_tnc(
+ igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height)
+{
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: Should this be size of FB? */
+ *max_width = 2048;
+ *max_height = 2048;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
new file mode 100644
index 0000000..300e826
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_tnc.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for napa overlay engine. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized structures and functions internal to
+ * the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_TNC_H
+#define _OVL2_TNC_H
+extern int blend2_surf_needed_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags,
+ igd_surface_t *blend_surf,
+ igd_rect_t *blend_rect);
+extern int alter_ovl2_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+extern int query_ovl2_tnc(igd_display_h display_h,
+ unsigned int flags);
+extern int query_max_size_ovl2_tnc(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+#endif /* _OVL2_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
new file mode 100644
index 0000000..06e85f7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
@@ -0,0 +1,190 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_regs_tnc.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay. It should be not be
+ * by any other module besides the overlay module itself. It contains the
+ * neccessary hardware virtualized register dependant information including
+ * values, structures and addresses specifically for the Napa core
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef OVL_REGS_TNC_H_
+#define OVL_REGS_TNC_H_
+
+/* Overlay Update Register Image Structure.*/
+typedef struct _ovl_reg_image_tnc{
+
+ volatile unsigned int buffer0_yrgb_loff;
+ volatile unsigned int buffer1_yrgb_loff;
+ volatile unsigned int buffer0_u_loff;
+ volatile unsigned int buffer0_v_loff;
+ volatile unsigned int buffer1_u_loff;
+ volatile unsigned int buffer1_v_loff;
+ volatile unsigned short yrgb_stride;
+ volatile unsigned short uv_stride;
+ volatile unsigned short yrgb_vert_phase_field0;
+ volatile unsigned short yrgb_vert_phase_field1;
+ volatile unsigned short uv_vert_phase_field0;
+ volatile unsigned short uv_vert_phase_field1;
+ volatile unsigned short yrgb_hphase;
+ volatile unsigned short uv_hphase;
+ volatile unsigned int init_phase_shift;
+ volatile unsigned short dest_pos_x_left;
+ volatile unsigned short dest_pos_y_top;
+ volatile unsigned short dest_width_x;
+ volatile unsigned short dest_height_y;
+ volatile unsigned short source_yrgb_width;
+ volatile unsigned short source_uv_width;
+ volatile unsigned short source_yrgb_width_swords;
+ volatile unsigned short source_uv_width_swords;
+ volatile unsigned short source_yrgb_height;
+ volatile unsigned short source_uv_height;
+ volatile unsigned int yrgb_scale;
+ volatile unsigned int uv_scale;
+ volatile unsigned int col_ctl_brt_con;
+ volatile unsigned int col_ctl_sat_hue;
+ volatile unsigned int dest_ckey_val;
+ volatile unsigned int dest_ckey_mask;
+ volatile unsigned int source_ckey_high;
+ volatile unsigned int source_ckey_low;
+ volatile unsigned int source_ckey_mask;
+ volatile unsigned int config;
+ volatile unsigned int command;
+ volatile unsigned int reserved1;
+ volatile unsigned int buffer0_yrgb_start;
+ volatile unsigned int buffer1_yrgb_start;
+ volatile unsigned int buffer0_u_start;
+ volatile unsigned int buffer0_v_start;
+ volatile unsigned int buffer1_u_start;
+ volatile unsigned int buffer1_v_start;
+ volatile unsigned short buffer0_yrgb_x_toff;
+ volatile unsigned short buffer0_yrgb_y_toff;
+ volatile unsigned short buffer1_yrgb_x_toff;
+ volatile unsigned short buffer1_yrgb_y_toff;
+ volatile unsigned short buffer0_u_x_toff;
+ volatile unsigned short buffer0_u_y_toff;
+ volatile unsigned short buffer0_v_x_toff;
+ volatile unsigned short buffer0_v_y_toff;
+ volatile unsigned short buffer1_u_x_toff;
+ volatile unsigned short buffer1_u_y_toff;
+ volatile unsigned short buffer1_v_x_toff;
+ volatile unsigned short buffer1_v_y_toff;
+ volatile unsigned int reserved11;
+ volatile unsigned int vert_downscale;
+ volatile unsigned int reserved12[86];
+ volatile unsigned short y_vert_coeff_single[52]; /*offset 0x200 --> 3*17/2 + 1*/
+ volatile unsigned int reserved13[38];
+ volatile unsigned short y_horz_coeff_single[86]; /*offset 0x300 --> 5*17/2 + 1*/
+ volatile unsigned int reserved14[85];
+ volatile unsigned short uv_vert_coeff_single[52]; /*offset 0x500 --> 3*17/2 + 1*/
+ volatile unsigned int reserved15[38];
+ volatile unsigned short uv_horz_coeff_single[52]; /*offset 0x600 --> 3*17/2 + 1*/
+ volatile unsigned int reserved16[38];
+
+} ovl_reg_image_tnc_t;
+
+/* Color Correction */
+#define OVL_YUV_COLOR_DEF_CONT_BRGHT 0x10c00fb
+#define OVL_YUV_COLOR_DEF_SATN_HUE 0x0000091
+#define OVL_RGB_COLOR_DEF_CONT_BRGHT 0x1000000
+#define OVL_RGB_COLOR_DEF_SATN_HUE 0x0000080
+
+
+/* Overlay Config */
+#define OVL_CONFIG_NO_LINE_BUFF 0xffffffff
+#define OVL_CONFIG_TWO_LINE_BUFF 0x00000000
+#define OVL_CONFIG_THREE_LINE_BUFF 0x00000001
+#define OVL_CONFIG_LINE_BUFF_MASK 0x00000001
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL_CMD_UV_SWAP 0x00004000
+#define OVL_CMD_Y_SWAP 0x00008000
+#define OVL_CMD_YUV_SWAP 0x0000C000
+
+/* Source Format */
+#define OVL_CMD_RGB_8888 0x00000400
+#define OVL_CMD_RGB_565 0x00000C00
+#define OVL_CMD_RGB_555 0x00000800
+#define OVL_CMD_YUV_NV12Alt 0x00001C00 /*planar NV12, Alternate?*/
+#define OVL_CMD_YUV_NV12 0x00002C00 /*planar NV12*/
+#define OVL_CMD_YUV_422 0x00002000 /*packed YUV422*/
+#define OVL_CMD_YUV_411 0x00002400 /*packed YUV411*/
+#define OVL_CMD_YUV_420P 0x00003000 /*planar YUV420*/
+#define OVL_CMD_YUV_422P 0x00003400 /*planar YUV422*/
+#define OVL_CMD_YUV_410P 0x00003800 /*planar YUV410*/
+#define OVL_CMD_YUV_444P 0x00003C00 /*planar YUV444*/
+#define OVL_CMD_SRC_FMT_MASK 0x00003C00 /*mask for above*/
+
+/* Flip Type */
+#define OVL_CMD_FRAME_MODE 0x00000000
+#define OVL_CMD_FIELD_MODE 0x00000020
+
+/* Field Sync Flip Enable */
+#define OVL_CMD_FIELD_SYNC_FLIP 0x00000080
+
+/* Buffer and Field */
+#define OVL_CMD_ACT_BUF0 0x00000000
+#define OVL_CMD_ACT_BUF1 0x00000004
+#define OVL_CMD_ACT_FLD0 0x00000000
+#define OVL_CMD_ACT_FLD1 0x00000002
+
+/* Initial phase register */
+#define Y_VPP_FLD0_PLUS1 0x100000
+#define Y_VPP_FLD0_PLUS2 0x200000
+#define Y_VPP_FLD0_MINUS1 0xF00000
+#define Y_VPP_FLD1_PLUS1 0x010000
+#define Y_VPP_FLD1_PLUS2 0x020000
+#define Y_VPP_FLD1_MINUS1 0x0F0000
+#define Y_HPP_PLUS1 0x001000
+#define Y_HPP_PLUS2 0x002000
+#define Y_HPP_MINUS1 0x00F000
+#define UV_VPP_FLD0_PLUS1 0x000100
+#define UV_VPP_FLD0_PLUS2 0x000200
+#define UV_VPP_FLD0_MINUS1 0x000F00
+#define UV_VPP_FLD1_PLUS1 0x000010
+#define UV_VPP_FLD1_PLUS2 0x000020
+#define UV_VPP_FLD1_MINUS1 0x0000F0
+#define UV_HPP_PLUS1 0x000001
+#define UV_HPP_PLUS2 0x000002
+#define UV_HPP_MINUS1 0x00000F
+
+#define OVL_REG_ADDR_GAMMA5 0x30010
+#define OVL_REG_ADDR_GAMMA4 0x30014
+#define OVL_REG_ADDR_GAMMA3 0x30018
+#define OVL_REG_ADDR_GAMMA2 0x3001C
+#define OVL_REG_ADDR_GAMMA1 0x30020
+#define OVL_REG_ADDR_GAMMA0 0x30024
+#define OVL_TOTAL_GAMMA_REG 6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+ than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV 0x43//4a
+#define MID_SATURATION_YUV 0x91//92
+#define MID_BRIGHTNESS_YUV -5
+
+#endif /* OVL_REGISTER_IMAGE_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
new file mode 100755
index 0000000..2565f48
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
@@ -0,0 +1,2469 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_tnc.c
+ * $Revision: 1.30 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains function that actually programs the overlay
+ * register back buffer with the bits to properly configure
+ * the overlay
+ * Also includes functions to execute the overlay flip instruction,
+ * and query the overlay flip status.
+ * Also contains some hardware capabilities querrying functions
+ * for upper overlay layer to get this chips overlay capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <math_fix.h>
+#include <tnc/cmd.h>
+#include "ovl_tnc_cache.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+#include "../cmn/ovl_coeff.h"
+#include "ovl2_tnc.h"
+
+#define OVL_DOWNSCALE_X_WORKAROUND
+
+/*-----------------------------------------------------------------------------
+ * Common dispatch functions
+ *---------------------------------------------------------------------------*/
+static int alter_ovl_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+static int query_ovl_tnc(igd_display_h display_h,
+ unsigned int flags);
+static int query_max_size_ovl_tnc(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+
+
+ovl_dispatch_t ovl_dispatch_tnc[] = {
+ /* Dispatch for the hardware overlay */
+ {
+ NULL, /* blend_surf_needed_tnc, */
+ alter_ovl_tnc,
+ query_ovl_tnc,
+ query_max_size_ovl_tnc,
+ },
+ /* Dispatch for the software overlay */
+ {
+ NULL, /* blend2_surf_needed_tnc, */
+ alter_ovl2_tnc,
+ query_ovl2_tnc,
+ query_max_size_ovl2_tnc,
+ },
+};
+
+
+
+typedef struct _ovl_chipset_tnc {
+ unsigned int num_linebuf;
+ unsigned int pixel_format;
+ unsigned int max_width;
+ unsigned int max_height;
+} ovl_chipset_tnc_t;
+
+static ovl_chipset_tnc_t ovl_chipset_tnc[] = {
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1280, 1080},
+ {OVL_CONFIG_THREE_LINE_BUFF,
+ (PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1024, 1080},
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1920, 1088},
+ {OVL_CONFIG_TWO_LINE_BUFF,
+ (PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1920, 1088},
+ {OVL_CONFIG_NO_LINE_BUFF, 0, 0, 0}
+};
+/* for Direct Display */
+typedef struct _dd_context_tnc {
+ igd_dd_context_t bridge;
+ igd_surface_t surf;
+ igd_ovl_info_t ovl;
+} dd_context_tnc_t;
+
+/* Pointers to allocated memory for the Direct Display context info */
+static dd_context_tnc_t *dd_context_ovl;
+static dd_context_tnc_t *dd_context_ovl2;
+
+#ifdef DEBUG_BUILD_TYPE
+static void ovl_dump_regs_tnc(
+ ovl_reg_image_tnc_t *ovl_regs_tnc)
+{
+ {
+ int i;
+ unsigned long *ovl_buf = (unsigned long *)ovl_regs_tnc;
+ for (i=0; i<0x10; i++) {
+ EMGD_DEBUG_S("0x%2x: 0x%8lx 0x%8lx 0x%8lx 0x%8lx\n",
+ i*0x10,
+ *(ovl_buf+(i*4)), *(ovl_buf+(i*4+1)),
+ *(ovl_buf+(i*4+2)), *(ovl_buf+(i*4+3)));
+ }
+ }
+
+
+ EMGD_DEBUG_S("************************************************\n");
+ EMGD_DEBUG_S("OVERLAY REGISTER LISTING\n");
+
+ EMGD_DEBUG_S("RGB LOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_yrgb_loff);
+ EMGD_DEBUG_S("RGB LOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_yrgb_loff);
+ EMGD_DEBUG_S("U LOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_u_loff);
+ EMGD_DEBUG_S("V LOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_v_loff);
+ EMGD_DEBUG_S("U LOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_u_loff);
+ EMGD_DEBUG_S("V LOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_v_loff);
+
+ EMGD_DEBUG_S("RGB STRIDE = 0x%x \n",
+ ovl_regs_tnc->yrgb_stride);
+ EMGD_DEBUG_S("UV STRIDE = 0x%x \n",
+ ovl_regs_tnc->uv_stride);
+ EMGD_DEBUG_S("DST POS X = %d \n",
+ ovl_regs_tnc->dest_pos_x_left);
+ EMGD_DEBUG_S("DST POS Y = %d \n",
+ ovl_regs_tnc->dest_pos_y_top);
+ EMGD_DEBUG_S("DST WIDTH = %d \n",
+ ovl_regs_tnc->dest_width_x);
+ EMGD_DEBUG_S("DST HEIGHT = %d \n",
+ ovl_regs_tnc->dest_height_y);
+ EMGD_DEBUG_S("SRC WIDTH = %d \n",
+ ovl_regs_tnc->source_yrgb_width);
+ EMGD_DEBUG_S("SRC SWWIDTH = 0x%x \n",
+ ovl_regs_tnc->source_yrgb_width_swords);
+ EMGD_DEBUG_S("SRC HEIGHT = %d \n",
+ ovl_regs_tnc->source_yrgb_height);
+ EMGD_DEBUG_S("UV SRC WIDTH = %d \n",
+ ovl_regs_tnc->source_uv_width);
+ EMGD_DEBUG_S("UV SRC SWWIDTH = %d \n",
+ ovl_regs_tnc->source_uv_width_swords);
+ EMGD_DEBUG_S("UV SRC HEIGHT = %d \n",
+ ovl_regs_tnc->source_uv_height);
+ EMGD_DEBUG_S("RGB SCALE = 0x%x \n",
+ ovl_regs_tnc->yrgb_scale);
+ EMGD_DEBUG_S("UV SCALE = 0x%x \n",
+ ovl_regs_tnc->uv_scale);
+ EMGD_DEBUG_S("COL CTL BRT CON = 0x%x \n",
+ ovl_regs_tnc->col_ctl_brt_con);
+ EMGD_DEBUG_S("COL CTL SAT HUE = 0x%x \n",
+ ovl_regs_tnc->col_ctl_sat_hue);
+ EMGD_DEBUG_S("DST COLOR KEY = 0x%x \n",
+ ovl_regs_tnc->dest_ckey_val);
+ EMGD_DEBUG_S("DST COLOR KEY MASK = 0x%x \n",
+ ovl_regs_tnc->dest_ckey_mask);
+ EMGD_DEBUG_S("SRC COLOR KEY HI = 0x%x \n",
+ ovl_regs_tnc->source_ckey_high);
+ EMGD_DEBUG_S("SRC COLOR KEY LO = 0x%x \n",
+ ovl_regs_tnc->source_ckey_low);
+ EMGD_DEBUG_S("SRC COLOR KEY MASK = 0x%x \n",
+ ovl_regs_tnc->source_ckey_mask);
+ EMGD_DEBUG_S("OVL CONFIG = 0x%x \n", ovl_regs_tnc->config);
+ EMGD_DEBUG_S("OVL CMD = 0x%x \n", ovl_regs_tnc->command);
+ EMGD_DEBUG_S("Y START 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_yrgb_start);
+ EMGD_DEBUG_S("Y START 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_yrgb_start);
+ EMGD_DEBUG_S("U START 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_u_start);
+ EMGD_DEBUG_S("V START 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_v_start);
+ EMGD_DEBUG_S("U START 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_u_start);
+ EMGD_DEBUG_S("V START 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_v_start);
+ EMGD_DEBUG_S("Y X TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_yrgb_x_toff);
+ EMGD_DEBUG_S("Y Y TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_yrgb_y_toff);
+ EMGD_DEBUG_S("Y X TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_yrgb_x_toff);
+ EMGD_DEBUG_S("Y Y TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_yrgb_y_toff);
+ EMGD_DEBUG_S("U X TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_u_x_toff);
+ EMGD_DEBUG_S("U Y TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_u_y_toff);
+ EMGD_DEBUG_S("V X TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_v_x_toff);
+ EMGD_DEBUG_S("V Y TOFF 0 = 0x%x \n",
+ ovl_regs_tnc->buffer0_v_y_toff);
+ EMGD_DEBUG_S("U X TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_u_x_toff);
+ EMGD_DEBUG_S("U Y TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_u_y_toff);
+ EMGD_DEBUG_S("V X TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_v_x_toff);
+ EMGD_DEBUG_S("V Y TOFF 1 = 0x%x \n",
+ ovl_regs_tnc->buffer1_v_y_toff);
+ EMGD_DEBUG_S("FAST_V_DSCALE = 0x%x \n",
+ ovl_regs_tnc->vert_downscale);
+ EMGD_DEBUG_S("************************************************\n");
+}
+#endif
+
+/*----------------------------------------------------------------------
+ * Function: ovl_check_pf_tnc()
+ * Parameters: unsigned int requested_pixel_format -
+ * according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ * TRUE on Success
+ * FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_check_pf_tnc(
+ igd_display_context_t *display,
+ unsigned int requested_pixel_format)
+{
+ unsigned long *overlay_pfs;
+ int temp_loop = 0;
+
+ display->context->dispatch.get_pixelformats(
+ (igd_display_h)display, NULL, NULL, &overlay_pfs, NULL, NULL);
+
+ while(overlay_pfs[temp_loop]) {
+ if(overlay_pfs[temp_loop] == requested_pixel_format) {
+ return TRUE;
+ }
+ ++temp_loop;
+ }
+
+ return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+ switch(pf) {
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ return 1;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ return 2;
+ break;
+ default:
+ return 0;
+ }
+
+}
+
+static unsigned int ovl_check_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ igd_timing_info_t *timing;
+ ovl_chipset_tnc_t *ovl_chip;
+ unsigned int min_w, min_h;
+
+ EMGD_TRACE_ENTER;
+
+ if (!display){
+ EMGD_ERROR_EXIT("display is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!PIPE(display)){
+ EMGD_ERROR_EXIT("PIPE(display) is null");
+ return -IGD_ERROR_INVAL;
+ }
+
+ timing = PIPE(display)->timing;
+
+ if(!timing) {
+ EMGD_ERROR_EXIT("timing is null\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /*************************************************************************
+ * Ensure the framebuffer dotclock does not exceed the board SKU
+ * max dotclock
+ *************************************************************************/
+ /* DCT-PC99TA crashes with dotclock > 300MHz */
+ /* FIXME: This is using the dclk from Napa */
+ if(timing->dclk >= 340000){
+ EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* The following parameters are only valid if the overlay is on, so
+ * return success if the overlay is being turned off. */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Ensure the overlay surface is ok and can be properly displayed.
+ * This ensures the following is valid:
+ * - Ensure x1, x2, y1, y2 are pixel aligned
+ * - 2 pixels or greater in width and height
+ * - Pixel format is supported by the overlay
+ * - Pitch is <= 8KB
+ * - Based on the pixel format, the width is supported
+ *************************************************************************/
+ if (!src_surf){
+ EMGD_ERROR_EXIT("src_surf is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (!src_rect){
+ EMGD_ERROR_EXIT("src_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ /* Get the minimum size of 1 pixel in width and height for y, u, and v.
+ */
+ min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+ min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+ if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+ ((src_rect->y2 - src_rect->y1) < min_h*2)) {
+ EMGD_ERROR_EXIT(
+ "Overlay source width or height is < 2 pixels (%dx%d)\n",
+ src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if (FALSE == ovl_check_pf_tnc(display, src_surf->pixel_format)) {
+ EMGD_ERROR_EXIT("Overlay source pixel format unsupported (pf:0x%lx)",
+ src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ if (src_surf->pitch > 8192) {
+ EMGD_ERROR_EXIT("Overlay source pitch (%d) > 8KB",
+ src_surf->pitch);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ ovl_chip = ovl_chipset_tnc;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((src_surf->pixel_format & IGD_PF_MASK) ==
+ ovl_chip->pixel_format) &&
+ (src_surf->width <= ovl_chip->max_width)) {
+ break;
+ }
+ ovl_chip++;
+ }
+ if (ovl_chip->num_linebuf == OVL_CONFIG_NO_LINE_BUFF) {
+ EMGD_ERROR_EXIT("Overlay source width (%d) > max supported",
+ src_surf->width);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /*************************************************************************
+ * Ensure the location on the framebuffer is ok and can be properly
+ * displayed
+ * This ensures the following is valid:
+ * - Greater than 1 pixel width and height
+ * - Will be displayed on screen (not panned off)
+ *************************************************************************/
+ if (!dest_rect){
+ EMGD_ERROR_EXIT("dest_rect is null");
+ return -IGD_ERROR_INVAL;
+ }
+ if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+ ((dest_rect->y2 - dest_rect->y1) <= 1)) {
+ EMGD_ERROR_EXIT(
+ "Overlay dest width or height is single pixel (%dx%d)\n",
+ dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ if ((dest_rect->x1 >= timing->width) ||
+ (dest_rect->y1 >= timing->height)) {
+ EMGD_ERROR_EXIT(
+ "Overlay dest is panned off the screen (%d,%d)\n",
+ dest_rect->x1, dest_rect->y1);
+ return -IGD_ERROR_INVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+static unsigned int ovl_update_src_tnc(igd_display_context_t *display,
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ ovl_chipset_tnc_t *ovl_chip;
+ unsigned int src_Bpp;
+ unsigned int src_uv_shift_x, src_uv_shift_y;
+ unsigned short src_w;
+ unsigned short src_h;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+ src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+ src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+ src_w = src_rect->x2 - src_rect->x1;
+ src_h = src_rect->y2 - src_rect->y1;
+
+ /* Surface pitch */
+ ovl_regs_tnc->yrgb_stride = (unsigned short)src_surf->pitch;
+ ovl_regs_tnc->uv_stride = (unsigned short)src_surf->u_pitch;
+
+
+ /* src width */
+ ovl_regs_tnc->source_yrgb_width = src_w;
+ ovl_regs_tnc->source_uv_width = src_w >> src_uv_shift_x;
+
+ /* src width swords - This equation follows the B-Spec */
+ /* Equation in B-spec is cancelling out fixed point round-up when -1.
+ Explain below:
+ [[(offset + width + 63)/128 - offset/128] * 2 ] - 1
+ [(width/128 + 63/128) * 2] - 1
+ (width/128)*2 + (0.249*2) - 1
+ width/64
+
+ Modify the formula witihout -1 to preserve fix point round-up.
+ Equation = width/64 + 0.4999
+ Also modified 63/128(0x3F) to 31/128(0x1F) to have 0.5 when *2.
+ */
+
+ ovl_regs_tnc->source_yrgb_width_swords =
+ (unsigned short)(((((src_surf->offset +
+ (ovl_regs_tnc->source_yrgb_width * src_Bpp) +
+ 0x1F) >> 6) -
+ (src_surf->offset >> 6)) << 1) << 2);
+ ovl_regs_tnc->source_uv_width_swords =
+ (unsigned short)(((((src_surf->u_offset +
+ (ovl_regs_tnc->source_uv_width * src_Bpp) +
+ 0x1F) >> 6) -
+ (src_surf->u_offset >> 6)) << 1) << 2 );
+
+ /* src height */
+ ovl_regs_tnc->source_yrgb_height = src_h;
+ ovl_regs_tnc->source_uv_height = src_h >> src_uv_shift_y;
+
+ /* src pixel format */
+ switch(src_surf->pixel_format){
+ case IGD_PF_YUV422_PACKED_YUY2:
+ ovl_regs_tnc->command |= OVL_CMD_YUV_422;
+ break;
+ case IGD_PF_YUV422_PACKED_UYVY:
+ ovl_regs_tnc->command |= OVL_CMD_YUV_422 | OVL_CMD_Y_SWAP;
+ break;
+ case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+ ovl_regs_tnc->command |= OVL_CMD_YUV_420P;
+ break;
+ case IGD_PF_YUV420_PLANAR_YV12:
+ ovl_regs_tnc->command |= OVL_CMD_YUV_420P | OVL_CMD_UV_SWAP;
+ break;
+ case IGD_PF_YUV420_PLANAR_NV12:
+ ovl_regs_tnc->command |= OVL_CMD_YUV_NV12;
+ break;
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ ovl_regs_tnc->command |= OVL_CMD_YUV_410P;
+ break;
+ case IGD_PF_ARGB32_8888:
+ case IGD_PF_xRGB32_8888:
+ ovl_regs_tnc->command |= OVL_CMD_RGB_8888;
+ break;
+ case IGD_PF_RGB16_565:
+ ovl_regs_tnc->command |= OVL_CMD_RGB_565;
+ break;
+ case IGD_PF_xRGB16_555:
+ case IGD_PF_ARGB16_1555:
+ ovl_regs_tnc->command |= OVL_CMD_RGB_555;
+ break;
+ default:
+ EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Turn off YUV to RGB conversion if the src is RGB */
+ if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+ ovl_regs_tnc->config |= (1<<4);
+ }
+
+ ovl_chip = ovl_chipset_tnc;
+ ovl_regs_tnc->config &= ~OVL_CONFIG_LINE_BUFF_MASK;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((src_surf->pixel_format & IGD_PF_MASK) ==
+ ovl_chip->pixel_format) &&
+ (src_w <= ovl_chip->max_width)) {
+ ovl_regs_tnc->config |= ovl_chip->num_linebuf;
+ break;
+ }
+ ovl_chip++;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static unsigned int ovl_update_src_ptr_tnc(igd_display_context_t *display,
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+ unsigned int src_Bpp;
+ unsigned int src_uv_shift_x, src_uv_shift_y;
+ unsigned short src_w;
+ unsigned short src_h;
+
+ EMGD_TRACE_ENTER;
+
+ /* This is in Bytes per pixel */
+ src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+ src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+ src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+ src_w = src_rect->x2 - src_rect->x1;
+ src_h = src_rect->y2 - src_rect->y1;
+
+ /* Surface offset */
+ ovl_regs_tnc->buffer0_yrgb_start =
+ ovl_regs_tnc->buffer1_yrgb_start =
+ src_surf->offset;
+ ovl_regs_tnc->buffer0_u_start =
+ ovl_regs_tnc->buffer1_u_start =
+ src_surf->u_offset;
+ ovl_regs_tnc->buffer0_v_start =
+ ovl_regs_tnc->buffer1_v_start =
+ src_surf->v_offset;
+
+ /* Linear surface information */
+ ovl_regs_tnc->buffer0_yrgb_loff =
+ ovl_regs_tnc->buffer1_yrgb_loff =
+ (src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp);
+
+ /*
+ * The NV12 format has the UV pixels interleaved so the total
+ * width of the UV portion of the surface is the same as the
+ * Y width. Thus, don't do any shifting of the UV plane in the
+ * X direction.
+ */
+ if (src_surf->pixel_format == IGD_PF_YUV420_PLANAR_NV12) {
+ ovl_regs_tnc->buffer0_u_loff =
+ ovl_regs_tnc->buffer1_u_loff =
+ ((src_rect->y1>>src_uv_shift_y) *
+ src_surf->u_pitch) + src_rect->x1;
+
+ ovl_regs_tnc->buffer0_v_loff =
+ ovl_regs_tnc->buffer1_v_loff =
+ ((src_rect->y1>>src_uv_shift_y) *
+ src_surf->v_pitch) + src_rect->x1;
+ } else {
+ ovl_regs_tnc->buffer0_u_loff =
+ ovl_regs_tnc->buffer1_u_loff =
+ ((src_rect->y1>>src_uv_shift_y) *
+ src_surf->u_pitch) +
+ (src_rect->x1>>src_uv_shift_x);
+
+ ovl_regs_tnc->buffer0_v_loff =
+ ovl_regs_tnc->buffer1_v_loff =
+ ((src_rect->y1>>src_uv_shift_y) * src_surf->v_pitch) +
+ (src_rect->x1>>src_uv_shift_x);
+ }
+
+
+ /* The B-Spec states that these values are ignored with a linear
+ * surface. However on the 965G, these values are not ignored,
+ * so zero them. */
+ ovl_regs_tnc->buffer0_yrgb_x_toff =
+ ovl_regs_tnc->buffer1_yrgb_x_toff =
+ ovl_regs_tnc->buffer0_yrgb_y_toff =
+ ovl_regs_tnc->buffer1_yrgb_y_toff =
+ ovl_regs_tnc->buffer0_u_x_toff =
+ ovl_regs_tnc->buffer0_v_x_toff =
+ ovl_regs_tnc->buffer1_u_x_toff =
+ ovl_regs_tnc->buffer1_v_x_toff =
+ ovl_regs_tnc->buffer0_u_y_toff =
+ ovl_regs_tnc->buffer0_v_y_toff =
+ ovl_regs_tnc->buffer1_u_y_toff =
+ ovl_regs_tnc->buffer1_v_y_toff =
+ 0;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static unsigned int ovl_update_phase_tnc(
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect)
+{
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ * Set the Vertical/Horizontal Phase Registers. Both Field0
+ * and Field1 are set, although Field1 is only used when
+ * interleaved.
+ */
+ switch (src_surf->pixel_format) {
+ case IGD_PF_YUV422_PACKED_YUY2:
+ case IGD_PF_YUV422_PACKED_UYVY:
+ /* YUV 422 */
+ ovl_regs_tnc->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_tnc->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0;
+ } else {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x8000; /*.5*/
+ }
+
+ /* Horizontal Phase */
+ if (!(src_rect->x1 & 1)) {
+ ovl_regs_tnc->yrgb_hphase = 0;
+ ovl_regs_tnc->uv_hphase = 0;
+ } else {
+ ovl_regs_tnc->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_tnc->yrgb_hphase = 0; /*1*/
+ ovl_regs_tnc->uv_hphase = 0x8000; /*.5*/
+ }
+ break;
+
+ case IGD_PF_YUV420_PLANAR_I420:
+ case IGD_PF_YUV420_PLANAR_YV12:
+ case IGD_PF_YUV420_PLANAR_NV12:
+ /* YUV 420 */
+ ovl_regs_tnc->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_tnc->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ if (!(src_rect->y1 & 1)) {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*0*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0xc000; /*-.25*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x4000; /*.25*/
+ } else {
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*0*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0xc000; /*-.25*/
+ }
+ } else {
+ if (!(src_rect->y1 & 1)) {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0xc000; /*.75*/
+ } else {
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0xc000; /*.75*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x4000; /*.25*/
+ }
+ }
+
+ /* Horizontal Phase */
+ if (!(src_rect->x1 & 1)) {
+ ovl_regs_tnc->yrgb_hphase = 0;
+ ovl_regs_tnc->uv_hphase = 0;
+ } else {
+ ovl_regs_tnc->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_tnc->yrgb_hphase = 0; /*1*/
+ ovl_regs_tnc->uv_hphase = 0x8000; /*.5*/
+ }
+ break;
+
+ case IGD_PF_YUV410_PLANAR_YVU9:
+ /* YUV 410 */
+ ovl_regs_tnc->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_tnc->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ switch (src_rect->y1 & 3) {
+ default:
+ case 0:
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*0*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0xa000; /*-.375*/
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0xe000; /*-.125*/
+ break;
+
+ case 1:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0xe000; /*-.125*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x2000; /*.125*/
+ break;
+
+ case 2:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*1*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x2000; /*.125*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x6000; /*.375*/
+ break;
+
+ case 3:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0; /*1*/
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;/*0*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x6000; /*.375*/
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0xa000; /*-.375*/
+ break;
+ }
+ } else {
+ switch (src_rect->y1 & 3) {
+ default:
+ case 0:
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0xc000; /*-.25*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0; /*0*/
+ break;
+
+ case 1:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x0; /*0*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x4000; /*.25*/
+ break;
+
+ case 2:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x4000; /*.25*/
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x8000; /*.5*/
+ break;
+
+ case 3:
+ ovl_regs_tnc->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x8000; /*.5*/
+ ovl_regs_tnc->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0xc000; /*-.25*/
+ break;
+ }
+ }
+
+ /* Horizontal Phase */
+ switch (src_rect->x1 & 3) {
+ default:
+ case 0:
+ ovl_regs_tnc->yrgb_hphase = 0;
+ ovl_regs_tnc->init_phase_shift |= UV_HPP_MINUS1;
+ ovl_regs_tnc->uv_hphase = 0xa000; /*-.375*/
+ break;
+
+ case 1:
+ ovl_regs_tnc->init_phase_shift |= Y_HPP_PLUS1;
+ ovl_regs_tnc->yrgb_hphase = 0; /*1*/
+ ovl_regs_tnc->init_phase_shift |= UV_HPP_MINUS1;
+ ovl_regs_tnc->uv_hphase = 0xe000; /*-.125*/
+ break;
+
+ case 2:
+ ovl_regs_tnc->init_phase_shift |= Y_HPP_PLUS2;
+ ovl_regs_tnc->yrgb_hphase = 0; /*2*/
+ ovl_regs_tnc->uv_hphase = 0x2000; /*.125*/
+ break;
+
+ case 3:
+ ovl_regs_tnc->init_phase_shift |= Y_HPP_PLUS2;
+ ovl_regs_tnc->yrgb_hphase = 0xffff; /*3*/
+ ovl_regs_tnc->uv_hphase = 0x6000; /*.375*/
+ break;
+ }
+ break;
+
+ default:
+ /* RGB format */
+ ovl_regs_tnc->init_phase_shift = 0;
+
+ /* Vertical Phase */
+ if (ovl_regs_tnc->config & OVL_CONFIG_THREE_LINE_BUFF) {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0;
+ } else {
+ ovl_regs_tnc->yrgb_vert_phase_field0 = 0x8000;
+ ovl_regs_tnc->yrgb_vert_phase_field1 = 0x8000;
+ ovl_regs_tnc->uv_vert_phase_field0 = 0x8000;
+ ovl_regs_tnc->uv_vert_phase_field1 = 0x8000;
+ }
+
+ /* Horizontal Phase */
+ ovl_regs_tnc->yrgb_hphase = 0;
+ ovl_regs_tnc->uv_hphase = 0;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_scale_tnc()
+ *
+ * Description: Will update only the scaling registers for the Atom E6xx core
+ *
+ * Returns:
+ * N/A
+ *----------------------------------------------------------------------*/
+
+static unsigned int ovl_update_scale_tnc(
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags)
+{
+ unsigned int uv_shift;
+ unsigned int xscale, xscale_int, xscale_fract;
+ unsigned int yscale, yscale_int, yscale_fract;
+ unsigned int xscale_int_uv, xscale_fract_uv;
+ unsigned int yscale_int_uv, yscale_fract_uv;
+
+ EMGD_TRACE_ENTER;
+
+ xscale = ((src_rect->x2 - src_rect->x1)<<12) /
+ (dest_rect->x2 - dest_rect->x1);
+ yscale = ((src_rect->y2 - src_rect->y1)<<12) /
+ (dest_rect->y2 - dest_rect->y1);
+
+ /* In interleaved mode, the y scale is /2 */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ yscale >>= 1;
+ }
+
+ xscale_int = (xscale & 0x3000) >> 12;
+ xscale_fract = xscale & 0xfff;
+ yscale_int = (yscale & 0x7ff000) >> 12;
+ yscale_fract = yscale & 0xfff;
+
+ /* The uv scale is used for both YUV Planar as well as YUV Packed */
+ uv_shift = get_uv_shift_x(src_surf->pixel_format);
+ xscale_int_uv = ((xscale>>uv_shift) & 0x3000) >> 12;
+ xscale_fract_uv = (xscale>>uv_shift) & 0xfff;
+
+ uv_shift = get_uv_shift_y(src_surf->pixel_format);
+ yscale_int_uv = ((yscale>>uv_shift) & 0x7ff000) >> 12;
+ yscale_fract_uv = (yscale>>uv_shift) & 0xfff;
+
+ ovl_regs_tnc->yrgb_scale =
+ (yscale_fract << 20) | /* Vert Scale Fraction */
+ (xscale_int << 16) | /* Horiz Scale Int */
+ (xscale_fract << 3); /* Horiz Scale Fraction */
+
+ ovl_regs_tnc->uv_scale =
+ (yscale_fract_uv << 20) | /* UV Vert Scale Fraction */
+ (xscale_int_uv << 16) | /* UV Horiz Scale Int */
+ (xscale_fract_uv << 3 ); /* UV Horiz Scale Fraction */
+ ovl_regs_tnc->vert_downscale =
+ (yscale_int << 16) | /* Vert Scale Factor */
+ yscale_int_uv; /* UV Vert Scale Factor */
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_video_quality_tnc()
+ *
+ * Description:
+ * This function updates the contrast, brightness, and saturation of
+ * the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ * != 0 on Error
+ * 0 on Success
+ *----------------------------------------------------------------------*/
+
+static int ovl_update_video_quality_tnc(
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_ovl_video_quality_info_t *video_quality)
+{
+ int calc_brightness_tmp = 0;
+ int calc_brightness = 0;
+ unsigned int calc_contrast_tmp = 0;
+ unsigned int calc_contrast = 0;
+ unsigned int calc_saturation_tmp = 0;
+ unsigned int calc_saturation = 0;
+ unsigned int calc_hue_tmp = 0;
+ unsigned int calc_hue = 0;
+
+ EMGD_TRACE_ENTER;
+
+ /* If the src_surf pixel format is RGB, then brightness, contrast,
+ * and saturation should all be set to the exact default */
+ if (src_surf->pixel_format & PF_TYPE_RGB) {
+ if (video_quality->brightness != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set brightness to default");
+ }
+ if (video_quality->contrast != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set contrast to default");
+ }
+ if (video_quality->saturation != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set saturation to default");
+ }
+ if (video_quality->hue != 0x8000) {
+ EMGD_DEBUG("RGB surfaces must set hue to default");
+ }
+ ovl_regs_tnc->col_ctl_brt_con = OVL_RGB_COLOR_DEF_CONT_BRGHT;
+ ovl_regs_tnc->col_ctl_sat_hue = OVL_RGB_COLOR_DEF_SATN_HUE;
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /*************************************************************************
+ * Brightness
+ *************************************************************************/
+ if (0x8000 == video_quality->brightness) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ } else if (video_quality->brightness < 0x8000) {
+ /*
+ * we have here a brightness that is less than the default
+ * mid point
+ */
+ calc_brightness_tmp = 0x8000 - video_quality->brightness;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = -128 - MID_BRIGHTNESS_YUV;
+ /*
+ * more range if the midpoint is positive but less range
+ * if midpoint is negative
+ */
+
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness < -128) {
+ calc_brightness = -128;
+ }
+ if (calc_brightness > MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ } else {
+ /*
+ * we have here a brightness that is more than the default
+ * mid point
+ */
+ calc_brightness_tmp = video_quality->brightness - 0x8000;
+ calc_brightness_tmp <<= 14;
+ calc_brightness_tmp /= 0x8000;
+ calc_brightness = 127 - MID_BRIGHTNESS_YUV;
+ /*
+ * less range if the midpoint is positive but more range
+ * if midpoint is negative
+ */
+ calc_brightness *= calc_brightness_tmp;
+ calc_brightness += BIT13;
+ calc_brightness >>= 14;
+
+ if (calc_brightness > 127) {
+ calc_brightness = 127;
+ }
+ if (calc_brightness < MID_BRIGHTNESS_YUV) {
+ calc_brightness = MID_BRIGHTNESS_YUV;
+ }
+ }
+
+ ovl_regs_tnc->col_ctl_brt_con =
+ (ovl_regs_tnc->col_ctl_brt_con & 0xFFFFFF00) |
+ (calc_brightness & 0xFF);
+
+ /*************************************************************************
+ * Contrast
+ *************************************************************************/
+ if (0x8000 == video_quality->contrast ){
+ calc_contrast = MID_CONTRAST_YUV;
+ } else if (video_quality->contrast < 0x8000) {
+ /* we have here a contrast that is less than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = MID_CONTRAST_YUV;
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ if (calc_contrast > 0x3F) {
+ calc_contrast = 0x3F;
+ }
+ } else {
+ /* we have here a contrast that is more than the
+ * default mid point */
+ calc_contrast_tmp = video_quality->contrast - 0x8000;
+ calc_contrast_tmp <<= 12;
+ calc_contrast_tmp /= 0x8000;
+ calc_contrast = (0x1FF - MID_CONTRAST_YUV);
+ calc_contrast *= calc_contrast_tmp;
+ calc_contrast += BIT11;
+ calc_contrast >>= 12;
+ calc_contrast += MID_CONTRAST_YUV;
+ if (calc_contrast > 0x1FF) {
+ calc_contrast = 0x1FF;
+ }
+ }
+
+ ovl_regs_tnc->col_ctl_brt_con =
+ (ovl_regs_tnc->col_ctl_brt_con & 0xF803FFFF) |
+ ((calc_contrast & 0x1FF) << 18);
+
+ /*************************************************************************
+ * Saturation
+ *************************************************************************/
+ if (video_quality->saturation == 0x8000) {
+ calc_saturation = MID_SATURATION_YUV;
+ } else if (video_quality->saturation < 0x8000) {
+ /* we have here a saturation that is less than the default
+ * mid point */
+ calc_saturation_tmp = video_quality->saturation;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = MID_SATURATION_YUV;
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ if (calc_saturation > 0x7F) {
+ calc_saturation = 0x7F;
+ }
+ } else {
+ /* we have here a saturation that is more than the default
+ * mid point*/
+ calc_saturation_tmp = video_quality->saturation - 0x8000;
+ calc_saturation_tmp <<= 12;
+ calc_saturation_tmp /= 0x8000;
+ calc_saturation = (0x3FF - MID_SATURATION_YUV);
+ calc_saturation *= calc_saturation_tmp;
+ calc_saturation += BIT11;
+ calc_saturation >>= 12;
+ calc_saturation += MID_SATURATION_YUV;
+
+ if (calc_saturation > 0x3FF) {
+ calc_saturation = 0x3FF;
+ }
+ }
+
+ ovl_regs_tnc->col_ctl_sat_hue =
+ (ovl_regs_tnc->col_ctl_sat_hue & 0xFFFFFC00) |
+ (calc_saturation & 0x3FF); // add 10bits saturation value
+
+ /*************************************************************************
+ * hue
+ *************************************************************************/
+ if (video_quality->hue == 0x8000) {
+ calc_hue = 0;
+ } else if (video_quality->hue < 0x8000) {
+ /* we have here a hue that is less than the middle value
+ * get 2's complement value decrease from 0x3ff to 0 */
+
+ calc_hue_tmp = 0x8000 - video_quality->hue;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ /* 2's complement negative value equal the corresponding
+ * positive value reverse every bits then plus 1
+ * and add signed bit, then the calc_hue is from -0x3ff to 0 */
+
+ calc_hue = (~calc_hue + 1) & 0x7ff;
+ } else {
+ /* we have here a saturation that is more than the middle value
+ * get 2's complement value increase from 0 to 0x3ff */
+
+ calc_hue_tmp = video_quality->hue - 0x8000;
+ calc_hue_tmp <<= 12;
+ calc_hue_tmp /= 0x8000;
+ calc_hue = 0x3FF;
+ calc_hue *= calc_hue_tmp;
+ calc_hue += BIT11;
+ calc_hue >>= 12;
+
+ if (calc_hue > 0x3FF) {
+ calc_hue = 0x3FF;
+ }
+ }
+ /* add 11bits hue value to register */
+ ovl_regs_tnc->col_ctl_sat_hue =
+ (ovl_regs_tnc->col_ctl_sat_hue & 0xF800FFFF) |
+ ((calc_hue & 0x7FF) << 16);
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static void check_gamma(unsigned int *gamma)
+{
+
+ if (*gamma < IGD_OVL_GAMMA_MIN) {
+ EMGD_ERROR("Gamma to small (0x%x in 24i.8f format), "
+ "changing to Min Gamma (0.6)",
+ *gamma);
+ *gamma = IGD_OVL_GAMMA_MIN;
+ }
+ if (*gamma > IGD_OVL_GAMMA_MAX) {
+ EMGD_ERROR("Gamma to large (0x%x in 24i.8f format), "
+ "changing to Max Gamma (6.0)",
+ *gamma);
+ *gamma = IGD_OVL_GAMMA_MAX;
+ }
+
+ return;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: ovl_update_gamma_tnc()
+ *
+ * Description:
+ * This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ * != 0 on Error
+ * IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int ovl_update_gamma_tnc(
+ igd_display_context_t *display,
+ igd_ovl_gamma_info_t * ovl_gamma)
+{
+ const int gamma_reg_input[OVL_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+ const int gamma_reg_offset[OVL_TOTAL_GAMMA_REG] = {
+ OVL_REG_ADDR_GAMMA0,
+ OVL_REG_ADDR_GAMMA1,
+ OVL_REG_ADDR_GAMMA2,
+ OVL_REG_ADDR_GAMMA3,
+ OVL_REG_ADDR_GAMMA4,
+ OVL_REG_ADDR_GAMMA5
+ };
+ const unsigned int gamma_def[OVL_TOTAL_GAMMA_REG] = {
+ 0x00080808,
+ 0x00101010,
+ 0x00202020,
+ 0x00404040,
+ 0x00808080,
+ 0x00c0c0c0
+ };
+ unsigned int new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+ unsigned int new_gamma_blue_24i_8f;
+ unsigned int gamma_normal_r_24i_8f;
+ unsigned int gamma_normal_g_24i_8f;
+ unsigned int gamma_normal_b_24i_8f;
+ unsigned int gamma_reg, gamma_reg_24i_8f;
+ unsigned int i;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The gamma values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /* If the overlay gamma is disabled, set it to the default */
+ if ((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) {
+ for (i = 0; i < OVL_TOTAL_GAMMA_REG; i++) {
+ /* program register */
+ EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+ }
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* It is assumed that the input value is a 24-bit number */
+ new_gamma_red_24i_8f = ovl_gamma->red;
+ new_gamma_green_24i_8f = ovl_gamma->green;
+ new_gamma_blue_24i_8f = ovl_gamma->blue;
+
+ /* Ensure the gamma values are between MIN and MAX */
+ check_gamma(&new_gamma_red_24i_8f);
+ check_gamma(&new_gamma_green_24i_8f);
+ check_gamma(&new_gamma_blue_24i_8f);
+
+ /*
+ * Program RGB for each of the 6 gamma registers
+ */
+
+ /* Since the OS_POW_FIX function can only take an integer base,
+ * we need to normalize the result by gamma_normal_x
+ */
+ gamma_normal_r_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+ gamma_normal_g_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+ gamma_normal_b_24i_8f = OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+ for( i = 0; i < OVL_TOTAL_GAMMA_REG; i++ )
+ {
+ /* red */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_red_24i_8f);
+ gamma_reg =
+ ((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+ /* green */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_green_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+ /* blue */
+ gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+ (1<<16)/new_gamma_blue_24i_8f);
+ gamma_reg |=
+ ((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+ /* turn overlay off (TBD) */
+
+ /* program register */
+ EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+ /* turn overlay on (TBD) */
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_coeff_tnc()
+ * Description: Function to calculate the filter coeffcient
+ * registers for tnc
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_update_coeff_tnc(
+ ovl_reg_image_tnc_t *ovl_regs_tnc,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ unsigned int flags)
+{
+ unsigned int scale_int, scale_fpint;
+
+ unsigned int dest_h = dest_rect->y2 - dest_rect->y1;
+ unsigned int dest_w = dest_rect->x2 - dest_rect->x1;
+ unsigned int src_h = src_rect->y2 - src_rect->y1;
+ unsigned int src_w = src_rect->x2 - src_rect->x1;
+
+ EMGD_TRACE_ENTER;
+
+ /* FIXME: The coeff values are re-written for every alter_ovl call.
+ * This may cause issues or may be to slow? If so, store the previous
+ * values and only re-write when they change. */
+
+ /*
+ ovl_regs_tnc =
+ (ovl_reg_image_tnc_t *)(display->context->device_context.virt_fb_adr +
+ ovl_context->reg_update_offset);
+ ovl_regs_tnc = phys_to_virt(ovl_context->reg_update_phys);
+ */
+
+ /* In interleaved mode, the src_h is /2 */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ src_h >>= 1;
+ }
+
+ /* Y Horizontal */
+ scale_int = ((ovl_regs_tnc->yrgb_scale) >> 16) & 0x7;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+ }
+ ovl_update_coeff_regs(5, scale_fpint, 1, 1,
+ (unsigned short *)ovl_regs_tnc->y_horz_coeff_single);
+
+ /* Y Vertical */
+ scale_int = ((ovl_regs_tnc->vert_downscale) >> 16) & 0x7ff;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+ }
+ ovl_update_coeff_regs(3, scale_fpint, 0, 1,
+ (unsigned short *)ovl_regs_tnc->y_vert_coeff_single);
+
+ /* UV Horizontal */
+ scale_int = ((ovl_regs_tnc->uv_scale) >> 16) & 0x7;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+ scale_fpint >>= get_uv_shift_x(src_surf->pixel_format);
+ }
+ ovl_update_coeff_regs(3, scale_fpint , 1, 0,
+ (unsigned short *)ovl_regs_tnc->uv_horz_coeff_single);
+
+ /* UV Vertical */
+ scale_int = (ovl_regs_tnc->vert_downscale) & 0x7ff;
+ if (!scale_int) {
+ /* upscale - clamp to 1.0 */
+ scale_fpint = 1<<20;
+ } else {
+ scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+ scale_fpint >>= get_uv_shift_y(src_surf->pixel_format);
+ }
+ ovl_update_coeff_regs(3, scale_fpint, 0, 0,
+ (unsigned short *)ovl_regs_tnc->uv_vert_coeff_single);
+
+ /* Adjust for 2-line Vertical Buffer */
+ if((ovl_regs_tnc->config & OVL_CONFIG_LINE_BUFF_MASK)==
+ OVL_CONFIG_TWO_LINE_BUFF){
+ ovl_update_coeff_regs(2, 0x10, 0, 1,
+ (unsigned short *)ovl_regs_tnc->y_vert_coeff_single);
+ ovl_update_coeff_regs(2, 0x10, 0, 0,
+ (unsigned short *)ovl_regs_tnc->uv_vert_coeff_single);
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static unsigned int convert_color_key_to_hw (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ case IGD_PF_ARGB8_INDEXED:
+ default:
+ output = input;
+ break;
+ case IGD_PF_RGB16_565:
+ output =
+ ((((input & 0xf800)>>11)<<3)<<16) |
+ ((((input & 0x07e0)>>5 )<<2)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ case IGD_PF_ARGB16_1555:
+ output =
+ ((((input & 0x7c00)>>10)<<3)<<16) |
+ ((((input & 0x03e0)>>5 )<<3)<<8 ) |
+ ((((input & 0x001f)>>0 )<<3)<<0 );
+ break;
+ }
+
+ return output;
+}
+static unsigned int convert_color_key_to_mask (
+ unsigned long pf,
+ unsigned int input)
+{
+ unsigned int output;
+
+ switch (pf) {
+ case IGD_PF_ARGB32:
+ case IGD_PF_xRGB32:
+ default:
+ output = 0x00000000;
+ break;
+ case IGD_PF_RGB16_565:
+ output = 0x00070307;
+ break;
+ case IGD_PF_ARGB16_1555:
+ output = 0x00070707;
+ break;
+ case IGD_PF_ARGB8_INDEXED:
+ output = 0x00ffff00;
+ break;
+ }
+
+ return output;
+}
+
+
+#ifndef OVL_TNC_CACHE_QUICK_SWAP
+
+static unsigned int ovl_update_regs_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl_reg_image_tnc_t *ovl_regs_tnc, *ovl_cache_tnc;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /*
+ ovl_regs_tnc =
+ (ovl_reg_image_tnc_t *)(display->context->device_context.virt_fb_adr +
+ ovl_context->reg_update_offset);
+ */
+ ovl_regs_tnc = phys_to_virt(ovl_context->reg_update_phys);
+ ovl_cache_tnc = OS_ALLOC(sizeof(ovl_reg_image_tnc_t));
+ OS_MEMSET(ovl_cache_tnc, 0, sizeof(ovl_reg_image_tnc_t));
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+ /* Turn the overlay Off */
+ ovl_regs_tnc->command = 0;
+ /* Always use buf 0 when turning the overlay off. */
+ ovl_context->ovl_buff = 0;
+ OS_FREE(ovl_cache_tnc);
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* Force value to even due hardware expects even number */
+ dest_rect->y1 &= ~1;
+ dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+ dest_rect->x1 &= ~1;
+ dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+ /*************************************************************************
+ * Copy the information passed in to the HW overlay structure
+ *************************************************************************/
+ /* Zero the config and command, since they will be OR'ed in with data
+ * below */
+ ovl_cache_tnc->config = 0;
+ ovl_cache_tnc->command = 0;
+
+ /* Set overlay to the proper pipe */
+ if (1 == PIPE(display)->pipe_num) {
+ /* This is pipe B */
+ ovl_cache_tnc->config |= 1 << 18;
+ }
+
+ /* Interleaved/progressive and Odd/Even if interleaved */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ ovl_cache_tnc->command |= OVL_CMD_FIELD_MODE;
+ /* Need to enable FIELD SYNC OVERLAY FLIP in field mode. */
+ ovl_cache_tnc->command |= OVL_CMD_FIELD_SYNC_FLIP;
+ /* HSD# 203821 Mplayer outputs single buffer including both even and odd fields. */
+ if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+ ovl_cache_tnc->command |= OVL_CMD_ACT_FLD1;
+ /* HSD# 203821 To display odd field, starts from first odd field. */
+ if (0 == src_rect->y1 & 1) {
+ src_rect->y1 += 1;
+ }
+ } else {
+ ovl_cache_tnc->command |= OVL_CMD_ACT_FLD0;
+ /* HSD# 203821 To display even field, starts from first even field. */
+ if (0 != src_rect->y1 & 1) {
+ src_rect->y1 += 1;
+ }
+ }
+ } else {
+ ovl_cache_tnc->command |= OVL_CMD_FRAME_MODE;
+ }
+
+ /* Dest rect information */
+ ovl_cache_tnc->dest_pos_x_left = (unsigned short)dest_rect->x1;
+ ovl_cache_tnc->dest_pos_y_top = (unsigned short)dest_rect->y1;
+ ovl_cache_tnc->dest_width_x =
+ (unsigned short)(dest_rect->x2 - dest_rect->x1);
+ ovl_cache_tnc->dest_height_y =
+ (unsigned short)(dest_rect->y2 - dest_rect->y1);
+
+ /* Src surface offset information */
+ ret = ovl_update_src_ptr_tnc(display, ovl_cache_tnc, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay updating src failed");
+ return ret;
+ }
+
+ /* Src rect and surface information */
+ ret = ovl_update_src_tnc(display, ovl_cache_tnc, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay updating src failed");
+ return ret;
+ }
+
+ /* Scaling information including Vertical downscaling.
+ * Scaling should be guaranteed to work, since if the scale is not
+ * supported, it should have already been blended to a supported scale. */
+ ret = ovl_update_scale_tnc(ovl_cache_tnc, src_surf, src_rect, dest_rect,
+ flags);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay updating scaling failed");
+ return ret;
+ }
+
+ /* Color control information */
+ ret = ovl_update_video_quality_tnc(ovl_cache_tnc, src_surf,
+ &ovl_info->video_quality);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay video quality failed");
+ return ret;
+ }
+ ret = ovl_update_gamma_tnc(display, &ovl_info->gamma);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay gamma failed");
+ return ret;
+ }
+
+ /* Destination color key */
+ EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Dest Color Key");
+ /* The mask and color key are different for the different
+ * pixel formats */
+ ovl_cache_tnc->dest_ckey_val = convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_tnc->dest_ckey_mask = convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_tnc->dest_ckey_mask |= 0x80000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Dest Color Key");
+ ovl_cache_tnc->dest_ckey_mask = 0x00000000;
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ EMGD_DEBUG("Overlay Enable Src Color Key");
+ ovl_cache_tnc->source_ckey_high = ovl_info->color_key.src_hi;
+ ovl_cache_tnc->source_ckey_low = ovl_info->color_key.src_lo;
+
+ ovl_cache_tnc->source_ckey_mask = 0x07000000;
+ } else {
+ EMGD_DEBUG("Overlay Disable Src Color Key");
+ ovl_cache_tnc->source_ckey_mask = 0x00000000;
+ }
+
+ /* Coefficients - Must be after Scaling */
+// ret = ovl_update_coeff_tnc(display, src_surf, src_rect, dest_rect, flags);
+ ret = ovl_update_coeff_tnc(ovl_cache_tnc, src_surf, src_rect, dest_rect, flags);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay updating coefficient failed");
+ return ret;
+ }
+
+ /* Phase information - Must be after Coefficients */
+ ret = ovl_update_phase_tnc(ovl_cache_tnc, src_surf, src_rect);
+ if (ret) {
+ OS_FREE(ovl_cache_tnc);
+ EMGD_ERROR_EXIT("Overlay updating phase failed");
+ return ret;
+ }
+
+ /* General overlay information. Turn the overlay on and alternate
+ * between Buffer 0 and Buffer 1. */
+ ovl_cache_tnc->command = (ovl_cache_tnc->command & 0xfffffff3) |
+ ovl_context->ovl_buff | 1;
+ ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+ /* Dump out the Overlay Update Registers if debugging */
+ EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_tnc(ovl_regs_tnc));
+
+ OS_MEMCPY(ovl_regs_tnc, ovl_cache_tnc, sizeof(ovl_reg_image_tnc_t));
+ OS_FREE(ovl_cache_tnc);
+
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+#else /* new version */
+
+
+/* Atom E6xx cache structure */
+static ovl_tnc_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+
+
+
+static unsigned int ovl_update_regs_tnc(
+ igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ ovl_reg_image_tnc_t *ovl_regs_tnc, *ovl_cache_regs;
+ unsigned int cache_changed;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* get the pointers to the real regs, and our cached copy of them */
+ ovl_regs_tnc = phys_to_virt(ovl_context->reg_update_phys);
+ ovl_cache_regs = &ovl_cache.ovl_regs;
+
+ /* Fast path for turning off overlay. No need for cache */
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+
+ /* Turn the overlay Off */
+ ovl_regs_tnc->command = 0;
+
+ /* if we were using the cache, turn it off there too */
+ if (!ovl_cache_needs_init) {
+ ovl_cache.ovl_regs.command = 0;
+ }
+
+ /* Reset the cache */
+ ovl_cache_needs_init = TRUE;
+
+ /* Always use buf 0 when turning the overlay off. */
+ ovl_context->ovl_buff = 0;
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ /* Force value of y1 to even due hardware expects even number */
+ dest_rect->y1 &= ~1;
+ dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+ dest_rect->x1 &= ~1;
+ dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+ /* Init the cache if necessary */
+ if (ovl_cache_needs_init) {
+ /* Force every cache check to miss */
+ OS_MEMSET(&ovl_cache, 0, sizeof(ovl_tnc_cache_t));
+
+ /* We just set our cached flags to 0, which might accidently
+ * match up with "OFF" for some important incoming flag
+ * bits, causing us to think we already handled them when
+ * we didn't. So set our cached flags to the exact
+ * opposite of the incoming flags, which will force
+ * us to test and handle every single bit, regardless
+ * of whether it is on or off. */
+ ovl_cache.flags = ~flags;
+
+ /* init our cached registers */
+ OS_MEMCPY(ovl_cache_regs,
+ ovl_regs_tnc,
+ sizeof(ovl_reg_image_tnc_t));
+
+ /* initialization complete */
+ ovl_cache_needs_init = FALSE;
+ }
+
+ /* See what has changed in the cache */
+ cache_changed = get_cache_changes_tnc(src_surf,
+ src_rect,
+ dest_rect,
+ ovl_info,
+ flags,
+ &ovl_cache);
+
+ /* Perhaps the biggest challenge of caching the overlay
+ * state is what to do with the command and config regs.
+ * Normally we would clear command and config to 0 here,
+ * and let the update process set only the bits that are
+ * needed. But doing this would invalidate our cache.
+ * Instead we are relying on the above call to
+ * get_cache_changes() to clear those bits in command
+ * and config that will be changing */
+
+ /* Set overlay to the proper pipe */
+ /* it is cheaper to just set this, than to test it and set it. */
+ if (1 == PIPE(display)->pipe_num) {
+ /* This is pipe B */
+ ovl_cache_regs->config |= 1 << 18;
+ } else {
+ ovl_cache_regs->config &= ~(1 << 18);
+ }
+
+ if (cache_changed & IGD_OVL_TNC_UPDATE_FLAGS) {
+ /* Interleaved/progressive and Odd/Even if interleaved. */
+ if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+ ovl_cache_regs->command |= OVL_CMD_FIELD_MODE;
+ /* enable FIELD SYNC OVERLAY FLIP in field mode. */
+ ovl_cache_regs->command |= OVL_CMD_FIELD_SYNC_FLIP;
+ /* HSD# 203821 Mplayer outputs single buffer including both even and odd fields. */
+ if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+ ovl_cache_regs->command |= OVL_CMD_ACT_FLD1;
+ /* HSD: 203821 To display odd field, starts from first odd field. */
+ if (0 == (src_rect->y1 & 1)) {
+ src_rect->y1 += 1;
+ }
+ } else {
+ ovl_cache_regs->command |= OVL_CMD_ACT_FLD0;
+ /* HSD: 203821 To display even field, starts from first even field. */
+ if (0 != (src_rect->y1 & 1)) {
+ src_rect->y1 += 1;
+ }
+ }
+ } else {
+ ovl_cache_regs->command |= OVL_CMD_FRAME_MODE;
+ }
+ }
+
+ /* Has our destination rectangle changed? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_DEST) {
+ ovl_cache_regs->dest_pos_x_left =
+ (unsigned short) dest_rect->x1;
+ ovl_cache_regs->dest_pos_y_top =
+ (unsigned short) dest_rect->y1;
+ ovl_cache_regs->dest_width_x =
+ (unsigned short) (dest_rect->x2 - dest_rect->x1);
+ ovl_cache_regs->dest_height_y =
+ (unsigned short) (dest_rect->y2 - dest_rect->y1);
+
+ }
+
+ /* Always update the source pointers every frame */
+ ret = ovl_update_src_ptr_tnc(display,
+ ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating src pointers failed");
+ return ret;
+ }
+
+ /* Did either the Src rect or surface change? */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_SURF |
+ IGD_OVL_TNC_UPDATE_SRC ) ) {
+
+ ret = ovl_update_src_tnc(display,
+ ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating src failed");
+ return ret;
+ }
+ }
+
+ /* Scaling information including Vertical downscaling.
+ * Scaling should be guaranteed to work, since if the scale
+ * is not supported, it should have already been blended
+ * to a supported scale. */
+ if ( cache_changed & (IGD_OVL_TNC_UPDATE_SRC |
+ IGD_OVL_TNC_UPDATE_SURF | IGD_OVL_TNC_UPDATE_DEST |
+ IGD_OVL_TNC_UPDATE_FLAGS) ) {
+
+ ret = ovl_update_scale_tnc(ovl_cache_regs,
+ src_surf,
+ src_rect,
+ dest_rect,
+ flags);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating scaling failed");
+ return ret;
+ }
+ }
+
+ /* Did video quality change? */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_VQ |
+ IGD_OVL_TNC_UPDATE_SURF ) ) {
+
+ /* Color control information */
+ ret = ovl_update_video_quality_tnc(ovl_cache_regs, src_surf,
+ &ovl_info->video_quality);
+
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay video quality failed");
+ return ret;
+ }
+ }
+
+ /* Did gamma change? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_GAMMA) {
+ ret = ovl_update_gamma_tnc(display, &ovl_info->gamma);
+ if (ret) {
+ /* Not good. Invalidate the entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay gamma failed");
+ return ret;
+ }
+ }
+
+ /* Did color key change? */
+ if (cache_changed & IGD_OVL_TNC_UPDATE_COLORKEY) {
+ /* Destination color key */
+ if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+ /* The mask and color key are different for the
+ * different pixel formats */
+ ovl_cache_regs->dest_ckey_val =
+ convert_color_key_to_hw(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_regs->dest_ckey_mask =
+ convert_color_key_to_mask(
+ PLANE(display)->fb_info->pixel_format,
+ ovl_info->color_key.dest);
+ ovl_cache_regs->dest_ckey_mask |= 0x80000000;
+ } else {
+ ovl_cache_regs->dest_ckey_mask = 0x00000000;
+ }
+
+ /* Source Color key */
+ if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+ ovl_cache_regs->source_ckey_high =
+ ovl_info->color_key.src_hi;
+ ovl_cache_regs->source_ckey_low =
+ ovl_info->color_key.src_lo;
+ ovl_cache_regs->source_ckey_mask = 0x07000000;
+ } else {
+ ovl_cache_regs->source_ckey_mask = 0x00000000;
+ }
+ } /* end color key changes */
+
+ /* Coefficients - Must be after Scaling */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_SRC |
+ IGD_OVL_TNC_UPDATE_SURF | IGD_OVL_TNC_UPDATE_DEST |
+ IGD_OVL_TNC_UPDATE_FLAGS ) ) {
+
+ ret = ovl_update_coeff_tnc(ovl_cache_regs,
+ src_surf,
+ src_rect,
+ dest_rect,
+ flags);
+ if (ret) {
+ /* Not good. Invalidate entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay update coefficient failed");
+ return ret;
+ }
+ }
+
+ /* Phase information - Must be after Coefficients */
+ if (cache_changed & (IGD_OVL_TNC_UPDATE_SRC |
+ IGD_OVL_TNC_UPDATE_SURF ) ) {
+
+ ret = ovl_update_phase_tnc(ovl_cache_regs,
+ src_surf,
+ src_rect);
+ if (ret) {
+ /* Not good. Invalidate entire cache and bail. */
+ ovl_cache_needs_init = TRUE;
+ EMGD_ERROR_EXIT("Overlay updating phase failed");
+ return ret;
+ }
+ }
+
+ /* General overlay information. Turn the overlay on and alternate
+ * between Buffer 0 and Buffer 1. */
+ ovl_cache_regs->command = (ovl_cache_regs->command & 0xfffffff3) |
+ ovl_context->ovl_buff | 1;
+ ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+ /* Dump out the Overlay Update Registers if debugging */
+ EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_tnc(ovl_regs_tnc));
+
+ /* Finally, transfer the cached regs to the real regs */
+ OS_MEMCPY(ovl_regs_tnc,
+ ovl_cache_regs,
+ sizeof(ovl_reg_image_tnc_t));
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+
+}
+#endif
+
+static unsigned int ovl_send_instr_tnc(
+ igd_display_context_t *display,
+ unsigned int flags)
+{
+ unsigned char * mmio = MMIO(display);
+ unsigned long tmp;
+
+ EMGD_TRACE_ENTER;
+
+ /* We dont need the CMD_WAIT_OVL_TNC instruction coz
+ * our alter_ovl code already querried status
+ * for last flip completion before getting here. See
+ * alter_ovl_tnc calling query
+ */
+
+ if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) {
+
+ ovl_context->state = OVL_STATE_ON;
+ /*
+ * If Overlay + FB Blend is requested and the FB is xRGB
+ * turn on the ARGB format.
+ */
+ if(ovl_context->fb_blend_ovl) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x18000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg);
+ EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
+ }
+ }
+
+ } else {
+
+ if (ovl_context->fb_blend_ovl) {
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ if((tmp & 0x3c000000) == 0x1c000000) {
+ tmp = tmp & 0xc3FFFFFF;
+ EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg);
+ EMGD_READ32(mmio + PLANE(display)->plane_reg);
+ tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c);
+ EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c);
+ OS_SLEEP(100);
+ }
+ }
+
+ OS_SLEEP(1);
+
+ /* if overlay is being turned OFF - ensure it's ON first */
+ if (ovl_context->state == OVL_STATE_OFF) {
+ /* Overlay is already off, no need to turn it off again */
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+ }
+
+ ovl_context->state = OVL_STATE_OFF;
+ }
+
+ /* Write the address of the memory buffer to the Overlay Update
+ * Address Register causes the HW to load the new values from the
+ * memory on the next VBLANK */
+
+ EMGD_WRITE32((ovl_context->reg_update_offset | 0x01), mmio + 0x30000);
+
+
+ ovl_context->sync = 0;
+
+ /*
+ display->context->dispatch.sync(display,
+ IGD_PRIORITY_NORMAL,
+ &ovl_context->sync,
+ IGD_SYNC_NONBLOCK);
+ */
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+static int alter_ovl_tnc(igd_display_context_t *display,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags)
+{
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* Check to ensure the overlay can be used given the current mode as
+ * well as what the IAL is asking for. If not return an error. */
+ ret = ovl_check_tnc(display, src_surf, src_rect, dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay Check failed");
+ return ret;
+ }
+
+ /* Check if last flip is still pending.
+ * This is necessary for the following reasons:
+ * - If the previous instructions have not been processed, then the
+ * ovl_regs_tnc is still in use and can not be overwritten.
+ */
+ if ((FALSE == query_ovl_tnc(
+ (igd_display_h)display, IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) &&
+ (flags & IGD_OVL_ALTER_ON)) {
+ /* Only return an error if the overlay is on. If turning it off,
+ * allow it to continue, since something may have failed and we
+ * should try our best to turn the overlay off. */
+ EMGD_ERROR_EXIT("Query Overlay failed");
+ return -IGD_ERROR_HWERROR;
+ }
+
+ /* Update all Overlay Update Registers */
+ ret = ovl_update_regs_tnc(display, src_surf, src_rect, dest_rect, ovl_info,
+ flags);
+ if (ret) {
+ EMGD_ERROR_EXIT("Overlay Update Registers failed");
+ return ret;
+ }
+
+ /* Send the instructions to the command queue */
+ ret = ovl_send_instr_tnc(display, flags);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+
+
+
+static int query_ovl_tnc(igd_display_h display_h,
+ unsigned int flags)
+{
+ igd_display_context_t *display = (igd_display_context_t *)display_h;
+ os_alarm_t timeout;
+
+ EMGD_TRACE_ENTER;
+
+ switch (flags) {
+
+ case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+ /* This is the first overlay, so HW overlay is supported */
+ break;
+
+ case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+
+ /* Check to see if the register update is complete. If not return
+ * FALSE (Flip not done). */
+ if(!(EMGD_READ32(MMIO(display) + 0x30008) & 0x80000000)) {
+ /* This is not an error */
+ return FALSE;
+ }
+
+ /* Now that we know the last flip is done and the register update is
+ * complete, set the sync to 0 and return TRUE (Flip done). */
+ ovl_context->sync = 0;
+ break;
+ case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+ /* Wait for 200 milliseconds for the last flip to complete. If not
+ * done in that time, there is likely a hardware problem so return
+ * FALSE. */
+ timeout = OS_SET_ALARM(200);
+ do {
+ if (TRUE ==
+ query_ovl_tnc(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+ EMGD_TRACE_EXIT;
+ return TRUE;
+ }
+ } while (!OS_TEST_ALARM(timeout));
+ EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+ return FALSE;
+ break;
+ case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+ return TRUE;
+ break;
+ case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+ return TRUE;
+ break;
+ }
+
+ EMGD_TRACE_EXIT;
+ return TRUE;
+}
+
+static int query_max_size_ovl_tnc(
+ igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height)
+{
+ ovl_chipset_tnc_t *ovl_chip;
+
+ EMGD_TRACE_ENTER;
+
+ ovl_chip = ovl_chipset_tnc;
+ *max_width = 0;
+ *max_height = 0;
+ while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+ if(((pf & IGD_PF_MASK) == ovl_chip->pixel_format) &&
+ (ovl_chip->max_width > *max_width)) {
+ *max_width = ovl_chip->max_width;
+ *max_height = ovl_chip->max_height;
+ }
+ ovl_chip++;
+ }
+
+ EMGD_TRACE_EXIT;
+ return IGD_SUCCESS;
+}
+
+/*
+ * enable_direct_display_tnc(): Enables direct display of video DMA input
+ * buffers on the Overlay or Sprite C plane of the specified screen.
+ */
+int enable_direct_display_tnc(void *arg, igd_dd_context_t dd_context)
+{
+ igd_display_context_t *display = (igd_display_context_t *)arg;
+ dd_context_tnc_t *dd_context_ptr;
+#ifdef OVL_DOWNSCALE_X_WORKAROUND
+ int src_w, dest_w, scale, rem, fix_needed;
+#endif
+
+ EMGD_TRACE_ENTER;
+
+ /* Ensure the display context has been set */
+ if (display == NULL) {
+ printk(KERN_ERR "display context (arg) cannot be NULL !\n");
+ return -EINVAL;
+ }
+ /* Ensure the igd context has been set */
+ if (display->context == NULL) {
+ printk(KERN_INFO "igd context cannot be NULL !\n");
+ return -EINVAL;
+ }
+ switch (dd_context.usage) {
+ case IGD_PLANE_OVERLAY_VIDEO:
+ /* Check to see if direct display on Overlay plane is available */
+ if (dd_context_ovl) {
+ printk(KERN_ERR "Overlay direct display already enabled !\n");
+ return -EBUSY;
+ }
+ break;
+ case IGD_PLANE_SPRITE_VIDEO:
+ /* Check to see if direct display on Sprite C plane is available */
+ if (dd_context_ovl2) {
+ printk(KERN_ERR "Overlay direct display already enabled !\n");
+ return -EBUSY;
+ }
+ break;
+ default:
+ printk(KERN_ERR "Invalid direct display usage type (%d) !\n",
+ dd_context.usage);
+ return -EINVAL;
+ }
+ /* Attempt to allocate the direct display context block */
+ dd_context_ptr = OS_ALLOC(sizeof(dd_context_tnc_t));
+ if (dd_context_ptr == NULL) {
+ printk(KERN_ERR "Unable to allocate DD context block !\n");
+ return -ENOMEM;
+ }
+ /* Clear the DD context block and then copy the bridge data into it */
+ OS_MEMSET(dd_context_ptr, 0, sizeof(dd_context_tnc_t));
+ dd_context_ptr->bridge = dd_context;
+
+ /* Initialize color keying, video quality, and gamma */
+ dd_context_ptr->ovl.color_key.src_lo = 0x00000000;
+ dd_context_ptr->ovl.color_key.src_hi = 0x00000000;
+ dd_context_ptr->ovl.color_key.dest = 0xFF00FF; /* customer specified */
+ dd_context_ptr->ovl.color_key.flags = IGD_OVL_DST_COLOR_KEY_DISABLE;
+ dd_context_ptr->ovl.video_quality.contrast = 0x8000;
+ dd_context_ptr->ovl.video_quality.brightness = 0x8000;
+ dd_context_ptr->ovl.video_quality.saturation = 0x8000;
+ dd_context_ptr->ovl.video_quality.hue = 0x8000;
+ dd_context_ptr->ovl.gamma.red = 0x100;
+ dd_context_ptr->ovl.gamma.green = 0x100;
+ dd_context_ptr->ovl.gamma.blue = 0x100;
+ dd_context_ptr->ovl.gamma.flags = IGD_OVL_GAMMA_DISABLE;
+
+ /* Ensure source rectangle starts on even coordinates */
+ dd_context_ptr->bridge.src.x1 = (dd_context_ptr->bridge.src.x1 + 1) & ~1;
+ dd_context_ptr->bridge.src.y1 = (dd_context_ptr->bridge.src.y1 + 1) & ~1;
+
+ /* Ensure destination rectangle starts on even coordinates */
+ dd_context_ptr->bridge.dest.x1 = (dd_context_ptr->bridge.dest.x1 + 1) & ~1;
+ dd_context_ptr->bridge.dest.y1 = (dd_context_ptr->bridge.dest.y1 + 1) & ~1;
+
+ /* Initialize the generic rendering surface attributes */
+ dd_context_ptr->surf.width = dd_context_ptr->bridge.src.x2 -
+ dd_context_ptr->bridge.src.x1 + 1;
+ dd_context_ptr->surf.height = dd_context_ptr->bridge.src.y2 -
+ dd_context_ptr->bridge.src.y1 + 1;
+ dd_context_ptr->surf.flags = IGD_OVL_ALTER_ON;
+ dd_context_ptr->surf.pitch = dd_context.video_pitch;
+
+#ifdef OVL_DOWNSCALE_X_WORKAROUND
+ src_w = dd_context_ptr->surf.width;
+ dest_w = dd_context_ptr->bridge.dest.x2 - dd_context_ptr->bridge.dest.x1 + 1;
+ scale = src_w / dest_w;
+ rem = src_w % dest_w;
+ fix_needed = 0;
+
+ /*
+ * If downscaling along the X dimension we need to avoid scale factors
+ * that are greater than 4 and less than 9, and greater than 12. The
+ * issue is with the destination rectangle, so we leave the source
+ * rectangle as specified, and expand the destination rectangle to be
+ * exactly 4 or 12 times smaller. We have to adjust the start and/or
+ * end position accordingly, so that it fits within the screen bounds.
+ */
+ if (src_w > dest_w) {
+ if ((scale > 4 && scale < 9) || (scale == 4 && rem)) {
+ /* Force a scale factor of 4 here */
+ dest_w = src_w / 4;
+ fix_needed = 1;
+ } else if ((scale > 12) || (scale == 12 && rem)) {
+ /* Force a scale factor of 12 here */
+ dest_w = src_w / 12;
+ fix_needed = 1;
+ }
+ if (fix_needed) {
+ /* Adjust the destination X endpoint */
+ dd_context_ptr->bridge.dest.x2 =
+ dd_context_ptr->bridge.dest.x1 + dest_w - 1;
+
+ /* Ensure rectangle X coordinates fit on screen */
+ if (dd_context_ptr->bridge.dest.x2 >=
+ dd_context_ptr->bridge.screen_w) {
+ /* Adjust X end position to screen edge */
+ dd_context_ptr->bridge.dest.x2 =
+ dd_context_ptr->bridge.screen_w - 1;
+ /* Adjust X start position according to width */
+ dd_context_ptr->bridge.dest.x1 =
+ dd_context_ptr->bridge.dest.x2 - dest_w + 1;
+ }
+ }
+ }
+#endif
+ if (dd_context.usage == IGD_PLANE_OVERLAY_VIDEO) {
+ /* Initialize the YUV422-specific surface attributes */
+ dd_context_ptr->surf.pixel_format = IGD_PF_YUV422_PACKED_UYVY;
+
+ /* Save this pointer as our Overlay context */
+ dd_context_ovl = dd_context_ptr;
+ } else {
+ /* Initialize the RGB565-specific surface attributes */
+ dd_context_ptr->surf.pixel_format = IGD_PF_RGB16_565;
+ dd_context_ptr->surf.pitch *= 2; /* RGB565 = 2 Bpp */
+
+ /* Save this pointer as our Overlay 2 (Sprite C) context */
+ dd_context_ovl2 = dd_context_ptr;
+ }
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+EXPORT_SYMBOL(enable_direct_display_tnc);
+
+
+/*
+ * disable_direct_display_tnc(): Disables direct display of video on the
+ * Overlay plane or Sprite C plane.
+ */
+int disable_direct_display_tnc(void *arg, int usage)
+{
+ igd_display_context_t *display = (igd_display_context_t *)arg;
+ dd_context_tnc_t *dd_context_ptr;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* Ensure the display context has been set */
+ if (display == NULL) {
+ printk(KERN_ERR "Display context (arg) cannot be NULL !\n");
+ return -EINVAL;
+ }
+ /* Set the direct display context pointer according to the usage arg */
+ dd_context_ptr =
+ (usage == IGD_PLANE_OVERLAY_VIDEO) ? dd_context_ovl : dd_context_ovl2;
+
+ /* Ensure this direct display context pointer is set */
+ if (dd_context_ptr == NULL) {
+ printk(KERN_ERR "%s direct display not currently enabled !\n",
+ (usage == IGD_PLANE_OVERLAY_VIDEO) ? "Overlay" : "Sprite C");
+ return -EINVAL;
+ }
+ /* Set the flag to turn Overlay/Sprite C off */
+ dd_context_ptr->surf.flags = IGD_OVL_ALTER_OFF;
+
+ /* Check the DD context being referenced */
+ if (usage == IGD_PLANE_OVERLAY_VIDEO) {
+ /* Disable the display of the Overlay plane */
+ ret = alter_ovl_tnc(display, &dd_context_ovl->surf,
+ &dd_context_ovl->bridge.src, &dd_context_ovl->bridge.dest,
+ &dd_context_ovl->ovl, dd_context_ovl->surf.flags);
+
+ /* Mark the Overlay direct display context as invalid */
+ dd_context_ovl = NULL;
+ } else {
+ /* Disable the display of the Sprite C plane */
+ ret = alter_ovl2_tnc(display, &dd_context_ovl2->surf,
+ &dd_context_ovl2->bridge.src, &dd_context_ovl2->bridge.dest,
+ &dd_context_ovl2->ovl, dd_context_ovl2->surf.flags);
+
+ /* Mark the Sprite C direct display context as invalid */
+ dd_context_ovl2 = NULL;
+ }
+ /* Deallocate the DD context block for the direct display plane */
+ OS_FREE(dd_context_ptr);
+
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+EXPORT_SYMBOL(disable_direct_display_tnc);
+
+
+/*
+ * direct_display_frame_tnc(): Performs the direct display of the new frame
+ * of video data on the Overlay plane or Sprite C plane.
+ */
+int direct_display_frame_tnc(void *arg, int usage, unsigned long offset)
+{
+ igd_display_context_t *display = (igd_display_context_t *)arg;
+ dd_context_tnc_t *dd_context_ptr;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ /* Ensure the display context is set */
+ if (display == NULL) {
+ printk(KERN_ERR "display context cannot be NULL !!!\n");
+ return -EINVAL;
+ }
+ /* Set the direct display context pointer according to the usage arg */
+ dd_context_ptr =
+ (usage == IGD_PLANE_OVERLAY_VIDEO) ? dd_context_ovl : dd_context_ovl2;
+
+ /* Ensure this direct display context pointer is set */
+ if (dd_context_ptr == NULL) {
+ printk(KERN_ERR "%s direct display context not set !\n",
+ (usage == IGD_PLANE_OVERLAY_VIDEO) ? "Overlay" : "Sprite C");
+ return -EINVAL;
+ }
+
+ /* Update the surface offset corresponding to this new frame */
+ dd_context_ptr->surf.offset = offset;
+
+ if (usage == IGD_PLANE_OVERLAY_VIDEO) {
+ /* display the new video frame on the Overlay plane */
+ ret = alter_ovl_tnc(display, &dd_context_ovl->surf,
+ &dd_context_ovl->bridge.src, &dd_context_ovl->bridge.dest,
+ &dd_context_ovl->ovl, dd_context_ovl->surf.flags);
+ } else {
+ /* display the new video frame on the Sprite C plane */
+ ret = alter_ovl2_tnc(display, &dd_context_ovl2->surf,
+ &dd_context_ovl2->bridge.src, &dd_context_ovl2->bridge.dest,
+ &dd_context_ovl2->ovl, dd_context_ovl2->surf.flags);
+ }
+ EMGD_TRACE_EXIT;
+ return ret;
+}
+EXPORT_SYMBOL(direct_display_frame_tnc);
+/*
+ * ovl_set_dest_colorkey_tnc(): Performs the enable or disable colorkey on the Overlay plane.
+ */
+int ovl_set_dest_colorkey_tnc(igd_dd_context_t dd_context, igd_ovl_color_key_info_t *color_key)
+{
+ EMGD_TRACE_ENTER;
+ switch (dd_context.usage) {
+ case IGD_PLANE_OVERLAY_VIDEO:
+ /* Check to see if direct display on Overlay plane is available */
+ if (!dd_context_ovl) {
+ printk(KERN_ERR "Overlay direct display = NULL !\n");
+ return -EINVAL;
+ }
+
+ dd_context_ovl->ovl.color_key.dest = color_key->dest;
+ dd_context_ovl->ovl.color_key.flags = color_key->flags;
+ break;
+ case IGD_PLANE_SPRITE_VIDEO:
+ /* Check to see if direct display on Sprite C plane is available */
+ if (!dd_context_ovl2) {
+ printk(KERN_ERR "Overlay direct display2 = NULL !\n");
+ return -EINVAL;
+ }
+
+ dd_context_ovl2->ovl.color_key.dest = color_key->dest;
+ dd_context_ovl2->ovl.color_key.flags = color_key->flags;
+ break;
+ default:
+ printk(KERN_ERR "Invalid direct display usage type (%d) !\n",
+ dd_context.usage);
+ return -EINVAL;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+EXPORT_SYMBOL(ovl_set_dest_colorkey_tnc);
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
new file mode 100644
index 0000000..f3d162e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
@@ -0,0 +1,244 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_tnc_cache.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Support functions for overlay caching.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.overlay
+
+#include "ovl_tnc_cache.h"
+
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_tnc(igd_rect_t *src_rect, povl_tnc_cache_t ovl_cache)
+{
+ if (src_rect) {
+ OS_MEMCPY(&ovl_cache->src_rect,
+ src_rect,
+ sizeof(igd_rect_t));
+ } else {
+ OS_MEMSET(&ovl_cache->src_rect,
+ 0,
+ sizeof(igd_rect_t));
+ }
+}
+
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_tnc( igd_rect_t *dest_rect, povl_tnc_cache_t ovl_cache)
+{
+ if (dest_rect) {
+ OS_MEMCPY(&ovl_cache->dest_rect,
+ dest_rect,
+ sizeof(igd_rect_t));
+ } else {
+ OS_MEMSET(&ovl_cache->dest_rect,
+ 0,
+ sizeof(igd_rect_t));
+ }
+}
+
+
+/* Copies a surface to the cache */
+void copy_surf_tnc(igd_surface_t *src_surf, povl_tnc_cache_t ovl_cache)
+{
+ if (src_surf) {
+ OS_MEMCPY(&ovl_cache->src_surf,
+ src_surf,
+ sizeof(igd_surface_t));
+ } else {
+ OS_MEMSET(&ovl_cache->src_surf,
+ 0,
+ sizeof(igd_surface_t));
+ }
+}
+
+
+/* Copies the color key to the cache */
+void copy_color_key_tnc( igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.color_key,
+ &(ovl_info->color_key),
+ sizeof(igd_ovl_color_key_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.color_key,
+ 0,
+ sizeof(igd_ovl_color_key_info_t));
+ }
+}
+
+
+/* Copies the video quality info to the cache */
+void copy_vq_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.video_quality,
+ &(ovl_info->video_quality),
+ sizeof(igd_ovl_video_quality_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.video_quality,
+ 0,
+ sizeof(igd_ovl_video_quality_info_t));
+ }
+}
+
+
+/* Copies the gamma to the cache */
+void copy_gamma_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache)
+{
+ if (ovl_info) {
+ OS_MEMCPY(&ovl_cache->ovl_info.gamma,
+ &(ovl_info->gamma),
+ sizeof(igd_ovl_gamma_info_t));
+ } else {
+ OS_MEMSET(&ovl_cache->ovl_info.gamma,
+ 0,
+ sizeof(igd_ovl_gamma_info_t));
+ }
+}
+
+
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_tnc(
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags,
+ povl_tnc_cache_t ovl_cache)
+{
+ unsigned int cache_changed = 0;
+
+ /* Have the flags changed? */
+ if (ovl_cache->flags != flags) {
+
+ /* NOTE that we did not check which flags changed.
+ Currently if any flag changes, we invalidate all
+ the flags. We could further optimize caching if
+ we tested for individual flag changes, but I don't
+ think it will really help much. Once a movie starts
+ playing, it pretty much uses the same flags
+ for its entire duration, unless the user is mucking
+ about with it as it plays, in which case it's going
+ to be slow anyway. */
+
+
+ ovl_cache->flags = flags;
+ cache_changed |= IGD_OVL_TNC_UPDATE_FLAGS;
+
+ /* Invalidating the flags cache will cause the following
+ * bits to be re-calculated. Clear them in preparation for
+ * re-calculation. */
+ ovl_cache->ovl_regs.command &= ~ (OVL_CMD_FRAME_MODE |
+ OVL_CMD_FIELD_MODE |
+ OVL_CMD_FIELD_SYNC_FLIP |
+ OVL_CMD_ACT_FLD1 |
+ OVL_CMD_ACT_FLD0 );
+ }
+
+ /* Do a comparison to source surface */
+ if (is_changed_surf(&ovl_cache->src_surf, src_surf)) {
+ cache_changed |= IGD_OVL_TNC_UPDATE_SURF;
+ copy_surf_tnc(src_surf, ovl_cache);
+
+ /* invalidating the source surface will cause the driver
+ * to recalculate the following bits in command */
+ ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422 |
+ OVL_CMD_YUV_420P |
+ OVL_CMD_YUV_410P |
+ OVL_CMD_YUV_NV12 |
+ OVL_CMD_Y_SWAP |
+ OVL_CMD_UV_SWAP |
+ OVL_CMD_RGB_8888 |
+ OVL_CMD_RGB_565 |
+ OVL_CMD_RGB_555 );
+
+ /* Invalidating the source surface will cause the driver
+ * to recalculate the following bits in config */
+ ovl_cache->ovl_regs.config &= ~ ( (1<<4) |
+ OVL_CONFIG_LINE_BUFF_MASK );
+
+ }
+
+ /* Do a comparison to source rectangle */
+ if (is_changed_rect(&ovl_cache->src_rect, src_rect)) {
+ cache_changed |= IGD_OVL_TNC_UPDATE_SRC;
+ copy_src_rect_tnc(src_rect, ovl_cache);
+
+ /* invalidating the source rectangle will cause the driver
+ * to recalculate the following bits in command */
+ ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422 |
+ OVL_CMD_YUV_420P |
+ OVL_CMD_YUV_410P |
+ OVL_CMD_YUV_NV12 |
+ OVL_CMD_Y_SWAP |
+ OVL_CMD_UV_SWAP |
+ OVL_CMD_RGB_8888 |
+ OVL_CMD_RGB_565 |
+ OVL_CMD_RGB_555 );
+
+ /* Invalidating the source rectangle will cause the driver
+ * to recalculate the following bits in config */
+ ovl_cache->ovl_regs.config &= ~ ( (1<<4) |
+ OVL_CONFIG_LINE_BUFF_MASK );
+
+
+ }
+
+ /* Has our destination rectangle changed? */
+ if (is_changed_rect(&ovl_cache->dest_rect, dest_rect)) {
+ cache_changed |= IGD_OVL_TNC_UPDATE_DEST;
+ copy_dest_rect_tnc(dest_rect, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info color key */
+ if (is_changed_color_key(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= (IGD_OVL_TNC_UPDATE_INFO |
+ IGD_OVL_TNC_UPDATE_COLORKEY);
+ copy_color_key_tnc(ovl_info, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info video quality */
+ if (is_changed_vq(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= ( IGD_OVL_TNC_UPDATE_INFO |
+ IGD_OVL_TNC_UPDATE_VQ);
+ copy_vq_tnc(ovl_info, ovl_cache);
+ }
+
+ /* Do a comparison to overlay info gamma */
+ if (is_changed_gamma(&ovl_cache->ovl_info, ovl_info)) {
+ cache_changed |= ( IGD_OVL_TNC_UPDATE_INFO |
+ IGD_OVL_TNC_UPDATE_GAMMA);
+ copy_gamma_tnc(ovl_info, ovl_cache);
+ }
+
+ return cache_changed;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
new file mode 100644
index 0000000..0df413a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
@@ -0,0 +1,162 @@
+/*
+ *----------------------------------------------------------------------------
+ * Filename: ovl_tnc_cache.h
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the internal header file for overlay caching. It should be not be
+ * by any other module besides the overlay module itself.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL_TNC_CACHE_H
+#define _OVL_TNC_CACHE_H
+
+#include <rb.h>
+#include "ovl_regs_tnc.h"
+#include "ovl2_regs_tnc.h"
+
+/* Turns the overlay cache on and off. */
+#define OVL_TNC_CACHE_QUICK_SWAP
+
+
+/*
+ * In order to cache the overlay registers we need a structure
+ * that defines and wraps them. We already have one for the primary
+ * display, called ovl_reg_image_tnc_t.
+ * Here we define a structure for the secondary display
+ */
+
+typedef struct _ovl2_reg_tnc_cache{
+ unsigned long control;
+ unsigned long start;
+ unsigned long plane_control;
+ unsigned long plane_start;
+ unsigned long linear_offset;
+ unsigned long tiled_offset;
+
+ unsigned long pitch;
+ unsigned long dest_rect_x1y1;
+ unsigned long dest_rect_w_h;
+ unsigned long cont_bright;
+ unsigned long satn_hue;
+ unsigned long gamma_regs[OVL2_TOTAL_GAMMA_REG];
+ unsigned long colorkey_hw;
+ unsigned long colorkey_mask;
+ unsigned long ckey_high;
+ unsigned long ckey_low;
+ unsigned long ckey_enable;
+} ovl2_reg_tnc_cache_t;
+
+#define MMIO_OFFSET_TNC2_CONTROL 0x72180
+#define MMIO_OFFSET_TNC2_LINEAR_OFF 0x72184
+#define MMIO_OFFSET_TNC2_PITCH 0x72188
+#define MMIO_OFFSET_TNC2_DEST_RECT_X1Y1 0x7218C
+#define MMIO_OFFSET_TNC2_DEST_RECT_W_H 0x72190
+#define MMIO_OFFSET_TNC2_CKEY_LOW 0x72194
+#define MMIO_OFFSET_TNC2_CKEY_ENABLE 0x72198
+#define MMIO_OFFSET_TNC2_SURF_ADDR 0x7219C
+#define MMIO_OFFSET_TNC2_CKEY_HIGH 0x721A0
+#define MMIO_OFFSET_TNC2_DSPC_TILE_OFF 0x721A4
+#define MMIO_OFFSET_TNC2_CONT_BRIGHT 0x721D0
+#define MMIO_OFFSET_TNC2_SATN_HUE 0x721D4
+#define MMIO_OFFSET_TNC2_COLORKEY_HW 0x14
+#define MMIO_OFFSET_TNC2_COLORKEY_MASK 0x18
+
+/*
+ * This stucture caches the overlay state, so we don't have to
+ * re-program everything for every single frame
+ */
+typedef struct _ovl_tnc_cache {
+ igd_surface_t src_surf;
+ igd_rect_t src_rect;
+ igd_rect_t dest_rect;
+ igd_ovl_info_t ovl_info;
+ unsigned long flags;
+ ovl_reg_image_tnc_t ovl_regs;
+ ovl2_reg_tnc_cache_t ovl2_regs;
+} ovl_tnc_cache_t, *povl_tnc_cache_t;
+
+
+/* Flags for things that might have changed in the cache */
+#define IGD_OVL_TNC_UPDATE_DEST (1 << 0)
+#define IGD_OVL_TNC_UPDATE_SRC (1 << 1)
+#define IGD_OVL_TNC_UPDATE_SURF (1 << 2)
+#define IGD_OVL_TNC_UPDATE_INFO (1 << 3)
+#define IGD_OVL_TNC_UPDATE_FLAGS (1 << 4)
+#define IGD_OVL_TNC_UPDATE_VQ (1 << 5)
+#define IGD_OVL_TNC_UPDATE_GAMMA (1 << 6)
+#define IGD_OVL_TNC_UPDATE_COLORKEY (1 << 7)
+
+
+/*
+ * Caching helper functions. Implemented in ovl_tnc.c, but used by
+ * the ovl2 and micro_ovl modules as well.
+ */
+
+/* Tells if a rectangle has changed */
+int is_changed_rect(igd_rect_t *old_rect, igd_rect_t *new_rect);
+
+/* Tells if a surface has changed */
+int is_changed_surf(igd_surface_t *old_surf, igd_surface_t *new_surf);
+
+/* Tells if the color key has changed */
+int is_changed_color_key(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the video quality has changed */
+int is_changed_vq(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the gamma has changed */
+int is_changed_gamma(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_tnc(igd_rect_t *src_rect, povl_tnc_cache_t ovl_cache);
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_tnc( igd_rect_t *dest_rect, povl_tnc_cache_t ovl_cache);
+
+/* Copies a surface to the cache */
+void copy_surf_tnc(igd_surface_t *src_surf, povl_tnc_cache_t ovl_cache);
+
+/* Copies the color key to the cache */
+void copy_color_key_tnc( igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Copies the video quality info to the cache */
+void copy_vq_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Copies the gamma to the cache */
+void copy_gamma_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_tnc(
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags,
+ povl_tnc_cache_t ovl_cache);
+
+
+
+#endif /* _OVL_TNC_CACHE_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
new file mode 100644
index 0000000..89b8fcf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
@@ -0,0 +1,342 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: topaz.c
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+#include <topaz.h>
+#include "topaz_hdr.h"
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#define MAX_CURRENT_TOPAZ_CMD_SIZE 5
+#define MAX_TOPAZ_CMD_SIZE 0x20
+
+void write_mtx_mem_multiple_setup(igd_context_t *context,
+ unsigned long addr)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long bank_size;
+ unsigned long ram_size;
+ unsigned long ram_id;
+ unsigned long reg;
+ unsigned long ctrl = 0;
+
+ reg = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+
+ reg = 0x0a0a0606;
+ bank_size = (reg & 0xf0000) >> 16;
+
+ ram_size = (unsigned long) (1 << (bank_size + 2));
+ ram_id = (addr - MTX_DATA_BASE) / ram_size;
+
+ /* cmd id */
+ ctrl = ((0x18 + ram_id) << 20) & 0x0ff00000;
+ /* Address to read */
+ ctrl |= ((addr >> 2) << 2) & 0x000ffffc;
+ ctrl |= 0x02;
+ /*printk(KERN_INFO "write_mtx_multiple_setup: ctrl=0x%08x, addr=0x%08x", ctrl, addr);*/
+ EMGD_WRITE32(ctrl, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+
+ return;
+}
+
+void write_mtx_mem_multiple(igd_context_t *context,
+ unsigned long cmd)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+
+ EMGD_WRITE32(cmd, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_DATA_TRANSFER);
+}
+
+/*
+ * This is the function that actually passes the message to the MTX
+ * firmware. The contents of the message are opaque to this function.
+ *
+ * Currently, the only supported message type is RENDER.
+ */
+int mtx_send_tnc(igd_context_t *context, unsigned long *msg)
+{
+ struct topaz_cmd_header *cur_cmd_header =
+ (struct topaz_cmd_header *) msg;
+ unsigned long cmd_size = cur_cmd_header->size;
+ unsigned long read_index, write_index;
+ const unsigned long *cmd_pointer = (unsigned long *)msg;
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+ int ret = 0;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ write_index = topaz_priv->topaz_cmd_windex;
+ if (write_index + cmd_size + 1 > topaz_priv->topaz_ccb_size)
+ {
+ int free_space = topaz_priv->topaz_ccb_size - write_index;
+
+ EMGD_DEBUG("TOPAZ: wrap CCB write point");
+ if (free_space > 0)
+ {
+ struct topaz_cmd_header pad_cmd;
+
+ pad_cmd.id = MTX_CMDID_NULL;
+ pad_cmd.size = free_space;
+ pad_cmd.seq = 0x7fff & topaz_priv->topaz_cmd_seq++;
+
+ EMGD_DEBUG("TOPAZ: MTX_CMDID_NULL:"
+ " size(%d),seq (0x%04x)\n",
+ pad_cmd.size, pad_cmd.seq);
+
+ TOPAZ_BEGIN_CCB(context);
+ TOPAZ_OUT_CCB(context, pad_cmd.val);
+ TOPAZ_END_CCB(context, 1);
+ }
+ POLL_WB_RINDEX(context, 0);
+ if (ret == 0) {
+ topaz_priv->topaz_cmd_windex = 0;
+ } else {
+ printk(KERN_ERR "TOPAZ: poll rindex timeout\n");
+ return ret; /* HW may hang, need reset */
+ }
+ EMGD_DEBUG("TOPAZ: -------wrap CCB was done.\n");
+ }
+
+ read_index = CCB_CTRL_RINDEX(context);/* temperily use CCB CTRL */
+ write_index = topaz_priv->topaz_cmd_windex;
+
+ /*printk(KERN_INFO "TOPAZ: write index(%ld), read index(%ld,WB=%ld)\n",
+ write_index, read_index, WB_CCB_CTRL_RINDEX(context));
+ printk(KERN_INFO "cmd size to kick %d",cmd_size);
+ for(count=0;count<cmd_size;count++){
+ printk(KERN_INFO "value to kick 0x%08x", *(cmd_pointer+count));
+ }*/
+
+ TOPAZ_BEGIN_CCB(context);
+ while (cmd_size > 0) {
+ TOPAZ_OUT_CCB(context, *cmd_pointer++);
+ --cmd_size;
+ }
+ TOPAZ_END_CCB(context, 1);
+
+ /*POLL_WB_RINDEX(context, topaz_priv->topaz_cmd_windex);
+ printk(KERN_INFO "RI after kick =%ld", CCB_CTRL_RINDEX(context));*/
+
+
+#if 0 /* kept for memory callback test */
+ for (i = 0; i < 100; i++) {
+ if (WB_CCB_CTRL_RINDEX(context) == topaz_priv->topaz_cmd_windex)
+ break;
+ else
+ OS_SLEEP(100);
+ }
+ if (WB_CCB_CTRL_RINDEX(context) != topaz_priv->topaz_cmd_windex) {
+ EMGD_ERROR("TOPAZ: poll rindex timeout\n");
+ ret = -IGD_ERROR_HWERROR;
+ }
+#endif
+
+ return ret;
+}
+
+void topaz_sync_tnc(igd_context_t *context)
+{
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+ unsigned long sync_cmd[3];
+ unsigned long *sync_p, temp_ret;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+ sync_p = (unsigned long *)topaz_priv->topaz_sync_addr;
+ topaz_priv->topaz_sync_id++;
+
+ /* insert a SYNC command here */
+ topaz_priv->topaz_sync_cmd_seq = (1 << 15) |
+ topaz_priv->topaz_cmd_seq++;
+ sync_cmd[0] = (MTX_CMDID_SYNC << 1) | (3 << 8) |
+ (topaz_priv->topaz_sync_cmd_seq << 16);
+ sync_cmd[1] = topaz_priv->topaz_sync_offset;
+ sync_cmd[2] = topaz_priv->topaz_sync_id;
+ temp_ret = mtx_send_tnc(context, sync_cmd);
+ if (0 != temp_ret){
+ EMGD_DEBUG("TOPAZ: sync error: %ld\n", temp_ret);
+ }
+
+ topaz_priv->topaz_frame_skip = CCB_CTRL_FRAMESKIP(context);
+
+#if 0
+ /* debug code to make sure SYNC can be done */
+ {
+ int count = 1000;
+ while (count && *sync_p != topaz_priv->topaz_sync_id) {
+ OS_SLEEP(1000);
+ --count;
+ }
+ if ((count == 0) && (*sync_p != 0x45)) {
+ EMGD_ERROR("TOPAZ: wait sync timeout (0x%08x),"
+ "actual 0x%08x\n",
+ topaz_priv->topaz_sync_id, *sync_p);
+ }
+ }
+#endif
+
+}
+
+
+/*
+ * To process this buffer, find the MTX firmware messages and send each
+ * one to the MTX firmware.
+ */
+
+int process_encode_mtx_messages(igd_context_t *context,
+ unsigned long *mtx_buf,
+ unsigned long size)
+{
+ unsigned long *command = (unsigned long *) mtx_buf;
+ unsigned long cmd_size = 0;
+ int ret = 0;
+ struct topaz_cmd_header *cur_cmd_header;
+ unsigned long cur_cmd_size, cur_cmd_id;
+ unsigned long codec;
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ cur_cmd_header = (struct topaz_cmd_header *) command;
+
+ if(!cur_cmd_header) {
+ printk(KERN_ERR "TOPAZ: Invalid Command\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ cur_cmd_size = cur_cmd_header->size;
+ cur_cmd_id = cur_cmd_header->id;
+
+ /* Verify the incoming current command size */
+ if((cur_cmd_size == 0) || (cur_cmd_size > MAX_CURRENT_TOPAZ_CMD_SIZE)) {
+ printk(KERN_ERR "TOPAZ: Invalid Command Size\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ while (cur_cmd_id != MTX_CMDID_NULL) {
+
+ switch (cur_cmd_id) {
+ case MTX_CMDID_SW_NEW_CODEC:
+ codec = *((unsigned long *) mtx_buf + 1);
+ EMGD_DEBUG("TOPAZ: setup new codec %ld\n", codec);
+ if (topaz_setup_fw(context, codec)) {
+ printk(KERN_ERR "TOPAZ: upload FW to HW failed\n");
+ return -IGD_ERROR_INVAL;
+ }
+ topaz_priv->topaz_cur_codec = codec;
+ break;
+ case MTX_CMDID_SW_ENTER_LOWPOWER:
+ EMGD_DEBUG("TOPAZ: enter lowpower.... \n");
+ EMGD_DEBUG("XXX: implement it\n");
+ break;
+ case MTX_CMDID_SW_LEAVE_LOWPOWER:
+ EMGD_DEBUG("TOPAZ: leave lowpower... \n");
+ EMGD_DEBUG("XXX: implement it\n");
+ break;
+ /* ordinary commmand */
+ case MTX_CMDID_START_PIC:
+ /* XXX: specially handle START_PIC hw command */
+ CCB_CTRL_SET_QP(context,
+ *(command + cur_cmd_size - 1));
+ /* strip the QP parameter (it's software arg) */
+ cur_cmd_header->size--;
+ case MTX_CMDID_DO_HEADER:
+ case MTX_CMDID_ENCODE_SLICE:
+ case MTX_CMDID_END_PIC:
+ case MTX_CMDID_SYNC:
+ case MTX_CMDID_ENCODE_ONE_ROW:
+ case MTX_CMDID_FLUSH:
+
+ cur_cmd_header->seq = 0x7fff &
+ topaz_priv->topaz_cmd_seq++;
+ EMGD_DEBUG("TOPAZ: %ld: size(%ld), seq (0x%04x)\n",
+ cur_cmd_id, cur_cmd_size, cur_cmd_header->seq);
+ ret = mtx_send_tnc(context, command);
+ if (ret) {
+ printk(KERN_ERR "TOPAZ: error -- ret(%d)\n", ret);
+ return -IGD_ERROR_INVAL;
+ }
+ break;
+ default:
+ printk(KERN_ERR "TOPAZ: Invalid Command\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* current command done */
+ command += cur_cmd_size;
+ cmd_size += cur_cmd_size;
+
+ /* Verify that the incoming commands are of reasonable size */
+ if((cmd_size >= MAX_TOPAZ_CMD_SIZE)) {
+ printk(KERN_ERR "TOPAZ: Invalid Command Size\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ /* Get next command */
+ cur_cmd_header = (struct topaz_cmd_header *) command;
+
+ if(!cur_cmd_header) {
+ printk(KERN_ERR "TOPAZ: Invalid Command\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ cur_cmd_size = cur_cmd_header->size;
+ cur_cmd_id = cur_cmd_header->id;
+
+ /* Verify the incoming current command size */
+ if((cur_cmd_size == 0) || (cur_cmd_size > MAX_CURRENT_TOPAZ_CMD_SIZE)) {
+ printk(KERN_ERR "TOPAZ: Invalid Command Size\n");
+ return -IGD_ERROR_INVAL;
+ }
+
+ }
+ topaz_sync_tnc(context);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
new file mode 100644
index 0000000..3545684
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
@@ -0,0 +1,128 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: topaz_hdr.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef TOPAZ_HDR_H
+#define TOPAZ_HDR_H
+
+#define MTX_CCBCTRL_ROFF 0
+#define MTX_CCBCTRL_COMPLETE 4
+#define MTX_CCBCTRL_CCBSIZE 8
+#define MTX_CCBCTRL_QP 12
+#define MTX_CCBCTRL_FRAMESKIP 20
+#define MTX_CCBCTRL_INITQP 24
+
+#define TOPAZ_CTX(ctx) \
+ ((platform_context_tnc_t *)(ctx)->platform_context)->tpz_private_data
+
+
+#define TOPAZ_BEGIN_CCB(ctx) \
+ write_mtx_mem_multiple_setup((ctx), \
+ TOPAZ_CTX((ctx)).topaz_ccb_buffer_addr + \
+ TOPAZ_CTX((ctx)).topaz_cmd_windex * 4)
+
+#define TOPAZ_OUT_CCB(ctx, cmd) \
+ write_mtx_mem_multiple((ctx), (cmd)); \
+ TOPAZ_CTX((ctx)).topaz_cmd_windex++;
+
+#define TOPAZ_END_CCB(ctx, kick_cnt) \
+ EMGD_WRITE32(1, (ctx)->device_context.virt_mmadr + TNC_TOPAZ_MTX_KICK);
+
+/* macros to get/set CCB control data */
+#define WB_CCB_CTRL_RINDEX(ctx) \
+*((unsigned long *)TOPAZ_CTX(ctx).topaz_ccb_wb)
+
+#define WB_CCB_CTRL_SEQ(ctx) \
+*((unsigned long *)(TOPAZ_CTX(ctx).topaz_ccb_wb + 1))
+
+/* HACK: temporary turn off MMU bypass to POLL, then turn on
+#define POLL_WB_RINDEX(ctx, value) \
+do { \
+ int i; \
+ unsigned char *mmio = ctx->device_context.virt_mmadr; \
+ EMGD_WRITE32(0x00000000, mmio + TNC_TOPAZ_MMU_CONTROL0);\
+ for (i = 0; i < 10000; i++) { \
+ if (CCB_CTRL_RINDEX(ctx) == value) \
+ break; \
+ else \
+ OS_SLEEP(100); \
+ } \
+ if (CCB_CTRL_RINDEX(ctx) != value) { \
+ EMGD_ERROR("TOPAZ: poll rindex timeout\n"); \
+ ret = -IGD_ERROR_HWERROR; \
+ } \
+ EMGD_WRITE32(0x00000800, mmio + TNC_TOPAZ_MMU_CONTROL0);\
+} while (0)*/
+
+#define POLL_WB_RINDEX(ctx, value) \
+do { \
+ int i; \
+ for (i = 0; i < 10000; i++) { \
+ if (CCB_CTRL_RINDEX(ctx) == value) \
+ break; \
+ else \
+ OS_SLEEP(100); \
+ } \
+ if (CCB_CTRL_RINDEX(ctx) != value) { \
+ EMGD_ERROR("TOPAZ: poll rindex timeout\n"); \
+ ret = -IGD_ERROR_HWERROR; \
+ } \
+} while (0)
+
+#define CCB_CTRL_RINDEX(ctx) \
+ read_mtx_mem(ctx, \
+ TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_ROFF)
+
+#define CCB_CTRL_SET_QP(ctx, qp) \
+ write_mtx_mem(ctx, \
+ TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_QP, qp)
+
+#define CCB_CTRL_FRAMESKIP(ctx) \
+ read_mtx_mem(ctx, \
+ TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_FRAMESKIP)
+
+#define CCB_CTRL_SEQ(ctx) \
+ read_mtx_mem(ctx, \
+ TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_COMPLETE)
+
+
+void write_mtx_mem_multiple_setup(igd_context_t *context,
+ unsigned long addr);
+
+void write_mtx_mem_multiple(igd_context_t *context,
+ unsigned long cmd);
+
+unsigned long read_mtx_mem(igd_context_t *, unsigned long );
+
+void write_mtx_mem(igd_context_t *,
+ unsigned long ,
+ unsigned long );
+
+#endif /* TOPAZ_HDR_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
new file mode 100755
index 0000000..a89ceb2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
@@ -0,0 +1,1201 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: topaz_init.c
+ * $Revision: 1.23 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <sched.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+#include <topaz.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "topaz_hdr.h"
+
+//#include <interrupt.h>
+//#include <os/interrupt.h>
+
+#include <drm/drm.h>
+#include <drm_emgd_private.h>
+#include "services_headers.h"
+
+#include "pvr_bridge_km.h"
+#include "msvdx_pvr.h"
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+static PVRSRV_KERNEL_MEM_INFO *g_wb_mem_info = NULL;
+static int g_topaz_initialized = 0;
+static IMG_VOID *g_pMutex = IMG_NULL;
+/* DDK specific DRM device */
+extern struct drm_device *gpDrmDevice;
+
+unsigned char *base_firmware_address;
+
+extern int process_encode_mtx_messages(igd_context_t *context,
+ unsigned long *mtx_buf,
+ unsigned long size);
+
+static int reg_ready_tnc(igd_context_t *,
+ unsigned long ,
+ unsigned long ,
+ unsigned long );
+
+static int write_firmware(igd_context_t *,
+ unsigned long ,
+ unsigned long ,
+ unsigned long *,
+ unsigned long );
+
+static int upload_firmware(igd_context_t *, enc_fw_info_t *);
+
+void topaz_write_core_reg(igd_context_t *,
+ unsigned long,
+ unsigned long);
+
+void topaz_read_core_reg(igd_context_t *,
+ unsigned long,
+ unsigned long*);
+
+void get_mtx_control_from_dash(igd_context_t *context);
+
+void release_mtx_control_from_dash(igd_context_t *context);
+
+#define RAM_SIZE (1024 * 24)
+#define ENC_FW_SIZE (512 * 1024)
+
+/* register default values */
+static unsigned long topaz_def_regs[184][3] = {
+ {MVEA_BASE, 0x00000000, 0x00000000},
+ {MVEA_BASE, 0x00000004, 0x00000400},
+ {MVEA_BASE, 0x00000008, 0x00000000},
+ {MVEA_BASE, 0x0000000C, 0x00000000},
+ {MVEA_BASE, 0x00000010, 0x00000000},
+ {MVEA_BASE, 0x00000014, 0x00000000},
+ {MVEA_BASE, 0x00000018, 0x00000000},
+ {MVEA_BASE, 0x0000001C, 0x00000000},
+ {MVEA_BASE, 0x00000020, 0x00000120},
+ {MVEA_BASE, 0x00000024, 0x00000000},
+ {MVEA_BASE, 0x00000028, 0x00000000},
+ {MVEA_BASE, 0x00000100, 0x00000000},
+ {MVEA_BASE, 0x00000104, 0x00000000},
+ {MVEA_BASE, 0x00000108, 0x00000000},
+ {MVEA_BASE, 0x0000010C, 0x00000000},
+ {MVEA_BASE, 0x0000011C, 0x00000001},
+ {MVEA_BASE, 0x0000012C, 0x00000000},
+ {MVEA_BASE, 0x00000180, 0x00000000},
+ {MVEA_BASE, 0x00000184, 0x00000000},
+ {MVEA_BASE, 0x00000188, 0x00000000},
+ {MVEA_BASE, 0x0000018C, 0x00000000},
+ {MVEA_BASE, 0x00000190, 0x00000000},
+ {MVEA_BASE, 0x00000194, 0x00000000},
+ {MVEA_BASE, 0x00000198, 0x00000000},
+ {MVEA_BASE, 0x0000019C, 0x00000000},
+ {MVEA_BASE, 0x000001A0, 0x00000000},
+ {MVEA_BASE, 0x000001A4, 0x00000000},
+ {MVEA_BASE, 0x000001A8, 0x00000000},
+ {MVEA_BASE, 0x000001AC, 0x00000000},
+ {MVEA_BASE, 0x000001B0, 0x00000000},
+ {MVEA_BASE, 0x000001B4, 0x00000000},
+ {MVEA_BASE, 0x000001B8, 0x00000000},
+ {MVEA_BASE, 0x000001BC, 0x00000000},
+ {MVEA_BASE, 0x000001F8, 0x00000000},
+ {MVEA_BASE, 0x000001FC, 0x00000000},
+ {MVEA_BASE, 0x00000200, 0x00000000},
+ {MVEA_BASE, 0x00000204, 0x00000000},
+ {MVEA_BASE, 0x00000208, 0x00000000},
+ {MVEA_BASE, 0x0000020C, 0x00000000},
+ {MVEA_BASE, 0x00000210, 0x00000000},
+ {MVEA_BASE, 0x00000220, 0x00000001},
+ {MVEA_BASE, 0x00000224, 0x0000001F},
+ {MVEA_BASE, 0x00000228, 0x00000100},
+ {MVEA_BASE, 0x0000022C, 0x00001F00},
+ {MVEA_BASE, 0x00000230, 0x00000101},
+ {MVEA_BASE, 0x00000234, 0x00001F1F},
+ {MVEA_BASE, 0x00000238, 0x00001F01},
+ {MVEA_BASE, 0x0000023C, 0x0000011F},
+ {MVEA_BASE, 0x00000240, 0x00000200},
+ {MVEA_BASE, 0x00000244, 0x00001E00},
+ {MVEA_BASE, 0x00000248, 0x00000002},
+ {MVEA_BASE, 0x0000024C, 0x0000001E},
+ {MVEA_BASE, 0x00000250, 0x00000003},
+ {MVEA_BASE, 0x00000254, 0x0000001D},
+ {MVEA_BASE, 0x00000258, 0x00001F02},
+ {MVEA_BASE, 0x0000025C, 0x00000102},
+ {MVEA_BASE, 0x00000260, 0x0000011E},
+ {MVEA_BASE, 0x00000264, 0x00000000},
+ {MVEA_BASE, 0x00000268, 0x00000000},
+ {MVEA_BASE, 0x0000026C, 0x00000000},
+ {MVEA_BASE, 0x00000270, 0x00000000},
+ {MVEA_BASE, 0x00000274, 0x00000000},
+ {MVEA_BASE, 0x00000278, 0x00000000},
+ {MVEA_BASE, 0x00000280, 0x00008000},
+ {MVEA_BASE, 0x00000284, 0x00000000},
+ {MVEA_BASE, 0x00000288, 0x00000000},
+ {MVEA_BASE, 0x0000028C, 0x00000000},
+ {MVEA_BASE, 0x00000314, 0x00000000},
+ {MVEA_BASE, 0x00000318, 0x00000000},
+ {MVEA_BASE, 0x0000031C, 0x00000000},
+ {MVEA_BASE, 0x00000320, 0x00000000},
+ {MVEA_BASE, 0x00000324, 0x00000000},
+ {MVEA_BASE, 0x00000348, 0x00000000},
+ {MVEA_BASE, 0x00000380, 0x00000000},
+ {MVEA_BASE, 0x00000384, 0x00000000},
+ {MVEA_BASE, 0x00000388, 0x00000000},
+ {MVEA_BASE, 0x0000038C, 0x00000000},
+ {MVEA_BASE, 0x00000390, 0x00000000},
+ {MVEA_BASE, 0x00000394, 0x00000000},
+ {MVEA_BASE, 0x00000398, 0x00000000},
+ {MVEA_BASE, 0x0000039C, 0x00000000},
+ {MVEA_BASE, 0x000003A0, 0x00000000},
+ {MVEA_BASE, 0x000003A4, 0x00000000},
+ {MVEA_BASE, 0x000003A8, 0x00000000},
+ {MVEA_BASE, 0x000003B0, 0x00000000},
+ {MVEA_BASE, 0x000003B4, 0x00000000},
+ {MVEA_BASE, 0x000003B8, 0x00000000},
+ {MVEA_BASE, 0x000003BC, 0x00000000},
+ {MVEA_BASE, 0x000003D4, 0x00000000},
+ {MVEA_BASE, 0x000003D8, 0x00000000},
+ {MVEA_BASE, 0x000003DC, 0x00000000},
+ {MVEA_BASE, 0x000003E0, 0x00000000},
+ {MVEA_BASE, 0x000003E4, 0x00000000},
+ {MVEA_BASE, 0x000003EC, 0x00000000},
+ {MVEA_BASE, 0x000002D0, 0x00000000},
+ {MVEA_BASE, 0x000002D4, 0x00000000},
+ {MVEA_BASE, 0x000002D8, 0x00000000},
+ {MVEA_BASE, 0x000002DC, 0x00000000},
+ {MVEA_BASE, 0x000002E0, 0x00000000},
+ {MVEA_BASE, 0x000002E4, 0x00000000},
+ {MVEA_BASE, 0x000002E8, 0x00000000},
+ {MVEA_BASE, 0x000002EC, 0x00000000},
+ {MVEA_BASE, 0x000002F0, 0x00000000},
+ {MVEA_BASE, 0x000002F4, 0x00000000},
+ {MVEA_BASE, 0x000002F8, 0x00000000},
+ {MVEA_BASE, 0x000002FC, 0x00000000},
+ {MVEA_BASE, 0x00000300, 0x00000000},
+ {MVEA_BASE, 0x00000304, 0x00000000},
+ {MVEA_BASE, 0x00000308, 0x00000000},
+ {MVEA_BASE, 0x0000030C, 0x00000000},
+ {MVEA_BASE, 0x00000290, 0x00000000},
+ {MVEA_BASE, 0x00000294, 0x00000000},
+ {MVEA_BASE, 0x00000298, 0x00000000},
+ {MVEA_BASE, 0x0000029C, 0x00000000},
+ {MVEA_BASE, 0x000002A0, 0x00000000},
+ {MVEA_BASE, 0x000002A4, 0x00000000},
+ {MVEA_BASE, 0x000002A8, 0x00000000},
+ {MVEA_BASE, 0x000002AC, 0x00000000},
+ {MVEA_BASE, 0x000002B0, 0x00000000},
+ {MVEA_BASE, 0x000002B4, 0x00000000},
+ {MVEA_BASE, 0x000002B8, 0x00000000},
+ {MVEA_BASE, 0x000002BC, 0x00000000},
+ {MVEA_BASE, 0x000002C0, 0x00000000},
+ {MVEA_BASE, 0x000002C4, 0x00000000},
+ {MVEA_BASE, 0x000002C8, 0x00000000},
+ {MVEA_BASE, 0x000002CC, 0x00000000},
+ {MVEA_BASE, 0x00000080, 0x00000000},
+ {MVEA_BASE, 0x00000084, 0x80705700},
+ {MVEA_BASE, 0x00000088, 0x00000000},
+ {MVEA_BASE, 0x0000008C, 0x00000000},
+ {MVEA_BASE, 0x00000090, 0x00000000},
+ {MVEA_BASE, 0x00000094, 0x00000000},
+ {MVEA_BASE, 0x00000098, 0x00000000},
+ {MVEA_BASE, 0x0000009C, 0x00000000},
+ {MVEA_BASE, 0x000000A0, 0x00000000},
+ {MVEA_BASE, 0x000000A4, 0x00000000},
+ {MVEA_BASE, 0x000000A8, 0x00000000},
+ {MVEA_BASE, 0x000000AC, 0x00000000},
+ {MVEA_BASE, 0x000000B0, 0x00000000},
+ {MVEA_BASE, 0x000000B4, 0x00000000},
+ {MVEA_BASE, 0x000000B8, 0x00000000},
+ {MVEA_BASE, 0x000000BC, 0x00000000},
+ {MVEA_BASE, 0x000000C0, 0x00000000},
+ {MVEA_BASE, 0x000000C4, 0x00000000},
+ {MVEA_BASE, 0x000000C8, 0x00000000},
+ {MVEA_BASE, 0x000000CC, 0x00000000},
+ {MVEA_BASE, 0x000000D0, 0x00000000},
+ {MVEA_BASE, 0x000000D4, 0x00000000},
+ {MVEA_BASE, 0x000000D8, 0x00000000},
+ {MVEA_BASE, 0x000000DC, 0x00000000},
+ {MVEA_BASE, 0x000000E0, 0x00000000},
+ {MVEA_BASE, 0x000000E4, 0x00000000},
+ {MVEA_BASE, 0x000000E8, 0x00000000},
+ {MVEA_BASE, 0x000000EC, 0x00000000},
+ {MVEA_BASE, 0x000000F0, 0x00000000},
+ {MVEA_BASE, 0x000000F4, 0x00000000},
+ {MVEA_BASE, 0x000000F8, 0x00000000},
+ {MVEA_BASE, 0x000000FC, 0x00000000},
+ {VLC_BASE, 0x00000000, 0x00000000},
+ {VLC_BASE, 0x00000004, 0x00000000},
+ {VLC_BASE, 0x00000008, 0x00000000},
+ {VLC_BASE, 0x0000000C, 0x00000000},
+ {VLC_BASE, 0x00000010, 0x00000000},
+ {VLC_BASE, 0x00000014, 0x00000000},
+ {VLC_BASE, 0x0000001C, 0x00000000},
+ {VLC_BASE, 0x00000020, 0x00000000},
+ {VLC_BASE, 0x00000024, 0x00000000},
+ {VLC_BASE, 0x0000002C, 0x00000000},
+ {VLC_BASE, 0x00000034, 0x00000000},
+ {VLC_BASE, 0x00000038, 0x00000000},
+ {VLC_BASE, 0x0000003C, 0x00000000},
+ {VLC_BASE, 0x00000040, 0x00000000},
+ {VLC_BASE, 0x00000044, 0x00000000},
+ {VLC_BASE, 0x00000048, 0x00000000},
+ {VLC_BASE, 0x0000004C, 0x00000000},
+ {VLC_BASE, 0x00000050, 0x00000000},
+ {VLC_BASE, 0x00000054, 0x00000000},
+ {VLC_BASE, 0x00000058, 0x00000000},
+ {VLC_BASE, 0x0000005C, 0x00000000},
+ {VLC_BASE, 0x00000060, 0x00000000},
+ {VLC_BASE, 0x00000064, 0x00000000},
+ {VLC_BASE, 0x00000068, 0x00000000},
+ {VLC_BASE, 0x0000006C, 0x00000000},
+ {0xffffffff, 0xffffffff, 0xffffffff}
+};
+
+unsigned long ui32H264_MTXTOPAZFWTextSize = 3478;
+unsigned long ui32H264_MTXTOPAZFWDataSize = 4704;
+unsigned long ui32H264_MTXTOPAZFWDataLocation = 0x82883680;
+
+unsigned long ui32H264VBR_MTXTOPAZFWTextSize = 4730;
+unsigned long ui32H264VBR_MTXTOPAZFWDataSize = 3456;
+unsigned long ui32H264VBR_MTXTOPAZFWDataLocation = 0x82884a00;
+
+unsigned long ui32H264CBR_MTXTOPAZFWTextSize = 5084;
+unsigned long ui32H264CBR_MTXTOPAZFWDataSize = 3104;
+unsigned long ui32H264CBR_MTXTOPAZFWDataLocation = 0x82884f80;
+
+unsigned long ui32H263CBR_MTXTOPAZFWTextSize = 4383;
+unsigned long ui32H263CBR_MTXTOPAZFWDataSize = 3808;
+unsigned long ui32H263CBR_MTXTOPAZFWDataLocation = 0x82884480;
+
+unsigned long ui32H263VBR_MTXTOPAZFWTextSize = 4498;
+unsigned long ui32H263VBR_MTXTOPAZFWDataSize = 3680;
+unsigned long ui32H263VBR_MTXTOPAZFWDataLocation = 0x82884680;
+
+unsigned long ui32H263_MTXTOPAZFWTextSize = 3202;
+unsigned long ui32H263_MTXTOPAZFWDataSize = 4976;
+unsigned long ui32H263_MTXTOPAZFWDataLocation = 0x82883240;
+
+unsigned long ui32MPG4CBR_MTXTOPAZFWTextSize = 4403;
+unsigned long ui32MPG4CBR_MTXTOPAZFWDataSize = 3776;
+unsigned long ui32MPG4CBR_MTXTOPAZFWDataLocation = 0x82884500;
+
+unsigned long ui32MPG4VBR_MTXTOPAZFWTextSize = 4519;
+unsigned long ui32MPG4VBR_MTXTOPAZFWDataSize = 3664;
+unsigned long ui32MPG4VBR_MTXTOPAZFWDataLocation = 0x828846c0;
+
+unsigned long ui32MPG4_MTXTOPAZFWTextSize = 3223;
+unsigned long ui32MPG4_MTXTOPAZFWDataSize = 4960;
+unsigned long ui32MPG4_MTXTOPAZFWDataLocation = 0x82883280;
+
+static enc_fw_info_t firmware[10] = {
+ { 0,0,0,0,0,0},
+ {
+ FW_H264_NO_RC,
+ &ui32H264_MTXTOPAZFWTextSize,
+ &ui32H264_MTXTOPAZFWDataSize,
+ &ui32H264_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H264_MTXTOPAZFWText,*/
+ NULL /*aui32H264_MTXTOPAZFWData*/
+ },
+ {
+ FW_H264_VBR,
+ &ui32H264VBR_MTXTOPAZFWTextSize,
+ &ui32H264VBR_MTXTOPAZFWDataSize,
+ &ui32H264VBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H264VBR_MTXTOPAZFWText,*/
+ NULL /*aui32H264VBR_MTXTOPAZFWData */
+ },
+ {
+ FW_H264_CBR,
+ &ui32H264CBR_MTXTOPAZFWTextSize,
+ &ui32H264CBR_MTXTOPAZFWDataSize,
+ &ui32H264CBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H264CBR_MTXTOPAZFWText,*/
+ NULL /*aui32H264CBR_MTXTOPAZFWData */
+ },
+ {
+ FW_H263_NO_RC,
+ &ui32H263_MTXTOPAZFWTextSize,
+ &ui32H263_MTXTOPAZFWDataSize,
+ &ui32H263_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H263_MTXTOPAZFWText,*/
+ NULL /*aui32H263_MTXTOPAZFWData*/
+ },
+ {
+ FW_H263_VBR,
+ &ui32H263VBR_MTXTOPAZFWTextSize,
+ &ui32H263VBR_MTXTOPAZFWDataSize,
+ &ui32H263VBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H263VBR_MTXTOPAZFWText,*/
+ NULL /*aui32H263VBR_MTXTOPAZFWData*/
+ },
+ {
+ FW_H263_CBR,
+ &ui32H263CBR_MTXTOPAZFWTextSize,
+ &ui32H263CBR_MTXTOPAZFWDataSize,
+ &ui32H263CBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32H263CBR_MTXTOPAZFWText,*/
+ NULL /*aui32H263CBR_MTXTOPAZFWData*/
+ },
+ {
+ FW_MPEG4_NO_RC,
+ &ui32MPG4_MTXTOPAZFWTextSize,
+ &ui32MPG4_MTXTOPAZFWDataSize,
+ &ui32MPG4_MTXTOPAZFWDataLocation,
+ NULL, /*aui32MPG4_MTXTOPAZFWText,*/
+ NULL /*aui32MPG4_MTXTOPAZFWData*/
+ },
+ {
+ FW_MPEG4_VBR,
+ &ui32MPG4VBR_MTXTOPAZFWTextSize,
+ &ui32MPG4VBR_MTXTOPAZFWDataSize,
+ &ui32MPG4VBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32MPG4VBR_MTXTOPAZFWText,*/
+ NULL /*aui32MPG4VBR_MTXTOPAZFWData*/
+ },
+ {
+ FW_MPEG4_CBR,
+ &ui32MPG4CBR_MTXTOPAZFWTextSize,
+ &ui32MPG4CBR_MTXTOPAZFWDataSize,
+ &ui32MPG4CBR_MTXTOPAZFWDataLocation,
+ NULL, /*aui32MPG4CBR_MTXTOPAZFWText,*/
+ NULL /*aui32MPG4CBR_MTXTOPAZFWData*/
+ }
+};
+
+IMG_VOID * HostCreateMutex(IMG_VOID)
+{
+ struct semaphore *psSem;
+
+ psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+ if (psSem)
+ {
+ sema_init(psSem, 1);
+ }
+
+ return psSem;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (down_trylock((struct semaphore *)pvMutex))
+ {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ down((struct semaphore *)pvMutex);
+ }
+#else
+ down((struct semaphore *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+ up((struct semaphore *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+ if (pvMutex)
+ {
+ kfree(pvMutex);
+ }
+}
+int topaz_shutdown_tnc(igd_context_t *context)
+{
+ EMGD_TRACE_ENTER;
+
+
+ g_topaz_initialized = 0;
+ g_wb_mem_info = NULL;
+
+ HostDestroyMutex(g_pMutex);
+ g_pMutex = IMG_NULL;
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+int topaz_init_tnc (unsigned long wb_offset,
+ void* mem_handle_writeback,
+ void *mem_handle_enc_fw)
+{
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ unsigned char *mmio;
+ unsigned long size;
+ int i;
+ platform_context_tnc_t *platform = NULL;
+ tnc_topaz_priv_t *topaz_priv;
+ unsigned long *km_firm_addr = NULL;
+ unsigned long *firm_offset_values = NULL;
+ PVRSRV_ERROR err;
+ PVRSRV_PER_PROCESS_DATA *ps_data = NULL;
+ IMG_UINT32 pid = 0;
+ PVRSRV_KERNEL_MEM_INFO *mem_info_fw = NULL;
+ PVRSRV_KERNEL_MEM_INFO *mem_info_wb = NULL;
+ struct msvdx_pvr_info *pvr;
+
+ priv = gpDrmDevice->dev_private;
+ context = priv->context;
+ mmio = context->device_context.virt_mmadr;
+#if 0
+ if(!mem_handle_writeback || !mem_handle_enc_fw) {
+ return -EINVAL;
+ }
+#else
+ if (!mem_handle_enc_fw) {
+ return -EINVAL;
+ }
+#endif
+ pid = OSGetCurrentProcessIDKM();
+ ps_data = PVRSRVPerProcessData(pid);
+ if (!ps_data) {
+ printk(KERN_ERR "TOPAZ: Cannot get process data information");
+ return -1;
+ }
+
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, (void **)&mem_info_fw,
+ (IMG_HANDLE)mem_handle_enc_fw, PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(err != PVRSRV_OK) {
+ printk(KERN_ERR "TOPAZ: Cannot get fw memory context from process data");
+ return -1;
+ }
+#if 0
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, (void **)&mem_info_wb,
+ (IMG_HANDLE)mem_handle_writeback, PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(err != PVRSRV_OK) {
+ printk(KERN_ERR "TOPAZ: Cannot get wb memory context from process data");
+ return -1;
+ }
+#endif
+
+ if(!mem_info_fw || mem_info_fw->ui32AllocSize < ENC_FW_SIZE) {
+ printk(KERN_ERR "TOPAZ: invalid fw memory context from process data");
+ return -1;
+ }
+
+#if 0
+ if(!mem_info_wb || mem_info_wb->ui32AllocSize < (4 * 1024)) {
+ printk(KERN_ERR "TOPAZ: Invalid wb memory context from process data");
+ return -1;
+ }
+#endif
+ /* Only support Atom E6xx */
+ if ((PCI_DEVICE_ID_VGA_TNC != context->device_context.did)||
+ (context->device_context.bid == PCI_DEVICE_ID_BRIDGE_TNC_ULP)) {
+ return -1;
+ }
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ if (g_topaz_initialized != 1)
+ {
+ spin_lock_init(&platform->topaz_init_tnc);
+
+ spin_lock(&platform->topaz_init_tnc);
+
+ size = WRITEBACK_MEM_SIZE;
+ GMM_SET_DEBUG_NAME("TOPAZ Writeback Memory");
+
+ pvr = platform->msvdx_pvr;
+ if (!g_wb_mem_info) {
+ err = PVRSRVAllocDeviceMemKM(pvr->sgx_cookie, pvr->per_proc,
+ pvr->heap_info[pvr->mapping_heap_index].hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ size, 0, &g_wb_mem_info, "TOPAZ writeback");
+
+ if (!g_wb_mem_info) {
+ printk(KERN_ERR "[EMGD] TOPAZ: Failed to allocate %u "
+ "bytes from SGX heap\n",
+ (unsigned int)size);
+
+ spin_unlock(&platform->topaz_init_tnc);
+ return -ENOMEM;
+ }
+ }
+
+ platform->topaz_busy = 0;
+
+ spin_unlock(&platform->topaz_init_tnc);
+ }
+
+ spin_lock(&platform->topaz_init_tnc);
+
+ topaz_priv->topaz_busy = 0;
+ topaz_priv->topaz_cmd_seq = 0;
+ topaz_priv->topaz_fw_loaded = 0;
+ topaz_priv->topaz_cur_codec = 0;
+ topaz_priv->cur_mtx_data_size = 0;
+
+ /*
+ printk(KERN_INFO "Topaz write back memory = %p", topaz_priv->topaz_ccb_wb);
+ printk(KERN_INFO "Topaz write back offset = %lx", topaz_priv->topaz_wb_offset);
+ printk(KERN_INFO "Topaz write back sync memory = %p", topaz_priv->topaz_sync_addr);
+ printk(KERN_INFO "Topaz write back sync offset = %lx", topaz_priv->topaz_sync_offset);
+ */
+
+ if (g_topaz_initialized == 1)
+ {
+ spin_unlock(&platform->topaz_init_tnc);
+ return 0;
+ }
+
+ topaz_priv->topaz_wb_offset = g_wb_mem_info->sDevVAddr.uiAddr; //wb_offset;
+ topaz_priv->topaz_ccb_wb = g_wb_mem_info->pvLinAddrKM; //(unsigned char *)mem_info_wb->pvLinAddrKM;
+
+ /* Sync location will be half of the writeback memory. */
+ topaz_priv->topaz_sync_addr = (unsigned long *)(topaz_priv->topaz_ccb_wb + 2048);
+ topaz_priv->topaz_sync_offset = topaz_priv->topaz_wb_offset + 2048;
+
+ *(topaz_priv->topaz_sync_addr) = 0; /*reset sync seq */
+ topaz_priv->topaz_sync_id = 0; /*reset sync id */
+
+ g_topaz_initialized = 1;
+
+ spin_unlock(&platform->topaz_init_tnc);
+
+ if ((g_pMutex = HostCreateMutex()) == IMG_NULL)
+ {
+ return 0;
+ }
+
+ topaz_priv->selected_codec = -1;
+
+ /* firmware part */
+ /* allocate memory for all firmwares */
+ /* to check, is allocate or not */
+ if ( !firmware[1].text && mem_info_fw->pvLinAddrKM) {
+ base_firmware_address = kmalloc( 512 * 1024, GFP_KERNEL);
+ if ( NULL == base_firmware_address){
+ printk (KERN_INFO "Kernel memory allocation failed\n");
+ printk (KERN_INFO "Kernel firmware is not loaded\n");
+ return 1;
+ }
+ /* copy all firmware to kernel memory */
+ km_firm_addr = (unsigned long *) base_firmware_address;
+ firm_offset_values = km_firm_addr;
+ memcpy(km_firm_addr, mem_info_fw->pvLinAddrKM, 512*1024);
+ /* printk(KERN_INFO "Topaz km_firm_addr = %p", km_firm_addr); */
+ /* to set firmwares */
+ /* NB! all offsets in bytes */
+ for ( i = 1; i < 10; i++){
+ firmware[i].text = km_firm_addr + (firm_offset_values[2*(i-1) + 0] >> 2) ;
+ firmware[i].data = km_firm_addr + (firm_offset_values[2*(i-1) + 1] >> 2) ;
+ }
+ }
+
+#if 0
+ /* DEBUG ONLY */
+ /* load fw here to make sure firmware can be loaded. */
+ topaz_setup_fw(context, FW_H264_NO_RC); /* just for test */
+
+#endif
+
+ return 0;
+}
+
+int topaz_setup_fw(igd_context_t *context, enum tnc_topaz_encode_fw codec)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long address, ctrl, core_id, core_rev;
+ //unsigned long reg=0;
+ int i = 0;
+ enc_fw_info_t *curr_fw;
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ // do no reload firmware
+ if (codec == topaz_priv->selected_codec)
+ {
+ return 0;
+ }
+ topaz_priv->selected_codec = codec;
+ EMGD_WRITE32(0x00000000, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+ /* Reset MVEA
+ * MVEA_SPE_SOFT_RESET |
+ * MVEA_IPE_SOFT_RESET |
+ * MVEA_CMPRS_SOFT_RESET |
+ * MVEA_JMCOMP_SOFT_RESET |
+ * MVEA_CMC_SOFT_RESET |
+ * MVEA_DCF_SOFT_RESET
+ */
+ EMGD_WRITE32(0x0000003f, mmio + TNC_TOPAZ_IMG_MVEA_SRST);
+ EMGD_WRITE32(0x00, mmio + TNC_TOPAZ_IMG_MVEA_SRST);
+
+ /* topaz_set_default_regs */
+ /* Set default value for Video Encode resgister */
+ while (topaz_def_regs[i][0] != 0xffffffff) {
+ EMGD_WRITE32(topaz_def_regs[i][2],
+ mmio + topaz_def_regs[i][0] + topaz_def_regs[i][1]);
+ i++;
+ }
+
+ /* topaz_upload_fw */
+ /* Point to request firmware */
+ if((codec < 1) || (codec > 9)) {
+ return 1;
+ }
+ curr_fw = &firmware[codec];
+
+ upload_firmware(context, curr_fw);
+
+ /* topaz_write_core_reg */
+ /* Start the firmware thread running */
+ /*topaz_write_core_reg(context, TOPAZ_MTX_PC, PC_START_ADDRESS);*/
+
+ /* topaz_read_core_reg */
+ EMGD_WRITE32(PC_START_ADDRESS, mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_DATA);
+ EMGD_WRITE32(TOPAZ_MTX_PC, mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST);
+ reg_ready_tnc(context, TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST,
+ 0x80000000, 0x80000000);
+
+ /* Enable auto clock gate for TOPAZ and MVEA
+ * TOPAZ_VLC_AUTO_CLK_GATE |
+ * TOPAZ_DB_AUTO_CLK_GATE |
+ *
+ * MVEA_IPE_AUTO_CLK_GATE |
+ * MVEA_SPE_AUTO_CLK_GATE |
+ * MVEA_CMPRS_AUTO_CLK GATE |
+ * MVEA_JMCOMP_AUTO_CLK_GATE |
+ */
+ EMGD_WRITE32(0x00000003, mmio + TNC_TOPAZ_IMG_TOPAZ_AUTO_CLK_GATE);
+ EMGD_WRITE32(0x0000000f, mmio + TNC_TOPAZ_MVEA_AUTO_CLOCK_GATING);
+
+ /* Clear the MTX interrupt */
+ EMGD_WRITE32(0x00000002, mmio + TNC_TOPAZ_IMG_TOPAZ_INTCLEAR);
+ /* Enable MTX */
+ EMGD_WRITE32(0x00000001, mmio + TNC_TOPAZ_MTX_ENABLE);
+ /* Once enable MTX fw should generate interrupt to indicate its reday */
+ reg_ready_tnc(context, TNC_TOPAZ_IMG_TOPAZ_INTSTAT,
+ 0x00000002, 0x00000002);
+ /* Clear the MTX interrupt */
+ EMGD_WRITE32(0x00000002, mmio + TNC_TOPAZ_IMG_TOPAZ_INTCLEAR);
+
+ /* get ccb buffer addr - file hostutils.c */
+ topaz_priv->topaz_ccb_buffer_addr = read_mtx_mem(
+ context, MTX_DATA_BASE + RAM_SIZE - 4);
+ topaz_priv->topaz_ccb_ctrl_addr = read_mtx_mem( context,
+ MTX_DATA_BASE + RAM_SIZE - 8);
+ topaz_priv->topaz_ccb_size = read_mtx_mem( context,
+ topaz_priv->topaz_ccb_ctrl_addr + MTX_CCB_CTRL_CCB_SIZE);
+ topaz_priv->topaz_cmd_windex = 0;
+
+ /* write back the intial QP value */
+ write_mtx_mem(context,
+ topaz_priv->topaz_ccb_ctrl_addr + MTX_CCB_CTRL_INIT_QP,
+ topaz_priv->stored_initial_qp);
+ write_mtx_mem(context,
+ MTX_DATA_BASE + RAM_SIZE - 12, topaz_priv->topaz_wb_offset);
+
+ /*reg = EMGD_READ32(mmio+TNC_TOPAZ_IMG_TOPAZ_INTSTAT);
+ printk( KERN_INFO "b4 first kick: TOPAZ_INTSTAT= 0x%08x ", reg);*/
+
+ /* this kick is important to update the WB offset */
+ *((unsigned long *)topaz_priv->topaz_ccb_wb) = 0x01020304;
+ EMGD_WRITE32(1, mmio + TNC_TOPAZ_MTX_KICK);
+ OS_SLEEP(1000);
+ /* printk(KERN_INFO "Expected 0x12345678, wb return 0x%08lx",
+ *((unsigned long *)topaz_priv->topaz_ccb_wb));
+ reg = EMGD_READ32(mmio+TNC_TOPAZ_IMG_TOPAZ_INTSTAT);
+ printk( KERN_INFO "after first kick: TOPAZ_INTSTAT= 0x%08x ", reg);
+ reg = EMGD_READ32(mmio+TNC_TOPAZ_MMU_STATUS);
+ printk( KERN_INFO "sync: TOPAZ_MMU_STATUS= 0x%08x ", reg);*/
+
+ topaz_priv->topaz_busy = 0;
+ topaz_priv->topaz_cmd_seq = 0;
+
+ /* Enable MMU by pass when confguring MMU - TOPAZ_CR_MMU_BYPASS*/
+ EMGD_WRITE32(0x00000800, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+ /* Topaz MMU will point to the same PD as SGX. */
+ address = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE1);
+ EMGD_WRITE32(address, mmio + TNC_TOPAZ_MMU_DIR_LIST_BASE0);
+ EMGD_WRITE32(0, mmio + TNC_TOPAZ_MMU_TILE0);
+
+ /*
+ * MMU Page size = 12
+ * MMU best count = 7
+ * MMU ADT TTE = 0
+ * MMU TTE threshold = 12
+ */
+ EMGD_WRITE32(0xc070000c, mmio + TNC_TOPAZ_MMU_CONTROL1);
+ EMGD_WRITE32(0x00, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+ /* Set index register, all pointing to directory bank 0, Flush the directory
+ * cache and disable the MMU bypass */
+ EMGD_WRITE32(0, mmio + TNC_TOPAZ_MMU_BANK_INDEX);
+ ctrl = EMGD_READ32(mmio + TNC_TOPAZ_MMU_CONTROL0) | 0x0C; /* Flush */
+ EMGD_WRITE32(ctrl, mmio + TNC_TOPAZ_MMU_CONTROL0);
+ EMGD_WRITE32(0x00, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+ core_id = EMGD_READ32(mmio + TNC_TOPAZ_IMG_TOPAZ_CORE_ID);
+ core_rev = EMGD_READ32(mmio + TNC_TOPAZ_IMG_TOPAZ_CORE_REV);
+
+ printk(KERN_INFO "Topaz Core Id (%lx)", core_id);
+ printk(KERN_INFO "Topaz Core Revision (%lx)", core_rev);
+
+ topaz_flush_tnc(context);
+
+ return 0;
+}
+
+
+static int upload_firmware(igd_context_t *context, enc_fw_info_t *fw)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long start_addr;
+
+ EMGD_DEBUG("Encode Firmware version is %s", fw->fw_version);
+ EMGD_DEBUG("Encode Firmware enum is %d", fw->idx);
+
+ /* # refer HLD document */
+ /* # MTX reset - MTX_SOFT_RESET_MTX_RESET_MASK */
+ EMGD_WRITE32(1, mmio + TNC_TOPAZ_MTX_SOFT_RESET);
+ OS_SLEEP(6000);
+
+ /* topaz_mtx_upload_by_register */
+ EMGD_DEBUG("Writing firmware text to core memory");
+ start_addr = PC_START_ADDRESS - MTX_CODE_BASE;
+ write_firmware(context, start_addr,
+ *(fw->text_size), fw->text, MTX_CORE_CODE_MEM);
+ /* topaz_mtx_upload_by_register */
+ EMGD_DEBUG("Writing firmware data to core memory");
+ start_addr = *(fw->data_offset) - MTX_DATA_BASE;
+ write_firmware(context, start_addr,
+ *(fw->data_size), fw->data, MTX_CORE_DATA_MEM);
+ OS_SLEEP(6000);
+ return 0;
+}
+
+/* topaz_mtx_upload_by_register() */
+static int write_firmware(igd_context_t *context,
+ unsigned long address,
+ unsigned long size,
+ unsigned long *data,
+ unsigned long mtx_mem)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long ram_bank;
+ unsigned long bank_size;
+ unsigned long current_bank;
+ unsigned long ram_id;
+ unsigned long ctrl;
+ unsigned long i;
+
+ get_mtx_control_from_dash(context);
+
+ ram_bank = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+ ram_bank = 0x0a0a0606;
+ bank_size = (ram_bank & 0x000f0000) >> 16;
+ bank_size = (1 << (bank_size + 2));
+
+ /* Loop writing text/code to core memory */
+ current_bank = ~0L;
+
+ for (i = 0; i < size; i++) {
+ /* Wait for MCMSTAT to become be idle 1 */
+ if (reg_ready_tnc(context, TNC_TOPAZ_MTX_RAM_ACCESS_STATUS,
+ 0x00000001, 0x00000001) == 0) {
+ ram_id = mtx_mem + (address / bank_size);
+ if (ram_id != current_bank) {
+ /*
+ * bits 20:27 - ram bank (CODE_BASE | DATA_BASE)
+ * bits 2:19 - address
+ * bit 1 - enable auto increment addressing mode
+ */
+ ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) |
+ 0x02;
+ EMGD_WRITE32(ctrl, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+
+ current_bank = ram_id;
+ }
+
+ address += 4;
+ EMGD_WRITE32(data[i],
+ mmio + TNC_TOPAZ_MTX_RAM_ACCESS_DATA_TRANSFER);
+ } else {
+ /* FIXME: Should we return something here */
+ printk(KERN_ERR "Timeout waiting for MCMSTAT to be idle");
+ }
+ }
+ release_mtx_control_from_dash(context);
+ return 0;
+}
+
+static int reg_ready_tnc(igd_context_t *context,
+ unsigned long reg,
+ unsigned long mask,
+ unsigned long value)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long status;
+ int poll_cnt = 1000;
+
+ while (poll_cnt) {
+ status = EMGD_READ32(mmio + reg);
+ if ((status & mask) == value) {
+ return 0;
+ }
+ poll_cnt--;
+ OS_SLEEP(100);
+ }
+
+ /* Timeout waiting for RAM ACCESS ready */
+ EMGD_DEBUG(KERN_ERR "TIMEOUT: Got 0x%08lx while waiting for 0x%08lx", status, value);
+ return 1;
+}
+
+unsigned long read_mtx_mem(igd_context_t *context, unsigned long addr)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long bank_size;
+ unsigned long ram_size;
+ unsigned long ram_id;
+ unsigned long reg;
+ unsigned long ctrl = 0;
+ unsigned long val = 0;
+
+ reg = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+
+ reg = 0x0a0a0606;
+ bank_size = (reg & 0xf0000) >> 16;
+
+ ram_size = (unsigned long) (1 << (bank_size + 2));
+ ram_id = (addr - MTX_DATA_BASE) / ram_size;
+
+ /* cmd id */
+ ctrl = ((0x18 + ram_id) << 20) & 0x0ff00000;
+ /* Address to read */
+ ctrl |= ((addr >> 2) << 2) & 0x000ffffc;
+ ctrl |= 0x00000001;
+
+ EMGD_WRITE32(ctrl, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+ reg_ready_tnc(context, TNC_TOPAZ_MTX_RAM_ACCESS_STATUS, 1, 1);
+ val = EMGD_READ32(mmio + TNC_TOPAZ_MTX_RAM_ACCESS_DATA_TRANSFER);
+
+ return val;
+}
+
+
+void write_mtx_mem(igd_context_t *context,
+ unsigned long addr, unsigned long value)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long bank_size;
+ unsigned long ram_size;
+ unsigned long ram_id;
+ unsigned long reg;
+ unsigned long ctrl = 0;
+
+ reg = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+ /*printk(KERN_INFO "write_mtx_mem: MTX_DEBUG: 0x%08x", reg);*/
+
+ reg = 0x0a0a0606;
+ bank_size = (reg & 0xf0000) >> 16;
+
+ ram_size = (unsigned long) (1 << (bank_size + 2));
+ ram_id = (addr - MTX_DATA_BASE) / ram_size;
+
+ /* cmd id */
+ ctrl = ((0x18 + ram_id) << 20) & 0x0ff00000;
+ /* Address to read */
+ ctrl |= ((addr >> 2) << 2) & 0x000ffffc;
+
+ /*printk(KERN_INFO "write_mtx_mem: ctrl=0x%08x, addr=0x%08x, value=0x%08x", ctrl, addr, value);*/
+
+ EMGD_WRITE32(ctrl, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+ EMGD_WRITE32(value, mmio + TNC_TOPAZ_MTX_RAM_ACCESS_DATA_TRANSFER);
+ reg_ready_tnc(context, TNC_TOPAZ_MTX_RAM_ACCESS_STATUS, 1, 1);
+
+ return;
+}
+
+void topaz_write_core_reg(igd_context_t *context,
+ unsigned long reg, unsigned long val)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long tmp;
+
+ get_mtx_control_from_dash(context);
+
+ /* put data into MTX_RW_DATA */
+ EMGD_WRITE32(val, mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_DATA);
+
+ /* request a write */
+ tmp = reg &
+ ~TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK;
+ EMGD_WRITE32(tmp, mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST);
+
+ /* wait for operation finished */
+ reg_ready_tnc(context,
+ TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST,
+ TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+ TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+ release_mtx_control_from_dash(context);
+}
+
+void topaz_read_core_reg(igd_context_t *context,
+ unsigned long reg, unsigned long *ret_val)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long tmp;
+
+ get_mtx_control_from_dash(context);
+
+ /* request a write */
+ tmp = reg &
+ ~TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK;
+ EMGD_WRITE32(tmp | TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK,
+ mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST);
+
+ /* wait for operation finished */
+ reg_ready_tnc(context,
+ (unsigned long )(mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST),
+ 0, TNC_TOPAZ_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+ /* read */
+ *ret_val = EMGD_READ32(mmio + TNC_TOPAZ_MTX_REGISTER_READ_WRITE_DATA);
+
+ release_mtx_control_from_dash(context);
+}
+
+void get_mtx_control_from_dash(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ int debug_reg_slave_val;
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+ unsigned long reg;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ reg = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+ reg &= 0xFFFFFFF0;
+ reg |= 0x00000006;
+
+ /*printk(KERN_INFO "get_mtx:debug value = 0x%08x", reg);*/
+
+ /* Get MTX control from dash
+ * TOPAZ_CR_MTX_DBG_IS_SLAVE |
+ * TOPAZ_CR_MTX_DBG_GPIO_OUT
+ */
+ EMGD_WRITE32(reg, mmio + TNC_TOPAZ_MTX_DEBUG);
+
+ do {
+ debug_reg_slave_val = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+ } while ((debug_reg_slave_val & 0x18) !=0 );
+
+ topaz_priv->topaz_dash_access_ctrl = EMGD_READ32(mmio +
+ TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+}
+
+void release_mtx_control_from_dash(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+ unsigned long reg;
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+
+ reg = EMGD_READ32(mmio + TNC_TOPAZ_MTX_DEBUG);
+ reg &= 0xFFFFFFF0;
+ reg |= 0x00000004;
+
+ /*printk(KERN_INFO "release:debug value = 0x%08x", reg);*/
+ /* restore access control */
+ EMGD_WRITE32(topaz_priv->topaz_dash_access_ctrl,
+ mmio + TNC_TOPAZ_MTX_RAM_ACCESS_CONTROL);
+
+ /* release bus
+ * TOPAZ_CR_MTX_DBG_IS_SLAVE
+ */
+ EMGD_WRITE32(reg, mmio + TNC_TOPAZ_MTX_DEBUG);
+}
+
+int process_video_encode_tnc(igd_context_t *context, unsigned long offset,
+ void *mem_handle, unsigned long *fence_id)
+{
+ unsigned long *mtx_buf;
+ unsigned long size=0;
+ int ret = 0;
+ platform_context_plb_t *platform;
+ tnc_topaz_priv_t *topaz_priv;
+ PVRSRV_ERROR err;
+ PVRSRV_PER_PROCESS_DATA *ps_data = NULL;
+ IMG_UINT32 pid = 0;
+ PVRSRV_KERNEL_MEM_INFO *mem_info_mtx_buf = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if(!mem_handle || !fence_id) {
+ return -EINVAL;
+ }
+
+ pid = OSGetCurrentProcessIDKM();
+ ps_data = PVRSRVPerProcessData(pid);
+ if (!ps_data) {
+ printk(KERN_ERR "TOPAZ: Cannot get process data information");
+ return -1;
+ }
+
+ err = PVRSRVLookupHandle(ps_data->psHandleBase, (void **)&mem_info_mtx_buf,
+ (IMG_HANDLE)mem_handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(err != PVRSRV_OK) {
+ printk(KERN_ERR "TOPAZ: Cannot get mtx buf memory context from process data");
+ return -1;
+ }
+
+ if(!mem_info_mtx_buf || mem_info_mtx_buf->ui32AllocSize < 0x3000) {
+ printk(KERN_ERR "TOPAZ: invalid mtx buf memory context from process data");
+ return -1;
+ }
+
+ platform = (platform_context_plb_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+ HostAquireMutex(g_pMutex);
+ mtx_buf = (unsigned long *) mem_info_mtx_buf->pvLinAddrKM;
+
+ EMGD_DEBUG("process_video_encode_tnc where buf=%p, offset=%lx\n",
+ mtx_buf, offset);
+
+ if (!platform->topaz_busy)
+ {
+ platform->topaz_busy = 1;
+ ret = process_encode_mtx_messages(context, mtx_buf, size);
+ if (ret){
+ printk(KERN_INFO "Invalid topaz encode cmd");
+ ret = -EINVAL;
+ }
+ platform->topaz_busy = 0;
+ }
+
+
+ *fence_id = topaz_priv->topaz_sync_id;
+
+ HostReleaseMutex(g_pMutex);
+ return ret;
+}
+
+int topaz_flush_tnc(igd_context_t *context)
+{
+ unsigned char *mmio = context->device_context.virt_mmadr;
+ unsigned long topaz_mmu;
+
+ /* Only support Atom E6xx */
+ if ((PCI_DEVICE_ID_VGA_TNC != context->device_context.did)||
+ (context->device_context.bid == PCI_DEVICE_ID_BRIDGE_TNC_ULP)) {
+ return -1;
+ }
+
+ topaz_mmu = EMGD_READ32(mmio + TNC_TOPAZ_MMU_CONTROL0);
+ topaz_mmu &= ~0x800; /* turn off MMU bypass mode if is on*/
+ topaz_mmu |= 0x0C; /* MMU_INVALDC + MMU_FLUSH */
+ EMGD_WRITE32(topaz_mmu, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+ topaz_mmu &= ~0x0C;
+ EMGD_WRITE32(topaz_mmu, mmio + TNC_TOPAZ_MMU_CONTROL0);
+
+#if 0
+ unsigned long reg;
+
+ topaz_mmu = EMGD_READ32(mmio + TNC_TOPAZ_MMU_CONTROL0);
+ printk(KERN_INFO "topaz_flush_tnc: CONTROL0=0x%08x", topaz_mmu);
+ reg = EMGD_READ32(mmio+TNC_TOPAZ_IMG_TOPAZ_INTSTAT);
+ printk( KERN_INFO "topaz_flush_tnc: TOPAZ_INTSTAT= 0x%08x ", reg);
+ reg = EMGD_READ32(mmio+TNC_TOPAZ_MMU_STATUS);
+ printk( KERN_INFO "topaz_flush_tnc: MMU_STATUS= 0x%08x ", reg);
+#endif
+
+ return 0;
+}
+
+int topaz_get_frame_skip(igd_context_t *context, unsigned long *frame_skip)
+{
+ tnc_topaz_priv_t *topaz_priv;
+ platform_context_tnc_t *platform;
+
+ if(!frame_skip) {
+ return -EINVAL;
+ }
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+ *frame_skip = topaz_priv->topaz_frame_skip;
+ /* printk(KERN_INFO "call frame skip with return %ld", *frame_skip);*/
+
+ return 0;
+}
+
+int topaz_get_fence_id(igd_context_t *context, unsigned long *fence_id)
+{
+ tnc_topaz_priv_t *topaz_priv;
+ unsigned long *sync_p;
+ platform_context_tnc_t *platform;
+
+ if(!fence_id) {
+ return -EINVAL;
+ }
+
+ platform = (platform_context_tnc_t *)context->platform_context;
+ topaz_priv = &platform->tpz_private_data;
+ sync_p = (unsigned long *)topaz_priv->topaz_sync_addr;
+
+ *fence_id = *sync_p;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/emgd/include/emgd_drm.h b/drivers/gpu/drm/emgd/include/emgd_drm.h
new file mode 100755
index 0000000..a1d946d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/emgd_drm.h
@@ -0,0 +1,938 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_drm.h
+ * $Revision: 1.64 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _EMGD_DRM_H_
+#define _EMGD_DRM_H_
+
+#include <linux/version.h>
+#include <drm/drm.h>
+#include <igd.h>
+#include <igd_appcontext.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_ovl.h>
+#include <igd_pd.h>
+#include <igd_pi.h>
+#include <igd_pwr.h>
+#include <igd_version.h>
+
+enum {
+ CHIP_PSB_8108 = 0,
+ CHIP_PSB_8109 = 1,
+ CHIP_TC_4108 = 2
+};
+
+/* To differentiate different engines for command buffer submission */
+#define PSB_ENGINE_2D 0
+#define PSB_ENGINE_VIDEO 1
+#define PSB_ENGINE_RASTERIZER 2
+#define PSB_ENGINE_TA 3
+#define PSB_ENGINE_HPRAST 4
+#define TNC_ENGINE_ENCODE 5
+#define PSB_ENGINE_COMPOSITOR_MMU 6
+
+
+/* OEM flags for buffer allocation through the PVR2DCreateFlipChain */
+#ifndef PVR2D_CREATE_FLIPCHAIN_SHARED
+#define PVR2D_CREATE_FLIPCHAIN_SHARED (1UL << 0)
+#define PVR2D_CREATE_FLIPCHAIN_QUERY (1UL << 1)
+#define PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY (1UL << 2)
+#define PVR2D_CREATE_FLIPCHAIN_AS_BLITCHAIN (1UL << 3)
+#endif
+
+#define PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY (1UL << 4)
+#define PVR2D_CREATE_FLIPCHAIN_OEMGENERAL (1UL << 5)
+#define PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN (1UL << 6)
+#define PVR2D_CREATE_FLIPCHAIN_CI (1UL << 7)
+#define PVR2D_CREATE_FLIPCHAIN_CI_V4L2_MAP (1UL << 8)
+/* Different command */
+#define CMD_VIDEO_STATE 1
+#define CMD_VIDEO_INITIALIZE 2
+#define CMD_VIDEO_UNINITIALIZE 3
+#define CMD_VIDEO_CLOSE_CONTEXT 4
+#define CMD_VIDEO_CREATE_CONTEXT 5
+#define CMD_VIDEO_SHUTDOWN 6
+#define CMD_VIDEO_GET_FENCE_ID 7
+#define CMD_VIDOE_GET_FRAME_SKIP 8
+#define CMD_VIDEO_GET_MSVDX_STATUS 9
+
+/* Video state */
+#define VIDEO_STATE_FW_LOADED 0x00000001
+#define VIDEO_STATE_RENDEC_FREED 0x00000002
+
+/* Different command for alter_ovl2 */
+#define CMD_ALTER_OVL2 1
+#define CMD_ALTER_OVL2_OSD 2
+
+typedef enum _kdrm_test_pvrsrv_opcodes {
+ SINGLE_DC_SWAPING = 0,
+ DIH_DC_DRAW_OPEN_DEV1 = 1,
+ DIH_DC_MODE_CHANGE1_DEV1 = 2,
+ DIH_DC_MODE_CHANGE2_DEV1 = 3,
+ DIH_DC_CLOSE_DEV1 = 4,
+ DIH_DC_DRAW_OPEN_DEV2 = 5,
+ DIH_DC_MODE_CHANGE1_DEV2 = 6,
+ DIH_DC_MODE_CHANGE2_DEV2 = 7,
+ DIH_DC_CLOSE_DEV2 = 8,
+} emgd_drm_test_pvrsrv_opcodes_t;
+
+
+/*
+ * This is where all the data structures used by the Koheo DRM interface are
+ * defined. These data structures are shared between and are used to pass data
+ * between the user-space & kernel-space code for each ioctl.
+ *
+ * The naming convention is: emgd_drm_<HAL-procedure-pointer-name>_t
+ */
+
+typedef struct _kdrm_alter_cursor {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ igd_cursor_info_t cursor_info; /* (DOWN) */
+ /**
+ * A pointer to the cursor data (in user space), which must be copied
+ * separately from this struct.
+ */
+ unsigned char *image; /* (DOWN) */
+} emgd_drm_alter_cursor_t;
+
+
+typedef struct _kdrm_alter_cursor_pos {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ igd_cursor_info_t cursor_info; /* (DOWN) */
+} emgd_drm_alter_cursor_pos_t;
+
+
+typedef struct _kdrm_alter_displays {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_info_t primary_pt_info; /* (DOWN) */
+ igd_display_info_t secondary_pt_info; /* (DOWN) */
+ igd_framebuffer_info_t primary_fb_info; /* (DOWN) */
+ igd_framebuffer_info_t secondary_fb_info; /* (DOWN) */
+ unsigned long dc; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+
+ igd_display_h primary; /* (UP) Generated "opaque handle" */
+ igd_display_h secondary; /* (UP) Generated "opaque handle" */
+} emgd_drm_alter_displays_t;
+
+
+typedef struct _kdrm_alter_ovl {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ igd_appcontext_h appcontext_h; /* (DOWN) a handle */
+ /* NOTE: igd_surface_t contains a pointer to an igd_palette_info_t struct
+ * (member name "palette_info"), which contains a pointer to an "unsigned
+ * long" "palette". Normally, each of these values must be copied from
+ * user to kernel space. However, an investigation found that the
+ * igd_palette_info_t struct is not used for either alter_ovl() or
+ * set_surface() (and igd_get_surface_plb() sets the value to 0,
+ * a.k.a. NULL). Thus, we're okay not copying this value.
+ */
+ igd_surface_t src_surf; /* (DOWN) */
+ igd_rect_t src_rect; /* (DOWN) */
+ igd_rect_t dst_rect; /* (DOWN) */
+ igd_ovl_info_t ovl_info; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_alter_ovl_t;
+
+typedef struct _kdrm_alter_ovl2 {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ igd_surface_t src_surf; /* (DOWN) */
+ igd_rect_t src_rect; /* (DOWN) */
+ igd_rect_t dst_rect; /* (DOWN) */
+ igd_ovl_info_t ovl_info; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+ int cmd; /* (DOWN) */
+} emgd_drm_alter_ovl2_t;
+
+
+typedef struct _kdrm_get_ovl_init_params {
+ ovl_um_context_t *ovl_um_context;
+ int rtn; /* (UP) - return value of HAL procedure */
+} emgd_drm_get_ovl_init_params_t;
+
+
+typedef struct _kdrm_appcontext_alloc {
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ int priority; /* (DOWN) */
+ unsigned int flags; /* (DOWN) */
+ igd_appcontext_h appcontext_h; /* (UP) a handle */
+} emgd_drm_appcontext_alloc_t;
+
+
+typedef struct _kdrm_appcontext_free {
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ int priority; /* (DOWN) */
+ igd_appcontext_h appcontext_h; /* (DOWN) a handle */
+} emgd_drm_appcontext_free_t;
+
+
+typedef struct _kdrm_driver_save_restore {
+ int rtn; /* (UP) - return value of HAL procedure */
+} emgd_drm_driver_save_restore_t;
+
+
+typedef struct _kdrm_enable_port {
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ unsigned long flag; /* (DOWN) */
+ unsigned long test; /* (DOWN) */
+} emgd_drm_enable_port_t;
+
+
+typedef struct _kdrm_get_attrs {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ /** The number of attributes of memory allocated by user-space. */
+ unsigned int allocated_size; /* (DOWN) */
+ /** The number of attributes returned by the kernel. */
+ unsigned long list_size; /* (UP) */
+ /**
+ * A pointer to the user-space-allocated memory for the kernel to copy the
+ * returned attribute list into. allocated_size is how many attributes
+ * this memory can contain. list_size is how many attributes the kernel is
+ * returning (or wants to return). If list_size > allocated_size, no data
+ * is copied back to user-space, and the user-space must re-allocate
+ * list_size amount of memory and try the ioctl again.
+ */
+ igd_attr_t *attr_list; /* (UP) */
+ int extended; /* (DOWN/UP) - true if there are/to get extended attributes */
+} emgd_drm_get_attrs_t;
+
+#define IGD_GET_DISPLAY_NO_3DD_REINIT 0x1
+
+typedef struct _kdrm_get_display {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned short port_number; /* (DOWN) */
+ igd_framebuffer_info_t fb_info; /* (DOWN/UP) Caller alloc's; DRM returns */
+ igd_display_info_t pt_info; /* (DOWN/UP) Caller alloc's; DRM returns */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_get_display_t;
+
+
+typedef struct _kdrm_get_drm_config {
+ int rtn; /* (UP) - return value of HAL procedure */
+ /** Which configuration to use within "xorg.conf" */
+ long config_id; /* (UP) */
+ /** The set of compile-time parameters, specified in "user_config.c". */
+ igd_param_t params; /* (UP) */
+ /** The display config (e.g. 8 for DIH). */
+ int display_config; /* (UP) */
+ /*
+ * Build configuration (e.g., DDK version used, debug vs release, etc.);
+ * if these don't match what userspace was built with, the driver may not
+ * run properly. (UP)
+ */
+ igd_build_config_t build_config;
+} emgd_drm_get_drm_config_t;
+
+
+typedef struct _kdrm_get_EDID_block {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ unsigned char block_number; /* (DOWN) */
+ unsigned char edid_block[128]; /* (UP) */
+} emgd_drm_get_EDID_block_t;
+
+
+typedef struct _kdrm_get_EDID_info {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ unsigned char edid_version; /* (UP) */
+ unsigned char edid_revision; /* (UP) */
+ unsigned long edid_size; /* (UP) */
+} emgd_drm_get_EDID_info_t;
+
+
+/*!
+ * This enum is used to state which of the 5 pixel format lists is desired to
+ * be returned in the emgd_drm_get_pixelformats_t struct (which only transfers
+ * one list).
+ */
+typedef enum _kdrm_which_pixelformat {
+ PIXEL_FORMAT_FRAMEBUFFER,
+ PIXEL_FORMAT_CURSOR,
+ PIXEL_FORMAT_OVERLAY,
+ PIXEL_FORMAT_RENDER,
+ PIXEL_FORMAT_TEXTURE
+} emgd_drm_which_pixelformat_t;
+
+/*!
+ * The igd_dispatch_t.get_pixelformats() procedure returns up-to 5 different
+ * lists of pixel formats. However, for Koheo drivers, only one of these lists
+ * is ever requested/returned. Thus, only one list needs to be passed between
+ * user/kernel space. Memory for the list is allocated in user space, and a
+ * pointer to it, along with its size and which format is desired, is passed to
+ * the kernel in this struct.
+ */
+typedef struct _kdrm_get_pixelformats {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ emgd_drm_which_pixelformat_t format; /* (DOWN) */
+ /** The number of pixelformats of memory allocated by user-space. */
+ unsigned int allocated_size; /* (DOWN) */
+ /** The number of pixelformats returned by the kernel. */
+ unsigned int list_size; /* (UP) */
+ unsigned long *format_list; /* (DOWN/UP) */
+} emgd_drm_get_pixelformats_t;
+
+
+typedef struct _kdrm_get_port_info {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ igd_port_info_t port_info; /* (UP) */
+} emgd_drm_get_port_info_t;
+
+
+typedef struct _kdrm_gmm_alloc_region {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long offset; /* (UP) */
+ unsigned long size; /* (DOWN/UP) */
+ unsigned int type; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_gmm_alloc_region_t;
+
+
+typedef struct _kdrm_gmm_alloc_surface {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long offset; /* (UP) */
+ unsigned long pixel_format; /* (DOWN) */
+ unsigned int width; /* (DOWN/UP) */
+ unsigned int height; /* (DOWN/UP) */
+ unsigned int pitch; /* (UP) */
+ unsigned long size; /* (DOWN/UP) */
+ unsigned int type; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_gmm_alloc_surface_t;
+
+
+typedef struct _kdrm_gmm_get_num_surface {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long count; /* (UP) */
+} emgd_drm_gmm_get_num_surface_t;
+
+
+typedef struct _kdrm_gmm_get_surface_list {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long allocated_size; /* (DOWN) */
+ unsigned long list_size; /* (UP) */
+ igd_surface_list_t **surface_list; /* (UP) */
+} emgd_drm_gmm_get_surface_list_t;
+
+
+typedef struct _kdrm_gmm_free {
+ unsigned long offset; /* (DOWN) */
+} emgd_drm_gmm_free_t;
+
+
+typedef struct _kdrm_gmm_flush_cache {
+ int rtn; /* (UP) - return value of HAL procedure */
+} emgd_drm_gmm_flush_cache_t;
+
+typedef struct _kdrm_video_cmd_buf {
+ int rtn;
+ int engine;
+ unsigned long offset;
+ void *mem_handle;
+ unsigned long fence_id;
+} emgd_drm_video_cmd_buf_t;
+
+typedef struct _kdrm_device_info {
+ unsigned long device_id;
+ unsigned long revision_id;
+ unsigned short bridge_id;
+ unsigned long display_memory_size;
+ unsigned long display_memory_offset;
+} emgd_drm_device_info_t;
+
+typedef struct _kdrm_init_video {
+ int rtn;
+ int cmd;
+ int engine;
+ union {
+ struct {
+ unsigned long base0;
+ unsigned long base1;
+ void *mem_handle_fw;
+ unsigned long fw_size;
+ };
+ struct {
+ unsigned long wb_offset;
+ void *mem_handle_writeback;
+ void *mem_handle_enc_fw;
+ };
+ unsigned long status;
+ unsigned long context_id;
+ };
+} emgd_drm_init_video_t;
+
+typedef struct _kdrm_video_get_info {
+ int rtn;
+ int engine;
+ int cmd;
+ int last_frame;
+ unsigned long fence_id;
+ unsigned long frame_skip;
+ unsigned long queue_status; /* (UP) - return 1 if msvdx queue empty, else 0 */
+ unsigned long mtx_msg_status; /* (UP) - return 1 if msvdx current message complete, else 0 */
+} emgd_drm_video_get_info_t;
+
+typedef struct _kdrm_video_flush_tlb {
+ int rtn;
+ int engine;
+} emgd_drm_video_flush_tlb_t;
+
+typedef struct _kdrm_preinit_mmu {
+ int rtn;
+ unsigned long memcontext;
+} emgd_drm_preinit_mmu_t;
+
+typedef struct _kdrm_get_display_info {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_info_t primary_pt_info; /* (UP) */
+ igd_display_info_t secondary_pt_info; /* (UP) */
+ igd_framebuffer_info_t primary_fb_info; /* (UP) */
+ igd_framebuffer_info_t secondary_fb_info; /* (UP) */
+ unsigned long dc; /* (UP) */
+ unsigned long flags; /* (UP) */
+
+ igd_display_h primary; /* (UP) Generated "opaque handle" */
+ igd_display_h secondary; /* (UP) Generated "opaque handle" */
+} emgd_drm_get_display_info_t;
+
+typedef struct _kdrm_pan_display {
+ /* Note: the return value is a long this time: */
+ long rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned long x_offset; /* (DOWN) */
+ unsigned long y_offset; /* (DOWN) */
+} emgd_drm_pan_display_t;
+
+
+typedef struct _kdrm_power_display {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ unsigned long power_state; /* (DOWN) */
+} emgd_drm_power_display_t;
+
+
+typedef struct _kdrm_pwr_alter {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned int power_state; /* (DOWN) */
+} emgd_drm_pwr_alter_t;
+
+
+/*!
+ * Memory for the list is allocated in user space, and a pointer to it, along
+ * with its size, is passed to the kernel in this struct.
+ */
+typedef struct _kdrm_query_dc {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long request; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+ /** The number of DCs of memory allocated by user-space. */
+ unsigned int allocated_size; /* (DOWN) */
+ /** The number of DCs returned by the kernel. */
+ unsigned int list_size; /* (UP) */
+ unsigned long *dc_list; /* (UP) */
+} emgd_drm_query_dc_t;
+
+
+typedef struct _kdrm_query_max_size_ovl {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned long pf; /* (DOWN) */
+ unsigned int max_width; /* (UP) */
+ unsigned int max_height; /* (UP) */
+} emgd_drm_query_max_size_ovl_t;
+
+
+typedef struct _kdrm_query_ovl {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_query_ovl_t;
+
+
+typedef struct _kdrm_query_mode_list {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long dc; /* (DOWN) */
+ unsigned long flags; /* (DOWN) */
+ /** The number of attributes of memory allocated by user-space. */
+ unsigned int allocated_size; /* (DOWN) */
+ /** The number of attributes returned by the kernel. */
+ unsigned int list_size; /* (UP) */
+ igd_display_info_t *mode_list; /* (DOWN/UP) */
+} emgd_drm_query_mode_list_t;
+
+
+typedef struct _kdrm_get_golden_htotal {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_info_t *in_mode; /* (DOWN/UP) */
+ igd_display_info_t *out_mode; /* (DOWN/UP) */
+} emgd_drm_get_golden_htotal_t;
+
+typedef struct _kdrm_set_attrs {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned short port_number; /* (DOWN) */
+ /** The number of attributes sent to the kernel. */
+ unsigned int list_size; /* (DOWN) */
+ /**
+ * Note: the attribute list is variable-sized data, but an ioctl must use a
+ * fixed-sized struct. Thus, this struct contains both a pointer to the
+ * attribute list (in user space, which must be copied separately from this
+ * struct) and the number of attibutes (above).
+ */
+ igd_attr_t *attr_list; /* (DOWN) */
+} emgd_drm_set_attrs_t;
+
+
+typedef struct _kdrm_set_palette_entry {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned long palette_entry; /* (DOWN) */
+ unsigned long palette_color; /* (DOWN) */
+} emgd_drm_set_palette_entry_t;
+
+
+typedef struct _kdrm_set_surface {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ int priority; /* (DOWN) */
+ igd_buffertype_t type; /* (DOWN) */
+ /* NOTE: igd_surface_t contains a pointer to an igd_palette_info_t struct:
+ * see the description above, in the typedef emgd_drm_alter_ovl_t.
+ */
+ igd_surface_t surface; /* (DOWN) */
+ igd_appcontext_h appcontext; /* (DOWN) a handle */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_set_surface_t;
+
+#define PRIMARY_DISPLAY 0
+#define SECONDARY_DISPLAY 1
+#define CLONE_PRIMARY PRIMARY_DISPLAY
+#define CLONE_SECONDARY SECONDARY_DISPLAY
+#define CLONE 0
+#define DIH 1
+
+#define DUAL_SCREEN_MAX_DISPLAY 2
+#define MAX_FFB_SURF_VEXT DUAL_SCREEN_MAX_DISPLAY
+#define MAX_FFB_SURF_DIH 1
+
+typedef struct _kdrm_dihclone_set_surface {
+ int rtn; /* (UP) - return value of HAL procedure */
+ unsigned long dih_clone_display; /* (DOWN) - primary or secondary display to clone */
+ unsigned long mode; /* (DOWN) - dih to clone or back to dih */
+} emgd_drm_dihclone_set_surface_t;
+
+typedef struct _kdrm_control_plane_format {
+ /* Note on modification to the structure to accomodate both
+ * Use PRIMARY/SECONDARY to indicate which display
+ * FB blend + overlay to turn ON/OFF. The relationship between
+ * plane, pipe and port is transparent to the user.
+ * A qualifier (use_plane) is used to decide which model the user wants.
+ */
+ int rtn; /* (UP) - return value of HAL procedure */
+ /* (DOWN) Turn off transparency by switching to XRGB format = 0
+ Turn on transparency by switching to ARGB format = 1 */
+ int enable;
+ union {
+ /* (DOWN) Plane A = 0
+ Plane B = 1 */
+ int display_plane;
+ /* (DOWN) Primary/Secondary display handle */
+ igd_display_h primary_secondary_dsp;
+ };
+ /* If set, KMD will use the plane convention */
+ unsigned int use_plane;
+} emgd_drm_control_plane_format_t;
+
+
+typedef struct _kdrm_set_overlay_display{
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h ovl_display[OVL_MAX_HW]; /* (DOWN) Overlay display handles */
+} emgd_drm_set_overlay_display_t;
+
+
+typedef struct _kdrm_sync {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ int priority; /* (DOWN) */
+ unsigned long in_sync; /* (DOWN/UP) */
+ unsigned long flags; /* (DOWN) */
+} emgd_drm_sync_t;
+
+
+typedef struct _kdrm_driver_pre_init {
+ int rtn; /* (UP) - return value of HAL procedure */
+ /**
+ * The set of user-specified parameters, parsed at X server PreInit() time.
+ */
+ igd_param_t params; /* (DOWN) */
+ /**
+ * The results of the HAL's igd_get_config_info() procedure. The
+ * user-space code allocates memory for this.
+ */
+ igd_config_info_t config_info; /* (UP) */
+ /* this is passed in by intelPreInit */
+ unsigned long bpp;
+} emgd_drm_driver_pre_init_t;
+
+
+typedef struct _kdrm_driver_get_ports {
+ int rtn; /* (UP) - return value of HAL procedure */
+ /** An array of ports discovered by the device-specific HAL driver. */
+ unsigned long ports[IGD_MAX_PORTS]; /* (UP) */
+} emgd_drm_driver_get_ports_t;
+
+
+typedef struct _kdrm_driver_get_chipset_info {
+ unsigned long device_id;
+ unsigned long revision_id;
+ char name[40];
+ char description[20];
+} emgd_drm_driver_get_chipset_info_t;
+
+
+typedef struct _kdrm_get_page_list {
+ int rtn; /* (UP) - return value of kernel-mode test code() */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned long offset; /* (DOWN) - surface offset (ID) */
+ unsigned long addr_count; /* (DOWN) - size of address list */
+ unsigned long *addr_list; /* (UP) */
+} emgd_drm_get_page_list_t;
+
+typedef struct _kdrm_start_pvrsrv {
+ int xserver; /* (DOWN) - 1 if called by X server, else 0 */
+ int rtn; /* (UP) - return value of PVRSRVDrmLoad() */
+} emgd_drm_start_pvrsrv_t;
+
+typedef struct _kdrm_test_pvrsrv {
+ emgd_drm_test_pvrsrv_opcodes_t opcode; /* (DOWN) */
+ int rtn; /* (UP) - return value of kernel-mode test code() */
+ char rtn_msg[1024]; /* (UP) */
+} emgd_drm_test_pvrsrv_t;
+
+
+typedef struct _kdrm_query_2d_caps_hwhint {
+ unsigned long caps_val; /* (DOWN) */
+ unsigned long *status; /* (UP) */
+} emgd_drm_query_2d_caps_hwhint_t;
+
+/* For Buffer Class FCB #17711*/
+typedef struct _kdrm_bc_ts {
+ int rtn;
+ int width;
+ int height;
+ int stride;
+ int is_continous;
+ unsigned long dev_id;
+ unsigned long buf_id;
+ unsigned long buf_tag;
+ unsigned long num_buf;
+ unsigned long pixel_format;
+ unsigned long phyaddr;
+ unsigned long virtaddr;
+ unsigned int mapped;
+} emgd_drm_bc_ts_t;
+
+typedef struct _kdrm_unlock_planes {
+ int rtn; /* (UP) - return value of HAL procedure */
+ igd_display_h display_handle; /* (DOWN) - an "opaque handle" */
+ unsigned int screen_num; /*primary=0, secondary=1 */
+} emgd_drm_unlock_planes_t;
+
+/*
+ * This is where all the IOCTL's used by the egd DRM interface are
+ * defined. This information is shared between the user space code and
+ * the kernel module.
+ */
+
+#define BASE DRM_COMMAND_BASE
+
+/*
+ * EMGD-specific ioctls. These get mapped to the device specific range
+ * between 0x40 and 0x79.
+ *
+ * Client driver must use these values!
+ */
+#define DRM_IGD_ALTER_CURSOR 0x00
+#define DRM_IGD_ALTER_CURSOR_POS 0x01
+#define DRM_IGD_ALTER_DISPLAYS 0x02
+#define DRM_IGD_ALTER_OVL 0x03
+#define DRM_IGD_APPCTX_ALLOC 0x04
+#define DRM_IGD_APPCTX_FREE 0x05
+#define DRM_IGD_DRIVER_SAVE_RESTORE 0x06
+#define DRM_IGD_ENABLE_PORT 0x07
+#define DRM_IGD_GET_ATTRS 0x08
+#define DRM_IGD_GET_DISPLAY 0x09
+#define DRM_IGD_GET_EDID_BLOCK 0x0a
+#define DRM_IGD_GET_EDID_INFO 0x0b
+#define DRM_IGD_GET_PIXELFORMATS 0x0c
+#define DRM_IGD_GET_PORT_INFO 0x0d
+#define DRM_IGD_GMM_ALLOC_REGION 0x0e
+#define DRM_IGD_GMM_ALLOC_SURFACE 0x0f
+#define DRM_IGD_GMM_FREE 0x10
+#define DRM_IGD_GMM_FLUSH_CACHE 0x11
+#define DRM_IGD_GMM_GET_NUM_SURFACE 0x31
+#define DRM_IGD_GMM_GET_SURFACE_LIST 0x32
+#define DRM_IGD_GET_GOLDEN_HTOTAL 0x33
+#define DRM_IGD_CONTROL_PLANE_FORMAT 0x34
+#define DRM_IGD_QUERY_2D_CAPS_HWHINT 0x35
+#define DRM_IGD_DIHCLONE_SET_SURFACE 0x36
+#define DRM_IGD_SET_OVERLAY_DISPLAY 0x37
+#define DRM_IGD_WAIT_VBLANK 0x40
+
+/*
+ * The EMGD DRM includes the PVR DRM, and as such, includes the following PVR
+ * DRM ioctls. The numbering must be kept in sync with what is defined in
+ * "emgd_shared.h":
+ */
+#define DRM_IGD_RESERVED_1 DRM_PVR_RESERVED1 /* Reserved */
+#define DRM_IGD_RESERVED_2 DRM_PVR_RESERVED2 /* Reserved */
+#define DRM_IGD_RESERVED_3 DRM_PVR_RESERVED3 /* Reserved */
+#define DRM_IGD_RESERVED_4 DRM_PVR_RESERVED4 /* Reserved */
+#define DRM_IGD_RESERVED_5 DRM_PVR_RESERVED5 /* Reserved */
+#define DRM_IGD_PAN_DISPLAY 0x17
+#define DRM_IGD_POWER_DISPLAY 0x18
+#define DRM_IGD_PWR_ALTER 0x19
+#define DRM_IGD_QUERY_DC 0x1a
+#define DRM_IGD_QUERY_MAX_SIZE_OVL 0x1b
+#define DRM_IGD_QUERY_OVL 0x1c
+#define DRM_IGD_QUERY_MODE_LIST 0x1d
+/*
+ * Another PVR DRM ioctl that must be kept in sync with what is defined in
+ * "emgd_shared.h":
+ */
+#define DRM_IGD_RESERVED_6 DRM_PVR_RESERVED6 /* Reserved */
+#define DRM_IGD_SET_ATTRS 0x1f
+#define DRM_IGD_SET_PALETTE_ENTRY 0x20
+#define DRM_IGD_SET_SURFACE 0x21
+#define DRM_IGD_SYNC 0x22
+#define DRM_IGD_DRIVER_PRE_INIT 0x23
+#define DRM_IGD_DRIVER_GET_PORTS 0x24
+#define DRM_IGD_START_PVRSRV 0x25
+#define DRM_IGD_TEST_PVRSRV 0x26
+/* For Video (MSVDX/TOPAZ) */
+#define DRM_IGD_VIDEO_CMD_BUF 0x27
+#define DRM_IGD_GET_DEVICE_INFO 0x28
+#define DRM_IGD_INIT_VIDEO 0x29
+#define DRM_IGD_VIDEO_GET_INFO 0x2a
+#define DRM_IGD_VIDEO_FLUSH_TLB 0x2b
+/* For X driver */
+#define DRM_IGD_GET_DRM_CONFIG 0x2c
+#define DRM_IGD_GET_PAGE_LIST 0x2d
+#define DRM_IGD_GET_OVL_INIT_PARAMS 0x2e
+#define DRM_IGD_ALTER_OVL2 0x2f
+#define DRM_IGD_GET_CHIPSET_INFO 0x30
+#define DRM_IGD_GET_DISPLAY_INFO 0x38
+#define DRM_IGD_PREINIT_MMU 0x39
+#define DRM_IGD_UNLOCK_PLANES 0x47
+
+/* For Buffer Class of Texture Stream */
+#define DRM_IGD_BC_TS_INIT 0x40
+#define DRM_IGD_BC_TS_UNINIT 0x41
+#define DRM_IGD_BC_TS_REQUEST_BUFFERS 0x42
+#define DRM_IGD_BC_TS_RELEASE_BUFFERS 0x43
+#define DRM_IGD_BC_TS_SET_BUFFER_INFO 0x44
+#define DRM_IGD_BC_TS_GET_BUFFERS_COUNT 0x45
+#define DRM_IGD_BC_TS_GET_BUFFER_INDEX 0x46
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
+#define DRMFB_PITCH pitches[0]
+#define DRMMODE_HANDLE handles[0]
+#define DRM_MODE_FB_CMD_TYPE drm_mode_fb_cmd2
+#else
+#define DRMFB_PITCH pitch
+#define DRMMODE_HANDLE handle
+#define DRM_MODE_FB_CMD_TYPE drm_mode_fb_cmd
+#endif
+
+/*
+ * egd IOCTLs.
+ */
+#define DRM_IOCTL_IGD_ALTER_CURSOR DRM_IOWR(DRM_IGD_ALTER_CURSOR + BASE,\
+ emgd_drm_alter_cursor_t)
+#define DRM_IOCTL_IGD_ALTER_CURSOR_POS DRM_IOWR(DRM_IGD_ALTER_CURSOR_POS +\
+ BASE,\
+ emgd_drm_alter_cursor_pos_t)
+#define DRM_IOCTL_IGD_ALTER_DISPLAYS DRM_IOWR(DRM_IGD_ALTER_DISPLAYS + BASE,\
+ emgd_drm_alter_displays_t)
+#define DRM_IOCTL_IGD_ALTER_OVL DRM_IOWR(DRM_IGD_ALTER_OVL + BASE,\
+ emgd_drm_alter_ovl_t)
+#define DRM_IOCTL_IGD_ALTER_OVL2 DRM_IOWR(DRM_IGD_ALTER_OVL2 + BASE,\
+ emgd_drm_alter_ovl2_t)
+#define DRM_IOCTL_IGD_APPCTX_ALLOC DRM_IOWR(DRM_IGD_APPCTX_ALLOC + BASE,\
+ emgd_drm_appcontext_alloc_t)
+#define DRM_IOCTL_IGD_APPCTX_FREE DRM_IOWR(DRM_IGD_APPCTX_FREE + BASE,\
+ emgd_drm_appcontext_free_t)
+#define DRM_IOCTL_IGD_DRIVER_SAVE_RESTORE DRM_IOWR(DRM_IGD_DRIVER_SAVE_RESTORE\
+ + BASE,\
+ emgd_drm_driver_save_restore_t)
+#define DRM_IOCTL_IGD_ENABLE_PORT DRM_IOWR(DRM_IGD_ENABLE_PORT + BASE,\
+ emgd_drm_enable_port_t)
+#define DRM_IOCTL_IGD_GET_ATTRS DRM_IOWR(DRM_IGD_GET_ATTRS + BASE,\
+ emgd_drm_get_attrs_t)
+#define DRM_IOCTL_IGD_GET_DISPLAY DRM_IOWR(DRM_IGD_GET_DISPLAY + BASE,\
+ emgd_drm_get_display_t)
+#define DRM_IOCTL_IGD_GET_DRM_CONFIG DRM_IOWR(DRM_IGD_GET_DRM_CONFIG + BASE,\
+ emgd_drm_get_drm_config_t)
+#define DRM_IOCTL_IGD_GET_EDID_BLOCK DRM_IOWR(DRM_IGD_GET_EDID_BLOCK + BASE,\
+ emgd_drm_get_EDID_block_t)
+#define DRM_IOCTL_IGD_GET_EDID_INFO DRM_IOWR(DRM_IGD_GET_EDID_INFO + BASE,\
+ emgd_drm_get_EDID_info_t)
+#define DRM_IOCTL_IGD_GET_PIXELFORMATS DRM_IOWR(DRM_IGD_GET_PIXELFORMATS +\
+ BASE,\
+ emgd_drm_get_pixelformats_t)
+#define DRM_IOCTL_IGD_GET_PORT_INFO DRM_IOWR(DRM_IGD_GET_PORT_INFO + BASE,\
+ emgd_drm_get_port_info_t)
+#define DRM_IOCTL_IGD_GMM_ALLOC_REGION DRM_IOWR(DRM_IGD_GMM_ALLOC_REGION +\
+ BASE,\
+ emgd_drm_gmm_alloc_region_t)
+#define DRM_IOCTL_IGD_GMM_ALLOC_SURFACE DRM_IOWR(DRM_IGD_GMM_ALLOC_SURFACE +\
+ BASE,\
+ emgd_drm_gmm_alloc_surface_t)
+#define DRM_IOCTL_IGD_GMM_GET_NUM_SURFACE DRM_IOW(\
+ DRM_IGD_GMM_GET_NUM_SURFACE +\
+ BASE,\
+ emgd_drm_gmm_get_num_surface_t)
+#define DRM_IOCTL_IGD_GMM_GET_SURFACE_LIST DRM_IOW(\
+ DRM_IGD_GMM_GET_SURFACE_LIST +\
+ BASE,\
+ emgd_drm_gmm_get_surface_list_t)
+#define DRM_IOCTL_IGD_GMM_FREE DRM_IOW(DRM_IGD_GMM_FREE + BASE,\
+ emgd_drm_gmm_free_t)
+#define DRM_IOCTL_IGD_GMM_FLUSH_CACHE DRM_IOR(DRM_IGD_GMM_FLUSH_CACHE + BASE,\
+ emgd_drm_gmm_flush_cache_t)
+#define DRM_IOCTL_IGD_PAN_DISPLAY DRM_IOWR(DRM_IGD_PAN_DISPLAY + BASE,\
+ emgd_drm_pan_display_t)
+#define DRM_IOCTL_IGD_POWER_DISPLAY DRM_IOWR(DRM_IGD_POWER_DISPLAY + BASE,\
+ emgd_drm_power_display_t)
+#define DRM_IOCTL_IGD_PWR_ALTER DRM_IOWR(DRM_IGD_PWR_ALTER + BASE,\
+ unsigned long)
+#define DRM_IOCTL_IGD_QUERY_DC DRM_IOWR(DRM_IGD_QUERY_DC + BASE,\
+ emgd_drm_query_dc_t)
+#define DRM_IOCTL_IGD_QUERY_MAX_SIZE_OVL DRM_IOWR(DRM_IGD_QUERY_MAX_SIZE_OVL +\
+ BASE,\
+ emgd_drm_query_max_size_ovl_t)
+#define DRM_IOCTL_IGD_QUERY_OVL DRM_IOWR(DRM_IGD_QUERY_OVL + BASE,\
+ emgd_drm_query_ovl_t)
+#define DRM_IOCTL_IGD_QUERY_MODE_LIST DRM_IOWR(DRM_IGD_QUERY_MODE_LIST + BASE,\
+ emgd_drm_query_mode_list_t)
+#define DRM_IOCTL_IGD_GET_GOLDEN_HTOTAL DRM_IOWR(DRM_IGD_GET_GOLDEN_HTOTAL + BASE,\
+ emgd_drm_get_golden_htotal_t)
+#define DRM_IOCTL_IGD_CONTROL_PLANE_FORMAT DRM_IOWR(DRM_IGD_CONTROL_PLANE_FORMAT + BASE,\
+ emgd_drm_control_plane_format_t)
+#define DRM_IOCTL_IGD_SET_OVERLAY_DISPLAY DRM_IOWR(DRM_IGD_SET_OVERLAY_DISPLAY + BASE,\
+ emgd_drm_set_overlay_display_t)
+#define DRM_IOCTL_IGD_SET_ATTRS DRM_IOWR(DRM_IGD_SET_ATTRS + BASE,\
+ emgd_drm_set_attrs_t)
+#define DRM_IOCTL_IGD_SET_PALETTE_ENTRY DRM_IOWR(DRM_IGD_SET_PALETTE_ENTRY +\
+ BASE,\
+ emgd_drm_set_palette_entry_t)
+#define DRM_IOCTL_IGD_SET_SURFACE DRM_IOWR(DRM_IGD_SET_SURFACE + BASE,\
+ emgd_drm_set_surface_t)
+#define DRM_IOCTL_IGD_SYNC DRM_IOWR(DRM_IGD_SYNC + BASE,\
+ emgd_drm_sync_t)
+#define DRM_IOCTL_IGD_DRIVER_PRE_INIT DRM_IOWR(DRM_IGD_DRIVER_PRE_INIT + BASE,\
+ emgd_drm_driver_pre_init_t)
+#define DRM_IOCTL_IGD_DRIVER_GET_PORTS DRM_IOWR(DRM_IGD_DRIVER_GET_PORTS + BASE,\
+ emgd_drm_driver_get_ports_t)
+#define DRM_IOCTL_IGD_START_PVRSRV DRM_IOWR(DRM_IGD_START_PVRSRV + BASE,\
+ emgd_drm_start_pvrsrv_t)
+#define DRM_IOCTL_IGD_TEST_PVRSRV DRM_IOWR(DRM_IGD_TEST_PVRSRV + BASE,\
+ emgd_drm_test_pvrsrv_t)
+
+#define DRM_IOCTL_IGD_GET_OVL_INIT_PARAMS DRM_IOWR(DRM_IGD_GET_OVL_INIT_PARAMS + BASE,\
+ emgd_drm_get_ovl_init_params_t)
+#define DRM_IOCTL_IGD_GET_CHIPSET_INFO DRM_IOWR(DRM_IGD_GET_CHIPSET_INFO + BASE,\
+ emgd_drm_driver_get_chipset_info_t)
+#define DRM_IOCTL_IGD_QUERY_2D_CAPS_HWHINT DRM_IOWR(DRM_IGD_QUERY_2D_CAPS_HWHINT + BASE,\
+ emgd_drm_query_2d_caps_hwhint_t)
+#define DRM_IOCTL_IGD_GET_DISPLAY_INFO DRM_IOR(DRM_IGD_GET_DISPLAY_INFO + BASE,\
+ emgd_drm_get_display_info_t)
+
+#define DRM_IOCTL_IGD_DIHCLONE_SET_SURFACE DRM_IOWR(DRM_IGD_DIHCLONE_SET_SURFACE + BASE,\
+ emgd_drm_dihclone_set_surface_t)
+
+#define DRM_IOCTL_IGD_WAIT_VBLANK DRM_IOWR(DRM_IGD_WAIT_VBLANK + BASE,\
+ emgd_drm_driver_set_sync_refresh_t)
+
+
+/* From pvr_bridge.h */
+#define DRM_IOCTL_IGD_RESERVED_1 DRM_IOW(DRM_IGD_RESERVED_1 + BASE, \
+ PVRSRV_BRIDGE_PACKAGE)
+#define DRM_IOCTL_IGD_RESERVED_2 DRM_IO(DRM_IGD_RESERVED_2 + BASE)
+#define DRM_IOCTL_IGD_RESERVED_3 DRM_IO(DRM_IGD_RESERVED_3 + BASE)
+#define DRM_IOCTL_IGD_RESERVED_4 DRM_IO(DRM_IGD_RESERVED_4 + BASE)
+#define DRM_IOCTL_IGD_RESERVED_5 DRM_IOWR(DRM_IGD_RESERVED_5 + BASE, \
+ unsigned long)
+#define DRM_IOCTL_IGD_RESERVED_6 DRM_IO(DRM_IGD_RESERVED_6 + BASE)
+
+/* For Video (MXVDX/TOPAZ) */
+#define DRM_IOCTL_IGD_VIDEO_CMD_BUF DRM_IOR(DRM_IGD_VIDEO_CMD_BUF + BASE,\
+ emgd_drm_video_cmd_buf_t)
+#define DRM_IOCTL_IGD_GET_DEVICE_INFO DRM_IOR(DRM_IGD_GET_DEVICE_INFO + BASE,\
+ emgd_drm_device_info_t)
+#define DRM_IOCTL_IGD_GET_PAGE_LIST DRM_IOR(DRM_IGD_GET_PAGE_LIST + BASE,\
+ emgd_drm_get_page_list_t)
+#define DRM_IOCTL_IGD_INIT_VIDEO DRM_IOR(DRM_IGD_INIT_VIDEO + BASE,\
+ emgd_drm_init_video_t)
+#define DRM_IOCTL_IGD_VIDEO_GET_INFO DRM_IOR(DRM_IGD_VIDEO_GET_INFO + BASE,\
+ emgd_drm_video_get_info_t)
+#define DRM_IOCTL_IGD_VIDEO_FLUSH_TLB DRM_IOR(DRM_IGD_VIDEO_FLUSH_TLB + BASE,\
+ emgd_drm_video_flush_tlb_t)
+#define DRM_IOCTL_IGD_PREINIT_MMU DRM_IOR(DRM_IGD_PREINIT_MMU + BASE,\
+ emgd_drm_preinit_mmu_t)
+#define DRM_IOCTL_IGD_UNLOCK_PLANES DRM_IOR(DRM_IGD_UNLOCK_PLANES + BASE,\
+ emgd_drm_unlock_planes_t)
+#define DRM_IOCTL_IGD_GET_DISPLAY_INFO DRM_IOR(DRM_IGD_GET_DISPLAY_INFO + BASE,\
+ emgd_drm_get_display_info_t)
+/* For Buffer Class of Texture Stream */
+#define DRM_IOCTL_IGD_BC_TS_INIT DRM_IOR(DRM_IGD_BC_TS_INIT + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_UNINIT DRM_IOR(DRM_IGD_BC_TS_UNINIT + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_REQUEST_BUFFERS DRM_IOR(DRM_IGD_BC_TS_REQUEST_BUFFERS + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_RELEASE_BUFFERS DRM_IOR(DRM_IGD_BC_TS_RELEASE_BUFFERS + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_SET_BUFFER_INFO DRM_IOR(DRM_IGD_BC_TS_SET_BUFFER_INFO + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_GET_BUFFERS_COUNT DRM_IOR(DRM_IGD_BC_TS_GET_BUFFERS_COUNT + BASE,\
+ emgd_drm_bc_ts_t)
+#define DRM_IOCTL_IGD_BC_TS_GET_BUFFER_INDEX DRM_IOR(DRM_IGD_BC_TS_GET_BUFFER_INDEX + BASE,\
+ emgd_drm_bc_ts_t)
+#endif
diff --git a/drivers/gpu/drm/emgd/include/emgd_shared.h b/drivers/gpu/drm/emgd/include/emgd_shared.h
new file mode 100644
index 0000000..fe576ed
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/emgd_shared.h
@@ -0,0 +1,98 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_shared.h
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This include file contains information that is shared between the various
+ * EMGD driver components.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _EMGD_SHARED_H
+#define _EMGD_SHARED_H
+
+/*
+ * Module name is the name of the drm kernel module. This is used by
+ * user space components to open a connection to the module. A typical
+ * call would look like -- drmOpen(EMGD_MODULE_NAME, NULL);
+ */
+#define EMGD_MODULE_NAME "emgd"
+
+#define EMGD_DRIVER_NAME "emgd"
+
+/*
+ * EMGD-specific numbering of the PVR DRM ioctls. The EMGD DRM module is in
+ * charge, and includes the PVR DRM code. As such, the PVR ioctls are included
+ * in with the EMGD ioctls ("emgd_drm.h"), and must be kept in sync. Both sets
+ * of these ioctls are mapped to the device specific range between 0x40 and
+ * 0x79.
+ *
+ * Client driver must use these values!
+ */
+#define DRM_PVR_RESERVED1 0x12
+#define DRM_PVR_RESERVED2 0x13
+#define DRM_PVR_RESERVED3 0x14
+#define DRM_PVR_RESERVED4 0x15
+#define DRM_PVR_RESERVED5 0x16
+#define DRM_PVR_RESERVED6 0x1E
+
+
+/*
+ * The following typedefs support the ability of non-HAL software to have a
+ * function called when a VBlank interrupt occurs.
+ */
+
+/**
+ * A pointer to a non-HAL-provided function that processes a VBlank interrupt.
+ */
+typedef int (*emgd_process_vblank_interrupt_t)(void *priv);
+
+/**
+ * This structure allows the HAL to track a non-HAL callback (and its
+ * parameter) to call when a VBlank interrupt occurs for a given port. An
+ * opaque pointer to this structure serves as a unique identifier for the
+ * callback/port combination.
+ */
+typedef struct _emgd_vblank_callback {
+ /** Non-HAL callback function to process a VBlank interrupt. */
+ emgd_process_vblank_interrupt_t callback;
+ /** An opaque pointer to a non-HAL data structure (passed to callback). */
+ void *priv;
+ /** Which HAL port number is associated with this interrupt callback. */
+ unsigned long port_number;
+} emgd_vblank_callback_t;
+
+/**
+ * An opaque pointer to a emgd_vblank_callback_t. This pointer serves as a
+ * unique identifier for the callback/port combination.
+ */
+typedef void *emgd_vblank_callback_h;
+
+/**
+ * A special value of a emgd_vblank_callback_h, meaning ALL devices/displays.
+ */
+#define ALL_PORT_CALLBACKS ((void *) 1001)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/gart.h b/drivers/gpu/drm/emgd/include/gart.h
new file mode 100644
index 0000000..228ac41
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/gart.h
@@ -0,0 +1,38 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gart.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains OS independent abstractions for common gart
+ * operations.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_GART_H
+#define _OAL_GART_H
+
+typedef void * os_gart_allocation_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd.h b/drivers/gpu/drm/emgd/include/igd.h
new file mode 100755
index 0000000..701bab8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd.h
@@ -0,0 +1,1630 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd.h
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains the top level dispatch table definition and includes
+ * the common header files necessary to interface with the shingle springs
+ * graphics driver.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_H
+#define _IGD_H
+
+#include <config.h>
+#include <igd_errno.h>
+#include <igd_mode.h>
+#include <igd_appcontext.h>
+#include <igd_render.h>
+#include <igd_2d.h>
+#include <igd_pd.h>
+#include <igd_gmm.h>
+#include <igd_rb.h>
+#include <igd_ovl.h>
+#include <emgd_shared.h>
+
+/*
+ * This is needed so that 16bit ports can use a far pointer on some
+ * of the prototypes.
+ */
+#ifndef FAR
+#define FAR
+#endif
+
+
+
+/*!
+ * @ingroup render_group
+ * @brief Dispatch table for accessing all runtime driver functions.
+ *
+ * This is the dispatch table for the driver. All rendering and driver
+ * manipulation functionality is done by calling functions within this
+ * dispatch table.
+ * This dispatch table will be populated during the igd_module_init()
+ * function call. Upon returning from that call all usable members
+ * will be populated. Any members left as NULL are not supported in the
+ * current HAL configuration and cannot be used.
+ */
+typedef struct _igd_dispatch {
+ /*!
+ * Save the register state of the graphics engine.
+ * This function is optional in the HAL. The caller must check that it
+ * is non-null before calling.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @param flags Any combination of the @ref driver_save_flags
+ * flags which control the types of state to be saved. Also used to
+ * specify where we save the register data.
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+ int (*driver_save)(igd_driver_h driver_handle,
+ const unsigned long flags);
+
+ /*!
+ * Restore the graphics engine to a previously saved state.
+ * This function is optional in the HAL. The caller must check that it
+ * is non-null before calling.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @param flags Used to specify where we are restoring from,
+ * @ref driver_save_flags
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+ int (*driver_restore)(igd_driver_h driver_handle,
+ const unsigned long flags);
+
+ /*!
+ * Save all driver registers and then restore all
+ * registers from a previously saved set.
+ * This function is optional in the HAL. The caller must check that it
+ * is non-null before calling.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ * @param flags Flags indicating what registers to save
+ *
+ * @return 0 on Success
+ * @return <0 on Error
+ */
+ int (*driver_save_restore)(igd_driver_h driver_handle, unsigned long flags);
+
+ /*!
+ * Gets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * @note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+ int (*get_param)(igd_display_h display_handle, unsigned long id,
+ unsigned long *value);
+
+ /*!
+ * Sets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * Note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+ int (*set_param)(igd_display_h display_handle, unsigned long id,
+ unsigned long value);
+
+ /*!
+ * This function returns the list of available pixel formats for the
+ * framebuffer and the list of available pixel formats for the cursor.
+ *
+ * Both lists end with NULL. They are read only and should
+ * not be modified.
+ *
+ * @bug To be converted to take a driver handle for IEGD 5.1
+ *
+ * @param display_handle A igd_display_h type returned from a previous
+ * display->alter_displays() call.
+ *
+ * fb_list_pfs - Returns the list of pixel formats for the framebuffer.
+ *
+ * cu_list_pfs - Returns the list of pixel formats for the cursor.
+ *
+ *
+ * Returns:
+ * 0: Success
+ * -IGD_INVAL: Error;
+ */
+ int (*get_pixelformats)(igd_display_h display_handle,
+ unsigned long **fb_list_pfs, unsigned long **cu_list_pfs,
+ unsigned long **overlay_pfs, unsigned long **render_pfs,
+ unsigned long **texture_pfs);
+
+ /*!
+ * @brief Return the list of available DCs.
+ *
+ * query_dc() returns the live zero terminated Display Configuration list.
+ * All usable display configurations are returned from the HAL. The IAL
+ * must select one from the list when calling alter_displays().
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init()
+ *
+ * @param dc_list The returned display configuration(s) list. The IAL
+ * should use a dc from the list when calling alter_displays(). The
+ * dc_list is zero terminated and live. It should not be altered by the
+ * IAL. See @ref dc_defines
+ *
+ * @param flags modifies the behavior of the function.
+ * See: @ref query_dc_flags
+ *
+ * @return 0: Success.
+ * @return -IGD_INVAL: Otherwise
+ */
+ int (*query_dc)(igd_driver_h driver_handle, unsigned long request,
+ unsigned long **dc_list, unsigned long flags);
+
+ /*!
+ * Returns a live copy of the current mode list
+ * for the requested display. This mode list will be for the master
+ * port on the pipe and therefore may be the mode list for a TWIN
+ * of the display requested.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init()
+ *
+ * @param dc The display configuration data to use when determining the
+ * available modes. See @ref dc_defines
+ *
+ * @param mode_list The returned mode list. This data should be freed by
+ * calling free_modes() unless the QUERY_LIVE_MODES flag was passed, in
+ * that case the live, in-use, data structure is returned. It should not
+ * be modified or freed.
+ *
+ * @param flags Flags to modify the operation of the function. Flags
+ * may contain any combination of the IGD_QUERY_* flags.
+ * See: @ref query_mode_list_flags
+ *
+ * @return 0: Success.
+ * @return -IGD_ERROR_INVAL: Otherwise
+ */
+ int (*query_mode_list)(igd_driver_h driver_handle, unsigned long dc,
+ igd_display_info_t **mode_list, unsigned long flags);
+
+ /*!
+ * Free modes that were returned from a previous call to query mode list.
+ *
+ * @param mode_list The mode list to be free. This data was returned
+ * from an earlier call to query_modes.=
+ */
+ void (*free_mode_list)(igd_display_info_t *mode_list);
+
+ /*!
+ * alter_displays() Modifies the modes associated with one or both display
+ * pipes according to the dc provided. The primary and secondary
+ * display handles are returned for use when rendering to these displays.
+ *
+ * In extended or DIH modes only one fb_info needs to be provided at a
+ * time. In this manner two calls can be used one per framebuffer, as
+ * may be required by the OS.
+ *
+ * @param driver_handle - required. This is returned from a call to
+ * igd_init_driver().
+ *
+ * @param primary A pointer to a display handle that will be populated
+ * during the call. This handle should be used for all rendering
+ * tasks directed to the primary framebuffer and pipe.
+ *
+ * @param primary_pt_info The display timing information to be used for
+ * the primary display pipe.
+ *
+ * @param primary_fb_info The framebuffer parameters to be used for the
+ * primary display. This data may be larger or smaller than the display
+ * timings to allow for centered/panned or scaled modes.
+ *
+ * @param secondary A pointer to a display handle that will be populated
+ * during the call. This handle should be used for all rendering
+ * tasks directed to the secondary framebuffer or pipe.
+ *
+ * @param secondary_pt_info The display timing information to be used for
+ * the secondary display pipe.
+ *
+ * @param secondary_fb_info The framebuffer parameters to be used for the
+ * secondary display. This data may be larger or smaller than the display
+ * timings to allow for centered/panned or scaled modes.
+ *
+ * @param dc A unique identifer to describe the configuration of the
+ * displays to be used. This identifier should be one returned from
+ * the _igd_dispatch::query_dc() call. See @ref dc_defines.
+ *
+ * @param flags Bitfield to alter the behavior of the call.
+ */
+ int (*alter_displays)(igd_driver_h driver_handle,
+ igd_display_h *primary,
+ igd_display_info_t *primary_pt_info,
+ igd_framebuffer_info_t *primary_fb_info,
+ igd_display_h *secondary,
+ igd_display_info_t *secondary_pt_info,
+ igd_framebuffer_info_t *secondary_fb_info,
+ unsigned long dc,
+ unsigned long flags);
+
+ /*!
+ * igd_configure_display() Modifies the modes associated with one display
+ * pipes according to the dc provided.
+ *
+ * @param driver_handle - required. This is returned from a call to
+ * igd_init_driver().
+ *
+ * @param display A pointer to a display handle that will be used
+ * during the call. This handle should be used for all rendering
+ * tasks directed to the secondary framebuffer or pipe.
+ *
+ * @param pt_info The display timing information to be used for
+ * the display pipe.
+ *
+ * @param fb_info The framebuffer parameters to be used for the
+ * display. This data may be larger or smaller than the display
+ * timings to allow for centered/panned or scaled modes.
+ *
+ * @param dc A unique identifer to describe the configuration of the
+ * displays to be used. This identifier should be one returned from
+ * the _igd_dispatch::query_dc() call. See @ref dc_defines.
+ *
+ * @param fb_index What is the 0-based framebuffer index
+ *
+ * @param flags Bitfield to alter the behavior of the call.
+ */
+ int (*igd_configure_display)(
+ igd_driver_h driver_handle,
+ igd_display_h *display,
+ igd_display_info_t *pt_info,
+ igd_framebuffer_info_t *fb_info,
+ unsigned long dc,
+ int fb_index,
+ unsigned long flags);
+
+ /*!
+ * pan_display() pans the display on the display device.
+ * It takes a @a x_offset, @a y_offset into the frame buffer and
+ * sets the display from (x_offset, y_offset) to
+ * (x_offset+width, y_offset+height).
+ * If x_offset+width, y_offset+height crosses frame buffer
+ * width and heigth, then it will return error.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ * from a successful call to dispatch->alter_displays().
+ *
+ * @param x_offset these are frame buffer offsets from (0, 0).
+ * @param y_offset these are frame buffer offsets from (0, 0).
+ *
+ * @return 0: The paning was successfull.
+ * @return -IGD_INVAL: Otherwise
+ */
+ long (*pan_display)(igd_display_h display_handle,
+ unsigned long x_offset,
+ unsigned long y_offset);
+
+ /*!
+ * Alters the current power state for the display. This does not
+ * change the power state for the graphics hardware device.
+ *
+ * @bug Needs to be modified to power all displays on a pipe
+ *
+ * @param driver_handle - handle to a driver handle returned from a
+ * previous call to igd_driver_init()
+ *
+ * @param port_number - specific display (port) to change.
+ *
+ * @param power_state - D state to change to.
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*power_display)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned int power_state);
+
+ /*!
+ * This function sets one palette entry for the framebuffer when the
+ * pixel format for the framebuffer indicates a palette is used.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param palette_color A 32bit ARGB color
+ *
+ * @param palette_entry The palette index to set.
+ *
+ * @returns
+ * - 0: Success
+ * - -IGD_INVAL: Otherwise
+ */
+ int (*set_palette_entry)(igd_display_h display_handle,
+ unsigned long palette_entry,
+ unsigned long palette_color);
+ /*!
+ * This function gets the requested palette entry from the hardware.
+ * The results are undefined when not in a paletted mode or in a
+ * mode that uses palette for color correction.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param palette_color A 32bit ARGB color
+ *
+ * @param palette_entry The palette index to return.
+ *
+ * @returns 0 on Success
+ * @returns -IGD_ERROR_INVAL Otherwise
+ */
+ int (*get_palette_entry)(igd_display_h display_handle,
+ unsigned long palete_entry,
+ unsigned long *palette_color);
+
+ /*!
+ * This function sets "count" palette entries starting with "count"
+ * offset into the palette_colors array.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param palette_colors A 32bit ARGB color array
+ *
+ * @param start_index The first palette index to program.
+ *
+ * @param count The number of palette entries to program.
+ *
+ * @returns 0 on Success
+ * @return -IGD_ERROR_INVAL Otherwise
+ */
+ int (*set_palette_entries)(igd_display_h display_handle,
+ unsigned long *palette_colors, unsigned int start_index,
+ unsigned int count);
+
+
+ /*!
+ * Gets attributes for a display. SS will allocate the memory required to
+ * return the *attr_list. This is a live copy of attributes used by both
+ * IAL and HAL. Don't deallocate this memory. This will be freed by the
+ * HAL.
+ *
+ * @param driver_handle Driver handle returned from a call to
+ * igd_driver_init()
+ *
+ * @param num_attrs pointer to return the number of attributes
+ * returned in attr_list.
+ *
+ * @param attr_list pointer to return the attributes.
+ *
+ * @returns 0 onSuccess
+ * @returns -IGD_ERROR_NOATTR No attributes defined for this display
+ * @returns -IGD_INVAL otherwise
+ */
+ int (*get_attrs)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned long *num_attrs,
+ igd_attr_t **attr_list);
+
+ /*!
+ * set attributes for a display.
+ *
+ * @param driver_handle Driver handle returned from a call to
+ * igd_driver_init()
+ *
+ * @param num_attrs pointer to return the number of attributes
+ * returned in attr_list. This is equal to the num_attrs returned by
+ * igd_get_attrs().
+ *
+ * @param attr_list pointer returned from igd_get_attrs(). Change
+ * the attributes to desired values.
+ *
+ * @returns 0 on Success
+ * @returns -IGD_ERROR_NOATTR No attributes defined for this display
+ * @returns -IGD_INVAL Otherwise
+ */
+ int (*set_attrs)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned long num_attrs,
+ igd_attr_t *attr_list);
+
+ /*!
+ * set flags for a display.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param port_number of the port to modify. (use zero to change
+ * all ports associated with a display?)
+ *
+ * @param flag to set in the port's pt_info before calling program
+ * port.
+ *
+ * @returns 0 on Success
+ * @returns -IGD_INVAL Otherwise
+ */
+ int (*enable_port)(igd_display_h display_handle,
+ unsigned short port_number,
+ unsigned long flag,
+ unsigned long test);
+
+ /*!
+ * This functions returns the current scanline for the display handle
+ * provided. The scanline will be accurate when possible, or equal
+ * to IGD_IN_VBLANK, or IGD_IN_VSYNC during the vblank/vsync periods.
+ * See @ref get_scanline_defs
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param scanline An unsigned long pointer which will be populated by
+ * the HAL during the call.
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*get_scanline)(igd_display_h display_handle, int *scanline);
+
+ /*!
+ * This function alters the parameters associated with a cursor.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param cursor_info An igd_cursor_info_t data structure with the
+ * parameters to be applied to the cursor.
+ *
+ * @param image A pointer to cursor image data. The image data
+ * will only be programmed with the cursor flag has either
+ * IGD_CURSOR_LOAD_ARGB_IMAGE or IGD_CURSOR_LOAD_XOR_IMAGE.
+ *
+ * @param 0 on Success
+ * @param <0 on Error
+ */
+ int (*alter_cursor)(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info, unsigned char *image);
+
+ /*!
+ * This function alters the position parameters associated with a cursor.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @param cursor_info An igd_cursor_info_t data structure with the
+ * parameters to be applied to the cursor. Only the x_offset and y_offset
+ * parameters will be used.
+ *
+ * @param 0 on Success
+ * @param <0 on Error
+ */
+ int (*alter_cursor_pos)(igd_display_h display_handle,
+ igd_cursor_info_t *cursor_info);
+
+ /*!
+ * This function will block until the start of the next vblank/vsync
+ * period.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*wait_vblank)(igd_display_h display_handle);
+
+ /*!
+ * This function will block until the start of the next vblank/vsync
+ * period.
+ *
+ * @param display_handle Display handle returned from a call to
+ * _igd_dispatch::alter_displays()
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*wait_vsync)(igd_display_h display_handle);
+
+ int (*query_in_vblank)(igd_display_h display_handle);
+
+ /*!
+ * This function is to access I2C register values for the specified I2C
+ * bus. Memory for 'igd_i2c_reg_t->buffer' should be allocated and freed
+ * by caller.
+ * This function is valid only for display connected via DIGITAL (DVO)
+ * ports.
+ *
+ * @bug Documentation needs update or Remove
+ *
+ * @param driver IGD driver handle.
+ *
+ * @param i2c_reg pointer to the i2c register structure.
+ *
+ * @param flags If the flags is
+ * IGD_I2C_WRITE - then igd_i2c_reg_t->buffer should point
+ * to array of 'num_bytes' number of valid I2C registers values.
+ * IGD_I2C_READ - then igd_i2c_reg_t->buffer pointer should have space
+ * for 'num_bytes' number of valid I2C registers.
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*access_i2c)(igd_display_h display, igd_i2c_reg_t *i2c_reg,
+ unsigned long flags);
+
+ /*!
+ * This function is to get the EDID information (not the actual block) for
+ * the display device associated with the 'display_handle'.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ * @param port_number display port number connected to display.
+ * @param edid_version EDID version number.
+ * @param edid_revision EDID revision number.
+ * @param edid_size Tells the caller what size of buffer to allocate
+ * for the transfer.
+ *
+ * @returns 0 on Success
+ * @returns -IGD_ERROR_EDID Error while reading EDID or no EDID
+ * @return -IGD_INVAL Other error
+ */
+ int (*get_EDID_info)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned char *edid_version,
+ unsigned char *edid_revision,
+ unsigned long *edid_size);
+
+ /*!
+ * This function is to get the EDID block of the specified size. The size
+ * is returned from previous call to igd_get_EDID_info().
+ *
+ * @note The return value indicates success/failure, blocksize should be
+ * set by the API to the actual number of bytes transferred upon return.
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ * @param port_number Specific display to query for EDID block data.
+ * @param edid_ptr Buffer to hold the EDID block data, must be 128bytes.
+ * @param block_number Tells the API which EDID block to read.
+ *
+ * @returns 0 on Success
+ * @returns -IGD_ERROR_EDID Error while reading EDID or no EDID
+ * @returns -IGD_INVAL Other error
+ */
+ int (*get_EDID_block)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ unsigned char FAR *edid_ptr,
+ unsigned char block_number);
+
+ /*!
+ * This function returns the information about the port/display
+ *
+ * @param driver_handle pointer to an IGD_DRIVER_H pointer returned
+ * from a successful call to igd_driver_init().
+ *
+ * @param port_number Specific port to get information for.
+ *
+ * @param port_info Port/display information
+ *
+ * @returns 0 on Success
+ * @returns -IGD_INVAL Otherwise
+ */
+ int (*get_port_info)(igd_driver_h driver_handle,
+ unsigned short port_number,
+ igd_port_info_t *port_info);
+
+ /*
+ * Sync is used to insert and check the status of synchronization
+ * points in the command queue. A sync inserted into the queue and
+ * then check insures that all rendering commands inserted before the
+ * sync are now complete.
+ *
+ * Sync should be called with the IGD_RENDER_NONBLOCK flag to insert
+ * a new sync without waiting for completion. When called with
+ * IGD_RENDER_BLOCK the call will wait for completion but may return
+ * due to a timeout. The caller should determine if calling again is
+ * prudent or if some other action should be taken insead of busy
+ * waiting.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ * from a successful call to dispatch->alter_displays().
+ *
+ * @param priority The command queue to use. IGD_PRIORITY_NORMAL is
+ * correct for most circumstances.
+ *
+ * @param sync The sync identifier that will be populated and returned
+ * during the call. To insert a new sync, this should be passed
+ * containing 0 (A pointer to a zero). To check the status of an
+ * existing sync pass the value returned from a previous call to
+ * this function.
+ *
+ * @param flags Sync flags.
+ *
+ * @returns
+ * 0: On Success
+ * -IGD_ERROR_BUSY: When the sync is not yet complete
+ */
+ int (*sync)(igd_display_h display_handle, int priority,
+ unsigned long *sync, unsigned long flags);
+ /*
+ * Idle stalls until the entire engine has been idled.
+ */
+ int (*idle)(igd_driver_h driver_handle);
+
+ /* igd_appcontext.h */
+ igd_appcontext_h (*appcontext_alloc)(igd_display_h display_handle,
+ int priority, unsigned int flags);
+ void (*appcontext_free)(igd_display_h display_handle,
+ int priority, igd_appcontext_h context_handle);
+
+ /* igd_pwr.h */
+ int (*pwr_alter)(igd_driver_h driver_handle, unsigned int power_state);
+ int (*pwr_query)(igd_driver_h driver_handle, unsigned int power_state);
+
+ /* igd_reset.h */
+ int (*reset_alter)(igd_driver_h driver_handle);
+
+ /* igd_gmm.h */
+
+ /*!
+ * This function is used by igd client drivers to allocate surfaces from
+ * graphics memory. A driver must use this function to allocate all
+ * surfaces, and must in turn free the surfaces with dispatch->gmm_free()
+ * before exit. Calls to this function are only valid after the gmm_init()
+ * function has been called by the igd init module.
+ *
+ * @param offset The offset into the Gtt memory space that the surface
+ * begins. This is an output only. Each element of this array can be
+ * added to the base physical or virtual address to obtain a full
+ * virtual or physical address. Therefore this parameter should be
+ * accessed as offset[x]. The number of offset elements is dependent on
+ * the surface type. Normal and Buffer surfaces return 1 element, Mip Map
+ * surfaces return NumMips level elements. Cube Map surfaces return
+ * NumMips level elements. Volume Map surfaces return NumSlices elements.
+ * For Volume Maps: The number of planes decreases by half for each
+ * mip level just as the number of X and Y pixels decreases by half.
+ * All plane offsets for the first mip are returned first followed
+ * by all planes for the second mip and so-forth.
+ *
+ * @param pixel_format The pixel format id. See @ref pixel_formats
+ *
+ * @param width The width in pixels of the surface. This may be modified
+ * to be larger than the requested value.
+ *
+ * @param height Height in pixels of the surface. This may be modified to
+ * be larger than the requested value.
+ *
+ * @param pitch The pitch in bytes of the surface. This value is returned
+ * by the driver.
+ *
+ * @param size The size of the surface in bytes. This value is returned by
+ * the driver. In Planar formats this will be greater than height*pitch
+ *
+ * @param type The defined type of the surface to be allocated.
+ * See @ref alloc_surface_types
+ *
+ * @param flags A bitfied of potential uses for the surface. These
+ * potentially impact the requried alignment of the surface offset.
+ * See @ref surface_info_flags
+ *
+ * @returns 0 on Success
+ * @returns <0 Error
+ */
+ int (*gmm_alloc_surface)(unsigned long *offset,
+ unsigned long pixel_format,
+ unsigned int *width,
+ unsigned int *height,
+ unsigned int *pitch,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long *flags);
+
+
+ int (*gmm_map_ci)(unsigned long *gtt_offset,
+ unsigned long ci_param, /*virtaddr or v4l2_offset*/
+ unsigned long *virt_addr,
+ unsigned int map_method,
+ unsigned long size);
+
+
+ int (*gmm_unmap_ci)(unsigned long virt_addr);
+
+
+ /*!
+ * This function maps an existing list of pages into the GTT.
+ *
+ * @param pagelist The live list of pages to be mapped. The GMM
+ * should not modify or release this list.
+ * @param gtt_offset The offset into the Gtt memory space at which the
+ * pages begin. This is an output only.
+ *
+ * @param numpages The number of pages to map (i.e., length of pagelist).
+ *
+ * @returns 0 on Success
+ * @returns <0 Error
+ */
+ int (*gmm_import_pages)(void **pagelist,
+ unsigned long *gtt_offset,
+ unsigned long numpages);
+
+ int (*gmm_get_num_surface)(unsigned long *count);
+ int (*gmm_get_surface_list)(unsigned long allocated_size,
+ unsigned long *list_size,
+ igd_surface_list_t **surface_list);
+
+ /*!
+ * This function is used by igd client drivers to allocate regions from
+ * graphics memory. Regions are portions of video memory that do not have
+ * width and height parameters, only a linear size. A driver must use this
+ * function to allocate all regions, and must in turn free the regions with
+ * igd_mm_free() before exit.
+ * Calls to this function are only valid after the gmm_init() function
+ * has been called by the igd init module.
+ *
+ * @param offset The offset into the Gtt memory space that the region
+ * begins. This is an output only. This value can be added to the base
+ * physical or virtual address to obtain a full virtual or physical
+ * address.
+ *
+ * @param size The size of the region, this value may be modified to be
+ * larger or smaller than the requested value.
+ *
+ * @param type The defined type of the surface to be allocated.
+ * See @ref alloc_region_types
+ *
+ * @param flags A bitfied of potential uses for the region. These
+ * potentially impact the requried alignment of the region offset.
+ * See @ref alloc_region_flags
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_region)(unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long flags);
+
+ /*!
+ * This function is used to find the actual physical address of the
+ * system memory page given an offset into Gtt memory. This function
+ * will only be successful if the offset provided was allocated to a
+ * cursor or overlay register type.
+ *
+ * @param offset The offset as provided by the allocation function.
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_virt_to_phys)(unsigned long offset,
+ unsigned long *physical);
+
+ /*!
+ * This function should be used to free any regions or surfaces allocated
+ * during igd use. Calling with offsets that were not obtained via a
+ * prior call to _igd_dispatch::gmm_alloc_surface() or
+ * _igd_dispatch::gmm_alloc_region() are invalid and will produce
+ * undefined results.
+ * Calls to this function are only valid after the igd_module_init()
+ * function has been called.
+ *
+ * @param offset The offset as provided by the allocation function.
+ *
+ * @returns void
+ */
+ void (*gmm_free)(unsigned long offset);
+
+ /*!
+ * This function should be used to release externally-allocated
+ * page lists that have been imported into the GMM. This will
+ * simply unmap the pages from the GTT; the pages themselves
+ * should subsequently be freed by the external source.
+ * Calling with offsets that were not obtained via a
+ * prior call to _igd_dispatch::gmm_import_pages() or
+ * are invalid and will produce undefined results.
+ * Calls to this function are only valid after the igd_module_init()
+ * function has been called.
+ *
+ * @param offset The offset as provided by the allocation function.
+ *
+ * @returns void
+ */
+ void (*gmm_release_import)(unsigned long offset);
+
+ /*!
+ * This function returns current memory statistics.
+ *
+ * @param memstat An _igd_memstat structure to be populated during the call
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_memstat)(igd_memstat_t *memstat);
+
+ /*!
+ * Allocates a surface similar to _igd_dispatch::gmm_alloc_surface();
+ * however, in this case the surface is allocated from a cached pool of
+ * similar surfaces to improve performance. The surface cache shrinks and
+ * grows automatically based on usage model. The surface cache should
+ * be used when many surfaces of similar format and size are allocated
+ * and freed repeatedly and the highest performance is required. The
+ * tradeoff is that memory will be consumed by the cache and which
+ * can lead to the need to flush the cache when non-cached surfaces
+ * fail due to out-of-memory conditions.
+ *
+ * Surface is passed in, and populated during call.
+ * All inputs are the same as with gmm_alloc_surface.
+ *
+ * @param display_handle Display used with this surface
+ * @param surface Input/Output structure containing surface information
+ * @param flags used to modify the behavior of the function.
+ * See @ref gmm_alloc_cached_flags
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_cached)(igd_display_h display_handle,
+ igd_surface_t *surface, unsigned int flags);
+
+ /*!
+ * Free a surface previously allocated with the
+ * _igd_dispatch::gmm_alloc_cached() dispatch function. When freeing
+ * a cached surface it is not necessary for rendering to be complete. In
+ * this manner better performance can be achieved because it is likely
+ * that the rendering will be complete before the surface could be reused.
+ * When freeing a cached surface a sync ID obtained from
+ * _igd_dispatch::sync() after all rendering commands to the surface
+ * should be provided such that the cache manager can be sure rendering
+ * is complete before the surface is reused or freed.
+ *
+ * @param display_handle Display used with this surface
+ * @param surface structure containing surface information
+ * @param sync_id obtained after all rendering to/from this surface
+ */
+ void (*gmm_free_cached)(igd_display_h display_handle,
+ igd_surface_t *surface,
+ unsigned long sync_id);
+
+ /*!
+ * Allocates a region similar to _igd_dispatch::gmm_alloc_region();
+ * however, in this case the region is allocated from a cached pool of
+ * similar regions to improve performance. The region cache shrinks and
+ * grows automatically based on usage model. The region cache should
+ * be used when many regions of similar format and size are allocated
+ * and freed repeatedly and the highest performance is required. The
+ * tradeoff is that memory will be consumed by the cache and which
+ * can lead to the need to flush the cache when non-cached regions
+ * fail due to out-of-memory conditions.
+ *
+ * Region information is passed in, and populated during call.
+ * All inputs are the same as with gmm_alloc_region.
+ *
+ * @param display_handle Display used with this region
+ *
+ * @param offset The offset into the Gtt memory space that the region
+ * begins. This is an output only. This value can be added to the base
+ * physical or virtual address to obtain a full virtual or physical
+ * address.
+ *
+ * @param size The size of the region, this value may be modified to be
+ * larger or smaller than the requested value.
+ *
+ * @param type The defined type of the region to be allocated.
+ * See @ref alloc_region_types
+ *
+ * @param region_flags A bitfied of potential uses for the region. These
+ * potentially impact the requried alignment of the region offset.
+ * See @ref alloc_region_flags
+ *
+ * @param flags used to modify the behavior of the function.
+ * See @ref gmm_alloc_cached_flags
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_cached_region)(igd_display_h display_handle,
+ unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned int region_flags,
+ unsigned int flags);
+
+ /*!
+ * Free a region previously allocated with the
+ * _igd_dispatch::gmm_alloc_cached_region() dispatch function. When freeing
+ * a cached region it is not necessary for rendering to be complete. In
+ * this manner better performance can be achieved because it is likely
+ * that the rendering will be complete before the region could be reused.
+ * When freeing a cached region a sync ID obtained from
+ * _igd_dispatch::sync() after all rendering commands to the region
+ * should be provided such that the cache manager can be sure rendering
+ * is complete before the region is reused or freed.
+ *
+ * @param display_handle Display used with this region
+ *
+ * @param offset The offset into the Gtt memory space that the region
+ * begins. This is an output only. This value can be added to the base
+ * physical or virtual address to obtain a full virtual or physical
+ * address.
+ *
+ * @param size The size of the region, this value may be modified to be
+ * larger or smaller than the requested value.
+ *
+ * @param type The defined type of the region to be allocated.
+ * See @ref alloc_region_types
+ *
+ * @param region_flags A bitfied of potential uses for the region. These
+ * potentially impact the requried alignment of the region offset.
+ * See @ref alloc_region_flags
+ *
+ * @param sync_id_write obtained after all rendering to this region
+ * @param sync_id_read obtained after all rendering from this region
+ */
+ void (*gmm_free_cached_region)(igd_display_h display_handle,
+ unsigned long offset,
+ unsigned long size,
+ unsigned int type,
+ unsigned int region_flags,
+ unsigned long sync_id_write,
+ unsigned long sync_id_read);
+
+ /*!
+ * Flushes surfaces out of the internal surface cache. During normal
+ * operation an IAL will not need to call this. Only when an IAL is
+ * making use of the surface cache for some operations and direct
+ * gmm operations for others would it be necessary to flush the cache.
+ *
+ *
+ * @returns 0 No surfaces flushed
+ * @returns >0 Surfaces flushed
+ * @returns <0 Error
+ */
+ int (*gmm_flush_cache)(void);
+
+ /*!
+ * Allocates a heap of the requested size. The heap allocated is managed
+ * by the GMM through "gmm_alloc_heapblock", "gmm_free_heapblock", and
+ * "gmm_free_heap" functions.
+ *
+ * @param display_handle Used to access other GMM dispatch functions
+ *
+ * @param heap_offset The offset into the Gtt memory space that the heap
+ * begins. This also serves as a "heap ID"
+ *
+ * @param heap_size The size of the heap.
+ *
+ * @param type Set to zero
+ *
+ * @param alignment The alignment of the blocks in this heap
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_heap)(igd_display_h display_handle,
+ unsigned long *heap_offset,
+ unsigned long *heap_size,
+ unsigned int type,
+ unsigned long alignment);
+
+ /*!
+ * Frees the heap allocated by gmm_alloc_heap
+ *
+ * @param heap_offset The offset into the Gtt memory space that the heap
+ * begins
+ */
+ void (*gmm_free_heap)(igd_display_h display_handle,
+ unsigned long heap_offset);
+
+ unsigned long (*gmm_get_pvtheap_size)(void);
+ unsigned long (*gmm_get_cache_mem)(void);
+ /*!
+ * Allocates a block of the requested size from the heap indicated by
+ * heap_offset.
+ *
+ * @param display_handle Used to access other GMM dispatch functions
+ *
+ * @param heap_offset The heap ID
+ *
+ * @param block_offset
+ *
+ * @param size The size of the block.
+ *
+ * @param type Set to zero
+ *
+ * @param flags Set to zero
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_heap_block)(igd_display_h display_handle,
+ unsigned long heap_offset,
+ unsigned long *block_offset,
+ unsigned long *size,
+ unsigned long flags);
+
+ /*!
+ * Frees a block of previously allocated by gmm_alloc_heap_block
+ *
+ * @param display_handle Used to access other GMM dispatch functions
+ *
+ * @param block_offset Offset given by gmm_alloc_heap_block
+ */
+ void (*gmm_free_heap_block)(igd_display_h display_handle,
+ unsigned long heap_offset,
+ unsigned long block_offset,
+ unsigned long sync_id_write,
+ unsigned long sync_id_read);
+
+ /*!
+ * Gets the heap id/offset from which the block
+ *
+ * @param block_offset Offset given by gmm_alloc_heap_block
+ * @param heap_offset Head ID/Offset associated with the block offset
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_get_heap_from_block)(unsigned long block_offset,
+ unsigned long *heap_offset);
+
+ /*!
+ * Allocates a reservation of the requested size. A reservation is a
+ * memory range that is dedicated for the callers use but it not
+ * populated with usable memory. The caller must make a single call to
+ * gmm_alloc_surface() or gmm_alloc_region() passing in the reservation
+ * address to allocate a surface within the reservation. Only a single
+ * surface or region may be placed in a reservation.
+ *
+ * @param offset The offset into the Gtt memory space that the reservation
+ * begins. This is an output only. This value can be added to the base
+ * physical or virtual address to obtain a full virtual or physical
+ * address.
+ *
+ * @param size The size of the reservation.
+ *
+ * @param flags A bitfied of potential uses for the reservation. These
+ * potentially impact the requried alignment of the reservation.
+ * See @ref alloc_reservation_flags
+ */
+ int (*gmm_alloc_reservation)(unsigned long *offset,
+ unsigned long size,
+ unsigned long flags);
+
+ /*!
+ * Allocates a region similar to _igd_dispatch::gmm_alloc_region();
+ * however, in this case the region is allocated from a pool of
+ * persisent regions. The pool can only grow as additional regions
+ * are allocated. The pool can be flushed but this should only be
+ * done when GMM is being shutdown.
+ *
+ * Region information is passed in, and populated during call.
+ * All inputs are the same as with gmm_alloc_region.
+ *
+ * @param display_handle Display used with this region
+ *
+ * @param offset The offset into the Gtt memory space that the region
+ * begins. This is an output only. This value can be added to the base
+ * physical or virtual address to obtain a full virtual or physical
+ * address.
+ *
+ * @param size The size of the region, this value may be modified to be
+ * larger or smaller than the requested value.
+ *
+ * @param type The defined type of the region to be allocated.
+ * See @ref alloc_region_types
+ *
+ * @param region_flags A bitfied of potential uses for the region. These
+ * potentially impact the requried alignment of the region offset.
+ * See @ref alloc_region_flags
+ *
+ * @param flags used to modify the behavior of the function.
+ * See @ref gmm_alloc_cached_flags
+ *
+ * @returns 0 on Success
+ * @returns <0 on Error
+ */
+ int (*gmm_alloc_persistent_region)(igd_display_h display_handle,
+ unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned int region_flags,
+ unsigned int flags);
+
+ /*!
+ * Free a region previously allocated with the
+ * _igd_dispatch::gmm_alloc_persistent_region() dispatch function.
+ * The region is marked as available and may be reused by the next
+ * allocation request. It is the callers responsibilty to make sure
+ * rendering to the region is complete before freeing it.
+ *
+ * @param display_handle Display used with this region
+ *
+ * @param offset The offset into the Gtt memory space that the region
+ * begins. This is an input only.
+ */
+ int (*gmm_free_persistent_region)(unsigned long offset);
+
+ /*!
+ * Flushes regions out of the internal persistent list. During normal
+ * operation an IAL will not need to call this. Only when an IAL is
+ * exiting should it flush the list.
+ *
+ *
+ * @returns 0 regions flushed
+ * @returns <0 Error
+ */
+ int (*gmm_flush_persistent_regions)(igd_display_h display_handle);
+
+ /*!
+ * Creates a linear mapping of a video memory region into the
+ * current process address space.
+ *
+ * @param offset Offset used to identifiy the memory region
+ *
+ * @returns address to mapping
+ * @returns NULL Error
+ */
+ void *(*gmm_map)(unsigned long offset);
+
+ /*!
+ * Unmaps a linear mapping created by gmm_map.
+ *
+ * @param address pointer to the mapping
+ */
+ void (*gmm_unmap)(void *address);
+
+ /*!
+ * Export the list of physical pages allocated to a memory
+ * retion.
+ *
+ * @param offset Offset used to identify the memory region
+ * @param pages Array of page structures holding the physical page
+ * addresses.
+ * @param page_cnt Number of pages in the page array.
+ *
+ * @returns 0 if successful
+ * -IGD_ERROR_NOMEM if offset is invalid.
+ */
+ int (*gmm_get_page_list)(unsigned long offset,
+ unsigned long **pages,
+ unsigned long *page_cnt);
+
+ void (*gmm_dump)(void);
+ void (*gmm_dump_v)(void);
+ char *gmm_debug_desc;
+
+ /* igd_2d.h */
+ int (*setup_clip_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect,
+ igd_appcontext_h appcontext_handle, unsigned int flags);
+ int (*setup_blt)(igd_display_h display_handle, int priority,
+ igd_surface_t *dest_surf, igd_rect_t *dest_rect,
+ unsigned long raster_ops, unsigned long bg_color,
+ unsigned long fg_color, igd_appcontext_h appcontext_handle,
+ unsigned int flags);
+ int (*color_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, unsigned int byte_mask,
+ unsigned int color, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*rgb_color_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, unsigned int byte_mask,
+ unsigned int color, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*pat_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, unsigned int byte_mask,
+ igd_pat_t *pat, igd_chroma_t *chroma, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*mono_pat_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, unsigned int byte_mask,
+ igd_mono_pat_t *pat, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*src_copy_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_surface_t *src,
+ igd_coord_t *src_coord, unsigned int byte_mask, igd_chroma_t *chroma,
+ unsigned int raster_ops, igd_appcontext_h appcontext,
+ unsigned int flags);
+ int (*mono_src_copy_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_mono_src_t *src,
+ unsigned int byte_mask, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*mono_src_copy_immed_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_mono_src_t *src,
+ igd_surface_t *src_surface, igd_rect_t *src_rect,
+ unsigned int byte_mask, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*full_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_surface_t *src,
+ igd_coord_t *src_coord, unsigned int byte_mask, igd_pat_t *pat,
+ unsigned int raster_ops, igd_appcontext_h appcontext,
+ unsigned int flags);
+ int (*full_mono_src_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_mono_src_t *src,
+ unsigned int byte_mask, igd_pat_t *pat, unsigned int raster_ops,
+ igd_appcontext_h appcontext, unsigned int flags);
+ int (*full_mono_pat_blt)(igd_display_h display_h, int priority,
+ igd_surface_t *dest, igd_rect_t *dest_rect, igd_coord_t *src_coord,
+ igd_surface_t *src, unsigned int byte_mask, igd_mono_pat_t *pat,
+ unsigned int raster_ops, igd_appcontext_h appcontext,
+ unsigned int flags);
+ int (*full_mono_pat_mono_src_blt)(igd_display_h display_h,
+ int priority, igd_surface_t *dest, igd_rect_t *dest_rect,
+ igd_mono_src_t *src, unsigned int byte_mask, igd_mono_pat_t *pat,
+ unsigned int raster_ops, igd_appcontext_h appcontext,
+ unsigned int flags);
+ int (*text_immed_blt)(igd_display_h display_h,
+ int priority, igd_surface_t *dest_surf,
+ igd_rect_t *dest_rect,
+ unsigned char *glyph_data, unsigned int num_glyph_bytes,
+ igd_appcontext_h appcontext_handle, unsigned long raster_ops,
+ unsigned long bg_color, unsigned long fg_color,
+ unsigned int flags);
+
+ /* igd_blend.h */
+ /*!
+ * Blend and stretch and color convert a stack of input surfaces into a
+ * destination surface.
+ *
+ * Blend takes N input surfaces and N corresponding input rectangles
+ * and output rectangles. This allows for any subset of an input surface
+ * to be output to any rectangle on the destination surface. The input
+ * and output rectangles need not have any correlation between inputs.
+ * Also, the input and output rectangle for any given surface need not
+ * be the same size or aspect ratio, full up and down scaling is possible.
+ * The destination surface is provided with a clip rectangle. All
+ * rendering will be clipped to this rectangle regardless of the
+ * provided destination rectangles.
+ * Each input surface has a set of render_ops that will be respected
+ * during the blend operation.
+ * The IGD_RENDER_OP_BLEND render operation will allow the surface to
+ * blend with the surfaces below it in the stack. The bottom surface
+ * in the stack will then optionally blend with the existing contents
+ * of the destination surface.
+ *
+ * All input surface must be allocated with the IGD_SURFACE_TEXTURE
+ * flag and all output surfaces must be allocated with the
+ * IGD_SURFACE_RENDER flag.
+ *
+ * When a stretch blit is performed (No blending) the surface should not
+ * have the IGD_RENDER_OP_BLEND bit set in the render_ops to insure
+ * that the fastest possible method is used and that no format
+ * conversion takes place.
+ *
+ * Due to the number of possible permutations of this API it is
+ * necessary to constrain the parameters that can be expected to work.
+ * Specific hardware implementations may support more, however there is
+ * no guarentee of functionality beyond those listed here.
+ *
+ * Blend will accept 1 or 2 input surfaces.
+ * Blend will accept a maximum of 1 input surface with a palette.
+ * Blend will accept a maximum of 1 input surface in planar format.
+ * All Surfaces can output to ARGB format.
+ * Only YUV inputs may output to YUV format.
+ * xRGB formats will output ARGB with Alpha of 1.0 when
+ * IGD_RENDER_OP_BLEND is set on the surface. Otherwise the x will
+ * be retained from the original source.
+ * Surfaces that are not pre-multipled cannot have a global alpha.
+ *
+ */
+ int (*blend)(igd_display_h display, int priority,
+ igd_appcontext_h appcontext,
+ igd_surface_t *src_surface, igd_rect_t *src_rect,
+ igd_surface_t *mask_surface, igd_rect_t *mask_rect,
+ igd_rect_t *dest_rect, igd_surface_t *dest_surface,
+ igd_rect_t *clip_rect, unsigned long flags);
+
+ /* igd_ovl.h */
+ /*!
+ * Alter the overlay associated with the given display_h.
+ * Only 1 video surface can be associated with a given display_h
+ * (i.e. you can not have 2 video surfaces using the same display).
+ * This function should be called once for each unique framebuffer.
+ * Therefore, single, twin, clone, and vertical extended modes
+ * should call this function once, and the HAL will properly display
+ * video using the primary overlay and second overlay if necessary.
+ * Whereas extended should call this function twice (once for each
+ * display_h) if the video spans multiple displays.
+ * In DIH, this function can be called once for each display, since a
+ * video surface can not span displays in DIH.
+ *
+ * The primary display in clone, the primary display in vertical extended,
+ * and the primary display in extended will always use the primary
+ * overlay. The secondary display in clone, the secondary display in
+ * vertical extended, and the secondary display in extended will always
+ * use the secondary overlay. The hardware overlay resources (excluding
+ * any video memory) will be allocated internal to the HAL during the
+ * _igd_dispatch::alter_displays() call. Video memory surfaces required
+ * internal to the HAL, for stretching or pixel format conversions, will
+ * be dynamically allocated and freed as necessary.
+ *
+ * @param display_h Input display used with this overlay
+ * @param appcontext_h Input appcontext which may be used for blend.
+ * This can be the same appcontext which is used for blend and
+ * 2d (DD and XAA/EXA).
+ * @param src_surf Input src surface information
+ * @param src_rect Input src surface rectangle.
+ * This is useful for clone, extended, and vertical extended modes
+ * where the entire src_surf may not be displayed.
+ * @param dest_rect Input dest surface rectangle. This is relative to the
+ * framebuffer not the display (so clone mode works properly).
+ * @param ovl_info Input overlay information to display.
+ * The color key, video quality, and gamma must be valid
+ * and correct when the overlay is on. That means NO passing in NULL
+ * values to use previous settings.
+ * @param flags Input to turn on/off the overlay and set other flags.
+ * See: @ref alter_ovl_flags
+ *
+ * @returns 0 (IGD_SUCCESS) on Success
+ * @returns <0 (-igd_errno) on Error. The overlay will be off, no need
+ * for the IAL to call the HAL to turn the overlay off.
+ * If -IGD_ERROR_INVAL is returned, something is either to big or
+ * to small for the overlay to handle, or it is panned off of the
+ * displayed. This is likely not critical, since it may be stretched
+ * or panned back, so the overlay can support it. The IAL
+ * should not return an error to the application, or else the
+ * application will likely exit.
+ * If -IGD_ERROR_HWERROR is returned, something is outside of what
+ * the overlay can support (pitch to large, dot clock to large,
+ * invalid pixel format, ring or flip not happening). In this case,
+ * the IAL should return an error to the application, since
+ * additional calls will always fail as well.
+ */
+ int (*alter_ovl)(igd_display_h display_h,
+ igd_appcontext_h appcontext_h,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+ int (*alter_ovl2)(igd_display_h display_h,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+/* int (*alter_ovl2_dihclone)(igd_display_h display_h,
+ igd_surface_t *src_surf,
+ igd_rect_t *src_rect,
+ igd_rect_t *dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);*/
+
+
+ /* igd_ovl.h */
+ /*!
+ * Retrieve the kernel mode initialization parameters for overlay.
+ * This function should be called by user-mode drivers as they are
+ * initialized, to retrieve overlay initialization parameters
+ * discovered and held by the kernel driver.
+ *
+ * @returns 0 (IGD_SUCCESS) on Success
+ * @returns <0 (-igd_errno) on Error.
+ */
+ int (*get_ovl_init_params)(igd_driver_h driver_handle,
+ ovl_um_context_t *ovl_um_context);
+
+ /*!
+ * Query the overlay to determine if an event is complete or if a given
+ * capability is present.
+ *
+ * @param display_h Display used with this overlay
+ * @param flags Used to check for which event is complete or which
+ * capability is present.
+ * See @ref query_ovl_flags
+ *
+ * @returns TRUE if event has occured or capability is available
+ * @returns FALSE if event is pending or capability is not available
+ */
+ int (*query_ovl)(igd_display_h display_h,
+ unsigned int flags);
+
+ /* User mode only query_ovl */
+ int (*query_ovl2)(igd_display_h display_h,
+ unsigned int flags);
+ /*!
+ * Query the overlay for the maximum width and height given the input
+ * src video pixel format.
+ *
+ * @param display_h Display used with this overlay
+ * @param pf Input src video pixel format
+ * @param max_width Output maximum overlay width supported (in pixels)
+ * @param max_height Output maximum overlay height supported (in pixels)
+ *
+ * @returns 0 (IGD_SUCCESS) on Success - will return success
+ * even if overlay is currently in use.
+ * @returns <0 (-igd_errno) on Error
+ */
+ int (*query_max_size_ovl)(igd_display_h display_h,
+ unsigned long pf,
+ unsigned int *max_width,
+ unsigned int *max_height);
+
+ /*!
+ * Alter the sprite C plane with the associated osd/subpicture data
+ */
+ int (*alter_ovl_osd)(igd_display_h display_h,
+ igd_appcontext_h appcontext_h,
+ igd_surface_t *sub_surface,
+ igd_rect_t *sub_src_rect,
+ igd_rect_t *sub_dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+ int (*alter_ovl2_osd)(igd_display_h display_h,
+ igd_surface_t *sub_surface,
+ igd_rect_t *sub_src_rect,
+ igd_rect_t *sub_dest_rect,
+ igd_ovl_info_t *ovl_info,
+ unsigned int flags);
+
+ /* igd_render.h */
+ _igd_get_surface_fn_t get_surface;
+ _igd_set_surface_fn_t set_surface;
+ _igd_query_event_fn_t query_event;
+
+ /* These functions are only to be used by priveledged IALs */
+ _igd_alloc_ring_fn_t alloc_ring;
+ _igd_exec_buffer_fn_t execute_buffer;
+ _igd_rb_reserve_fn_t rb_reserve;
+ _igd_rb_update_fn_t rb_update;
+ _igd_get_sync_slot_fn_t get_sync_slot;
+ _igd_query_buffer_fn_t query_buffer;
+
+ /*!
+ * dispatch->get_display() returns the current framebuffer and
+ * display information.
+ *
+ * @param display_handle required. The display_handle contains the
+ * display information to return. This parameter was returned from a
+ * previous call to dispatch->alter_displays().
+ *
+ * @param port_number required. The port number will determine which
+ * port's display info data to return.
+ *
+ * @param fb_info required and allocated by the caller. The fb_info
+ * struct is returned to the caller describing the current
+ * frame buffer.
+ *
+ * @param pt_info required and allocated by the caller. The
+ * pt_info struct is returned to caller describing the
+ * requested display parameters.
+ *
+ * @param flags - Currently not used
+ *
+ * @returns 0 The mode was successfully returned for all displays.
+ * @returns -IGD_INVAL: Was not able to return the display information.
+ */
+ int (*get_display)(igd_display_h display_handle,
+ unsigned short port_number, igd_framebuffer_info_t *fb_info,
+ igd_display_info_t *pt_info, unsigned long flags);
+
+#ifdef D3D_DPM_ALLOC
+ /* FIXEME: Somehow this D3D_DPM_ALLOC is always invisible to display dll.
+ * To avoid the whole structure corruption, the following delcaration
+ * appended at the very end.
+ */
+ unsigned long* (*gmm_map_sgx)(unsigned long size, unsigned long offset,
+ unsigned long flag);
+#endif
+ int (*get_golden_htotal)(igd_display_info_t *drm_mode_in, igd_display_info_t *drm_mode_out );
+
+ /*!
+ * Registers a VBlank interrupt callback function (and its parameter) to
+ * call when a VBlank interrupt occurs for a given port.
+ *
+ * @param callback (IN). A callback (function pointer) to a non-HAL
+ * function that processes a VBlank interrupt.
+ *
+ * @param priv (IN). An opaque pointer to a non-HAL data structure.
+ * This pointer is passed as a parameter of the callback function.
+ *
+ * @param port_number (IN). The EMGD port number to register a VBlank
+ * interrupt callback for.
+ *
+ * @return A handle that uniquely identifies this callback/port
+ * combination, or NULL if a failure.
+ */
+ emgd_vblank_callback_h (*register_vblank_callback)(
+ emgd_process_vblank_interrupt_t callback,
+ void *priv,
+ unsigned long port_number);
+
+ /*!
+ * Unregisters a previously-registered VBlank interrupt callback function
+ * for a given port.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies the VBlank
+ * interrupt callback to unregister.
+ */
+ void (*unregister_vblank_callback)(
+ emgd_vblank_callback_h callback_h);
+
+ /*!
+ * Enable delivering VBlank interrupts to the callback function for the
+ * registered callback/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to enable.
+ *
+ * @return Zero if successful, non-zero if a failure.
+ */
+ int (*enable_vblank_callback)(emgd_vblank_callback_h callback_h);
+
+ /*!
+ * Disable delivering VBlank interrupts to the callback function for the
+ * registered function/port combination.
+ *
+ * @param callback_h (IN). The handle that uniquely identifies which
+ * VBlank interrupt callback/port combination to disable.
+ */
+ void (*disable_vblank_callback)(
+ emgd_vblank_callback_h callback_h);
+
+ /*!
+ * Shutdown MSVDX before the X exits.
+ */
+ void (*video_shutdown)(void);
+
+
+ /*!
+ * Query the hardware on for given 2D Caps.
+ */
+ void (*query_2d_caps_hwhint)(unsigned long caps_val,
+ unsigned long *status);
+
+ int (*dihclone_set_surface)(
+ unsigned long display_number,
+ unsigned long mode);
+
+ /*!
+ * Allows a user mode application to change pixel format of a display
+ * plane from XRGB to ARGB and vice versa.
+ *
+ * @param enable (IN). Whether to turn on transparency or not with the
+ * assumption that XRGB turns off transparency and ARGB turns it on.
+ * 0 = disable
+ * 1 = enable
+ * @param display_plane (IN). Which display plane to change pixel_format of
+ * 0 = Plane A
+ * 1 = Plane B
+ */
+ int (*control_plane_format)(int enable, igd_display_h display_handle);
+
+ /*!
+ * Overlay Plane assignment override.
+ */
+ int (*set_ovl_display)(igd_display_h ovl_displays[]);
+
+/*!
+ * Get MSVDX status.
+ */
+ int (*msvdx_status)(igd_driver_h driver_handle, unsigned long *queue_status, unsigned long *mtx_msg_status);
+ /* show_desktop calls this function so, the planes now show the desktop instead of the splas screen */
+ int (*unlock_planes)(igd_display_h display_handle , unsigned int scrn_num);
+} igd_dispatch_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_2d.h b/drivers/gpu/drm/emgd/include/igd_2d.h
new file mode 100644
index 0000000..f7ee253
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_2d.h
@@ -0,0 +1,380 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_2d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is a header file for the Intel GFX commands.
+ * This includes commands specific to Intel hardware and structures specific
+ * to Intel hardware. All other commands and structures are available
+ * through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_2D_H
+#define _IGD_2D_H
+
+/* Needed for igd_display_h and pixel_format. */
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_appcontext.h>
+
+/* byte mask */
+#define IGD_ALPHA_CHANNEL 0x200000
+#define IGD_RGB_CHANNEL 0x100000
+
+/* flags for XY_SETUP_CLIP_BLT */
+#define IGD_CLIP_ENABLED 0x01
+#define IGD_CLIP_DISABLED 0x00
+
+/* flags for igd_mono_src_t->pat_select_transp_mode for functions
+ * igd_mono_src_copy_blt
+ * igd_full_mono_src_blt
+ * igd_full_mono_pat_blt
+ * igd_full_mono_pat_mono_src_blt
+ */
+#define IGD_SRC_TRANSP_MODE_BACKGROUND (0x0 << 29)
+#define IGD_SRC_TRANSP_MODE_ENABLED (0x1 << 29)
+
+/* flags for igd_mono_pat_t->pat_select_transp_mode for functions
+ * igd_full_mono_pat_blt
+ * igd_full_mono_pat_mono_src_blt
+*/
+#define IGD_PAT_SOLID (0x1 << 31)
+#define IGD_PAT_NO_SOLID (0x0 << 31)
+
+/* flags for igd_mono_pat_t->pat_select_transp_mode for functions
+ * igd_mono_pat_blt
+ * igd_full_mono_pat_blt
+ * igd_full_mono_pat_mono_src_blt
+ * FIXME: Does this work for igd_full_mono_pat_blt???
+ */
+#define IGD_PAT_TRANSP_MODE_BACKGROUND (0x0 << 28)
+#define IGD_PAT_TRANSP_MODE_ENABLED (0x1 << 28)
+
+
+/* chroma transparency range mode */
+#define IGD_NO_TRANSP 0
+#define IGD_SRC_RGB_TRANSP 1
+#define IGD_SRC_RGB_ALPHA_TRANSP 2
+#define IGD_DEST_RGB_TRANSP 3
+#define IGD_DEST_RGB_ALPHA_TRANSP 4
+
+
+typedef struct igd_chroma {
+ unsigned int transp_range_mode;
+ unsigned int color_low;
+ unsigned int color_high;
+} igd_chroma_t;
+
+typedef struct igd_mono_src {
+ unsigned int data_bit_pos;
+ unsigned int mono_src_transp_mode;
+ /*
+ * FIXME: Maybe. Immediate mode instructions need a virtual
+ * address. The rest need an offset. Hence there are two
+ * address values in this structure. The type of instructure
+ * determines which one is used. This is a bit confusing for
+ * the IAL layer. Ideally, these would be combined into one value.
+ */
+ unsigned long addr;
+ unsigned char *virt_addr; /* Used by Immediate mode instructions */
+ unsigned int bgcolor;
+ unsigned int fgcolor;
+ int mono_src_size;
+} igd_mono_src_t;
+
+/* fixed pattern not supported yet */
+typedef struct igd_mono_pat {
+ unsigned int pat_select_transp_mode;
+ unsigned int horiz_seed;
+ unsigned int vert_seed;
+ unsigned int bgcolor;
+ unsigned int fgcolor;
+ unsigned int data0;
+ unsigned int data1;
+} igd_mono_pat_t;
+
+typedef struct igd_pat {
+ unsigned int horiz_seed;
+ unsigned int vert_seed;
+ unsigned long base_addr;
+ unsigned char *virt_addr;
+} igd_pat_t;
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->setup_clip_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_rect_t *dest_rect,
+ * igd_appcontext_h appcontext_handle,
+ * unsigned int flags);
+ *
+ * Description:
+ * XY_SETUP_CLIP_BLT: used to change the clip coordinate registers
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->color_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * unsigned int byte_mask,
+ * unsigned int color,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * color_blt: copy solid_color to dest at specific address
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->rgb_color_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * unsigned int byte_mask,
+ * unsigned int color,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->pat_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * unsigned int byte_mask,
+ * igd_pat_t *pat,
+ * igd_chroma_t *chroma,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * pat_blt() copy a color pattern to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->mono_pat_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * unsigned int byte_mask,
+ * igd_mono_pat_t *pat,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * mono_pat_blt(): copy a monochrome pattern to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->src_copy_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_surface_t *src,
+ * igd_coord_t *src_coord,
+ * unsigned int byte_mask,
+ * igd_chroma_t *chroma,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * src_copy_blt: copy a source surface to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->mono_src_copy_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_mono_src_t *src,
+ * unsigned int byte_mask,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * mono_src_copy_blt: color source copy with chroma-keying
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->full_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_surface_t *src,
+ * igd_coord_t *src_coord,
+ * unsigned int byte_mask,
+ * igd_pat_t *pat,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * full_blt: copy with specification of destination, source
+ * and pattern
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->full_mono_src_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_mono_src_t *src,
+ * unsigned int byte_mask,
+ * igd_pat_t *pat,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * full_mono_src_blt: copy with specification of destination, source
+ * and pattern where source is monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->full_mono_pat_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_coord_t *src_coord,
+ * igd_surface_t *src,
+ * unsigned int byte_mask,
+ * igd_mono_pat_t *pat,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * full_mono_pat_blt copy with specification of destination, source
+ * and pattern where pattern is monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->full_mono_pat_mono_src_blt(igd_display_h display_handle,
+ * int priority,
+ * igd_surface_t *dest,
+ * igd_rect_t *dest_rect,
+ * igd_mono_src_t *src,
+ * unsigned int byte_mask,
+ * igd_mono_pat_t *pat,
+ * unsigned int raster_ops,
+ * igd_appcontext_h appcontext,
+ * unsigned int flags);
+ *
+ * Description:
+ * full_mono_pat_mono_src_blt copy with specification of destination, source
+ * and pattern where patter and source are monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+#endif /* _IGD_2D_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_appcontext.h b/drivers/gpu/drm/emgd/include/igd_appcontext.h
new file mode 100644
index 0000000..d987937
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_appcontext.h
@@ -0,0 +1,72 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_appcontext.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is an IGD exported header file for the client context Module.
+ * This module includes tools for maintaining device state including
+ * hardware context allocation.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_APPCONTEXT_H
+#define _IGD_APPCONTEXT_H
+
+typedef void *igd_appcontext_h;
+
+#define IGD_CONTEXT_STATE_2D 0x00000001
+#define IGD_CONTEXT_STATE_3D 0x00000002
+#define IGD_CONTEXT_STATE_VD 0x00000004
+
+/*----------------------------------------------------------------------
+ * Function:
+ * igd_appcontext_h dispatch->appcontext_alloc(igd_display_h display_handle,
+ * int priority,
+ * unsigned int flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ * void dispatch->appcontext_free(igd_display_h display_handle,
+ * int priority,
+ * igd_appcontext_h context_handle);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_blend.h b/drivers/gpu/drm/emgd/include/igd_blend.h
new file mode 100644
index 0000000..2ea3eb6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_blend.h
@@ -0,0 +1,73 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_blend.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is a header file for the Intel GFX commands.
+ * This includes commands specific to Intel hardware and structures specific
+ * to Intel hardware. All other commands and structures are available
+ * through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_BLEND_H
+#define _IGD_BLEND_H
+
+#include <igd_render.h>
+
+/* These flags must not conflict with the IGD_RENDER flags in igd_render.h */
+#define IGD_FILTER_MASK 0x00000300
+#define IGD_FILTER_NEAREST 0x00000000
+#define IGD_FILTER_BILINEAR 0x00000100
+#define IGD_FILTER_ANISOTROPIC 0x00000200
+#define IGD_FILTER_4X4 0x00000300
+/* Indicates multiple blends will be sent in a row and this is not the
+ * last blend. */
+#define IGD_BLEND_NO_FLUSH 0x00000800
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->blend(igd_display_h display_handle,
+ * int priority,
+ * igd_appcontext_h appcontext,
+ * unsigned int num_src,
+ * igd_surface_t **src_surface_list,
+ * igd_rect_t **src_rect_list,
+ * igd_rect_t **dest_rect_list,
+ * igd_surface_t *dest_surface,
+ * igd_rect_t *clip_rect,
+ * unsigned long flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * flags: Flags are defined in igd_render.h
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+#endif /* _IGD_BLEND_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_debug.h b/drivers/gpu/drm/emgd/include/igd_debug.h
new file mode 100644
index 0000000..455b182
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_debug.h
@@ -0,0 +1,72 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_debug.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains data structures and variables needed to control
+ * debugging within the IEGD driver.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_DEBUG_H
+#define _IGD_DEBUG_H
+
+typedef struct _igd_debug {
+ struct {
+ /* Per-Module Debug Bits */
+ short cmd ;
+ short dsp ;
+ short mode ;
+ short init ;
+ short overlay ;
+ short power ;
+ short _2d ;
+ short blend ;
+ short state ;
+ short gmm ;
+ short gart ;
+ short oal ;
+ short intr ;
+ short dpd ;
+ short video ;
+ short pvr3dd ;
+ short buf_class;
+ /* Global Debug Bits */
+ short trace ;
+ short instr ;
+ short debug ;
+ /* Verbose debug bits */
+ short blend_stats ;
+ short dump_overlay_regs ;
+ short dump_command_queue ;
+ short dump_gmm_on_fail ;
+ short dump_shaders ;
+ } hal;
+} igd_debug_t;
+
+extern igd_debug_t *emgd_debug;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_errno.h b/drivers/gpu/drm/emgd/include/igd_errno.h
new file mode 100644
index 0000000..ee0c69c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_errno.h
@@ -0,0 +1,60 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_errno.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains igd error definitions.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_ERRNO_H
+#define _IGD_ERRNO_H
+
+/* Error values, must be <64kb for vBIOS */
+#define IGD_ERROR_NOMEM 0x0001
+#define IGD_ERROR_INVAL 0x0002
+#define IGD_ERROR_BUSY 0x0003
+#define IGD_ERROR_PWRDOWN 0x0004
+#define IGD_ERROR_NODEV 0x0005
+#define IGD_ERROR_HWERROR 0x0006
+#define IGD_ERROR_EDID 0x0007
+#define IGD_ERROR_INVAL_CONTEXT 0x0008
+#define IGD_ERROR_INVAL_PARAM 0x0009
+#define IGD_ERROR_IOCTL 0x000A
+#define IGD_ERROR_GENERIC 0x000B
+#define IGD_ERROR_BLT_NOTCOMPLETE 0x000B
+#define IGD_ERROR_NOT_IMPLEMENTED 0x000C
+#define IGD_ERROR_MAPPING_FAILED 0x000D
+
+#define IGD_NO_MEM IGD_ERROR_NOMEM
+#define IGD_INVAL IGD_ERROR_INVAL
+
+/* Success value */
+#define IGD_SUCCESS 0
+#define IGD_SUCCESS_DO_QRY_SETMODE 0x1001
+
+#define IGD_DO_QRY_SETMODE IGD_SUCCESS_DO_QRY_SETMODE
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_gart.h b/drivers/gpu/drm/emgd/include/igd_gart.h
new file mode 100644
index 0000000..568e271
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_gart.h
@@ -0,0 +1,77 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_gart.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_GART_H_
+#define _IGD_GATR_H_
+
+typedef struct _gtt_info {
+ void* virt_mmadr;
+ void* virt_gttadr;
+ void* virt_gttadr_upper;
+
+ unsigned long new_gtt;
+ unsigned long gtt_phyadr;
+ unsigned long is_virt_aperture;
+ unsigned long reset_gtt_entries;
+ unsigned long fb_phys_addr;
+ unsigned long scratch_phys;
+
+ unsigned long num_gtt_entries;
+ unsigned long gtt_entry_start;
+ unsigned long gtt_entry_end;
+ unsigned long num_contig_allocs;
+ unsigned char **cont_pages_virts;
+ /* FIXME!!! - this cant handle 64-bit Architecture*/
+ unsigned long *cont_pages_phys;
+ unsigned long *cont_pages_sizes;
+#ifdef D3D_DPM_ALLOC
+ void* virt_gttadr_dpm;
+#endif
+}gtt_info_t;
+
+/*
+ * Note: Platforms extend this data structure so the pointer can be used
+ * as either this DI dispatch or cast to the DD dipatch.
+ */
+typedef struct _init_gart_dispatch {
+ int (*get_gtt_ctl)(void* gtt_info);
+ int (*init_gtt_table)(void* gtt_info);
+ int (*flush_gtt_tlb)(void* gtt_info);
+ int (*shutdown_gtt)(void* gtt_info);
+} init_gart_dispatch_t;
+
+void* igd_get_gtt_dispatch(unsigned long dev_id);
+int igd_get_gtt_ctl(void* gtt_info, unsigned long dev_id);
+int igd_init_gtt(void* gtt_info, unsigned long dev_id);
+int igd_flush_gtt(void* gtt_info, unsigned long dev_id);
+int igd_shutdown_gtt(void* gtt_info, unsigned long dev_id);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_gmm.h b/drivers/gpu/drm/emgd/include/igd_gmm.h
new file mode 100755
index 0000000..7bd1a89
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_gmm.h
@@ -0,0 +1,390 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_gmm.h
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the public header file for gmm. It should be included by any
+ * client driver or igd module that requires gmm interaction.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_MM_H
+#define _IGD_MM_H
+
+#include <igd_mode.h>
+#include <igd_render.h>
+
+/*!
+ * @addtogroup gmm_group
+ *
+ * <B>Relavent Dispatch Functions</B>
+ * - _igd_dispatch::gmm_alloc_surface()
+ * - _igd_dispatch::gmm_alloc_region()
+ * - _igd_dispatch::gmm_free()
+ * - _igd_dispatch::gmm_memstat()
+ * - _igd_dispatch::gmm_alloc_cached()
+ * - _igd_dispatch::gmm_free_cached()
+ * - _igd_dispatch::gmm_flush_cache()
+ *
+ * @{
+ */
+
+/*!
+ * @name Surface Alignment Flags
+ * @anchor surface_info_flags
+ *
+ * Surface Alignment Flags are passed to the _igd_dispatch::gmm_alloc_surface()
+ * function as an indicator for how the surface will be used.
+ *
+ * - IGD_SURFACE_RENDER The surface may be used as a rendering target,
+ * this must be set for all color buffers.
+ * - IGD_SURFACE_TEXTURE The surface may be used as a texture input.
+ * - IGD_SURFACE_CURSOR Surface may be used as a cursor
+ * - IGD_SURFACE_OVERLAY Surface may be used with the overlay
+ * - IGD_SURFACE_DISPLAY This surface is suitable for use with the display
+ * engine. This flag must be set for any render target that may later
+ * be flipped to the front buffer.
+ * - IGD_SURFACE_DEPTH The surface may be used as a depth (Z) buffer.
+ * - IGD_SURFACE_DRI2 The surface is a DRI2 allocation (back buffer,
+ * fake front buffer, etc.). It should be allocated on the general
+ * heap rather than the default '2D' heap.
+ *
+ * - IGD_SURFACE_YMAJOR If the surface is tiled, it is tiled with the
+ * walk in the YMajor direction. This flag is output only unless the
+ * allocation type is Fixed TF.
+ * - IGD_SURFACE_XMAJOR If the surface is tiled, it is tiled with the
+ * walk in the YMajor direction. This flag is output only unless the
+ * allocation type is Fixed TF.
+ * - IGD_SURFACE_TILED Surface is tiled. This flag is output only unless
+ * the allocation type is Fixed TF.
+ * - IGD_SURFACE_FENCED Surface is fenced. This flaf is output only unless
+ * the allocation type is Fixed TF.
+ *
+ * Additionally all FB flags can be populated
+ * See: @ref fb_info_flags
+ *
+ * @{
+ */
+#define IGD_SURFACE_RENDER 0x00000001
+#define IGD_SURFACE_TEXTURE 0x00000002
+#define IGD_SURFACE_CURSOR 0x00000004
+#define IGD_SURFACE_OVERLAY 0x00000008
+#define IGD_SURFACE_DISPLAY 0x00000010
+#define IGD_SURFACE_DEPTH 0x00000020
+#define IGD_SURFACE_VIDEO 0x00000040
+#define IGD_SURFACE_VIDEO_ENCODE 0x00000080
+#define IGD_SURFACE_DRI2 0x00000100
+
+#define IGD_SURFACE_WALK_MASK 0x00001000
+#define IGD_SURFACE_YMAJOR 0x00001000
+#define IGD_SURFACE_XMAJOR 0x00000000
+#define IGD_SURFACE_TILED 0x00002000
+#define IGD_SURFACE_FENCED 0x00004000
+#define IGD_SURFACE_SYS_MEM 0x00008000
+#define IGD_SURFACE_PHYS_PTR 0x00010000
+#define IGD_SURFACE_CI 0x00020000
+#define IGD_SURFACE_CI_V4L2_MAP 0x00040000 /*will be set when map_method=0 without WA*/
+#define IGD_SURFACE_CI_TEXTSTREAM 0x00080000
+/*
+ * Mipmap flags are only valid on mipmap surfaces.
+ * Planes flags are only valid on volume surfaces.
+ */
+#define IGD_MIPLEVEL_SHIFT 16
+#define IGD_MIPLEVEL_MASK (0xf<<IGD_MIPLEVEL_SHIFT)
+#define IGD_NUMPLANES_SHIFT 20
+#define IGD_NUMPLANES_MASK (0x0ff00000UL)
+
+/*
+ * These flags exist in the Framebuffer info data structure also.
+ * They are here to insure that no overlap of flags happens.
+ */
+#define IGD_SURFACE_RESERVED_FLAGS 0xf0000000
+
+/*! @} */
+
+/*!
+ * @name Surface Allocation Types
+ * @anchor alloc_surface_types
+ *
+ * These types are used with the _igd_dispatch::alloc_surface() call to
+ * control the allocation behavior.
+ *
+ * - IGD_GMM_ALLOC_TYPE_NORMAL Normal surface allocation. GMM will
+ * determine the best tiling and fencing options and return that
+ * information in the surface flags.
+ * - IGD_GMM_ALLOC_TYPE_FIXED_TF Surface allocation will be done using
+ * the tiled and fenced options from the surface flags. GMM will
+ * not override these flags but will fail an allocation if the
+ * tiling options would result in an unusable surface.
+ * - IGD_GMM_ALLOC_TYPE_RESERVATION The offset provided in the call
+ * was reserved earlier. The provided offset must be used. This
+ * may be used with the Fixed bit enabled.
+ * @{
+ */
+#define IGD_GMM_ALLOC_TYPE_NORMAL 0x0000
+#define IGD_GMM_ALLOC_TYPE_FIXED_TF 0x0001
+#define IGD_GMM_ALLOC_TYPE_RESERVATION 0x0002
+
+/*! @} */
+
+/*!
+ * @name Mipmap layout type
+ * @anchor alloc_mipmap
+ *
+ * These constants are used when allocating surfaces to know how many
+ * offsets to expect GMM to return.
+ *
+ * - IGD_GMM_SURFACE_LAYOUT_RIGHT LOD1 be on the right of LOD0
+ * - IGD_GMM_SURFACE_LAYOUT_BELOW LOD1 is below LOD0
+ * - IGD_GMM_SURFACE_LAYOUT_LEGACY Traditional format, used by
+ * 915 and below
+ * @{
+ */
+
+#define IGD_GMM_SURFACE_LAYOUT_RIGHT 0x0001
+#define IGD_GMM_SURFACE_LAYOUT_BELOW 0x0002
+#define IGD_GMM_SURFACE_LAYOUT_LEGACY 0x0003
+/*! @} */
+
+/*!
+ * @name Surface Allocation Constants
+ * @anchor alloc_surface_constants
+ *
+ * These constants are used when allocating surfaces to know how many
+ * offsets to expect GMM to return.
+ *
+ * - IGD_MAX_MIPLEVELS The maximum number of miplevels returned by GMM.
+ * - IGD_MAX_VOLUME_PLANES The maximum number of planes in a volume map.
+ * - IGD_MAX_VOLUME_SLICES The maximum number of slices in a mipped volume map.
+ * There are 50% fewer planes with each successive mip level.
+ * The number of slices can be calculated as,
+ * (planes*2 - 1) - ((planes>>lod) - 1)
+ * @{
+ */
+#define IGD_MAX_MIPLEVELS 12
+#define IGD_MAX_VOLUME_PLANES 256
+#define IGD_MAX_VOLUME_SLICES 511
+/*! @} */
+
+/*!
+ * @name Region Alignment Flags
+ * @anchor alloc_region_flags
+ *
+ * @{
+ */
+#define IGD_GMM_REGION_ALIGN_MMAP 0x00000001
+#define IGD_GMM_REGION_ALIGN_SIZE 0x00000002 /* Size Aligned */
+#define IGD_GMM_REGION_ALIGN_CONTEXT 0x00000003
+#ifdef D3D_DPM_ALLOC
+#define IGD_GMM_DOUBLE_MAP 0x00000004 /* mapped to SGX/DPM space */
+#endif
+#define IGD_GMM_REGION_ALIGN_64K 0x00000010
+/*! @} */
+
+/*!
+ * @name Region Allocation Types
+ * @anchor alloc_region_types
+ *
+ * @{
+ */
+#define IGD_GMM_REGION_TYPE_DMA 0x00000001
+#define IGD_GMM_REGION_TYPE_RING 0x00000002
+#define IGD_GMM_REGION_TYPE_OVLREG 0x00000003
+#define IGD_GMM_REGION_TYPE_CONTEXT 0x00000004
+#define IGD_GMM_REGION_TYPE_HWSTATUS 0x00000005
+#define IGD_GMM_REGION_TYPE_BPL 0x00000006
+#define IGD_GMM_REGION_TYPE_PERSISTENT 0x00000007
+#define IGD_GMM_REGION_TYPE_OVLREG64 0x00000008
+#define IGD_GMM_REGION_TYPE_RANDEC0 0x00000009
+#define IGD_GMM_REGION_TYPE_RANDEC1 0x0000000A
+/*! @} */
+
+/*!
+ * @name Reservation Flags
+ * @anchor alloc_reservation_flags
+ *
+ * @{
+ */
+#define IGD_GMM_RESERVATION_FENCED 0x00000001
+/*! @} */
+
+
+/*!
+ * @brief Memory stats returned from _igd_dispatch::gmm_memstat()
+ *
+ * This data structure is used to retrieve the memory usage statistics
+ * from the HAL with a dispatch->gmm_memstat() function call.
+ */
+typedef struct _igd_memstat {
+ /*! @brief The total memory space available (Bytes) */
+ unsigned long total_avail;
+ /*! @brief Total memory used (Bytes) */
+ unsigned long total_used;
+ /*! @brief Maximum offscreen memory allowed (Bytes) */
+ unsigned long offscreen_max;
+ /*! @brief The amount of offscreen memory currently used (Bytes) */
+ unsigned long offscreen_used;
+ unsigned long offscreen_static_used;
+} igd_memstat_t;
+
+
+struct emgd_ci_meminfo_t{
+ unsigned long v4l2_offset;
+ unsigned long virt;
+ unsigned long size;
+ unsigned int used;
+ unsigned long vbufqueue_handle;
+};
+/*!
+ * @name GMM Alloc Cached Flags
+ * @anchor gmm_alloc_cached_flags
+ *
+ * These flags are used with the _igd_dispatch::gmm_alloc_cached() dispatch
+ * function.
+ *
+ * - IGD_GMM_FLUSH_ALL: Flush out all cached surfaces if needed.
+ * - 0: Flush out no surfaces.
+ *
+ * @{
+ */
+#define IGD_GMM_FLUSH_ALL 0x1
+/*! @} */
+
+typedef unsigned long (*_gmm_get_pvtheap_size)(void);
+typedef unsigned long (*_gmm_gmm_get_cache_mem)(void);
+
+typedef int (*_gmm_alloc_surface_fn_t)(
+ unsigned long *offset,
+ unsigned long pixel_format,
+ unsigned int *width,
+ unsigned int *height,
+ unsigned int *pitch,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long *flags);
+
+typedef int (*_gmm_get_num_surface_fn_t)(
+ unsigned long *count);
+
+typedef int (*_gmm_get_surface_list_fn_t)(
+ unsigned long allocated_size,
+ unsigned long *list_size,
+ igd_surface_list_t **surface_list);
+
+typedef int (*_gmm_alloc_region_fn_t)(
+ unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned long flags);
+
+typedef int (*_gmm_virt_to_phys_fn_t)(
+ unsigned long offset,
+ unsigned long *physical);
+
+typedef void (*_gmm_free_fn_t)(unsigned long offset);
+
+typedef int (*_gmm_memstat_fn_t)(igd_memstat_t *memstat);
+
+typedef int (*_gmm_alloc_cached_fn_t)(igd_display_h display_handle,
+ igd_surface_t *surface, unsigned int flags);
+
+typedef void (*_gmm_free_cached_fn_t)(igd_display_h display_handle,
+ igd_surface_t *surface,
+ unsigned long sync_id);
+
+typedef int (*_gmm_alloc_cached_region_fn_t)(igd_display_h display_handle,
+ unsigned long *offset,
+ unsigned long *size,
+ unsigned int type,
+ unsigned int region_flags,
+ unsigned int flags);
+
+typedef void (*_gmm_free_cached_region_fn_t)(igd_display_h display_handle,
+ unsigned long offset,
+ unsigned long size,
+ unsigned int type,
+ unsigned int region_flags,
+ unsigned long sync_id_write,
+ unsigned long sync_id_read);
+
+typedef int (*_gmm_flush_cache_fn_t)(void);
+
+
+/*
+ * This interface is used in debug driver only. An IAL or HAL component
+ * may point this at a string (char[80]) prior to a surface/region
+ * allocation. A copy of this string will be stored with the allocation
+ * information and will be seen in a GMM dump.
+ */
+#define GMM_DEBUG_DESC_SIZE 80
+extern char gmm_debug_desc[];
+
+#if defined(DEBUG_BUILD_TYPE) && defined(CONFIG_GMM)
+
+/*
+ * This function is only used to copy the debug description name into
+ * the debug string. This way we don't have to worry about a strcpy
+ * being available.
+ * Note: This function is not a real strcpy. It is hardcoded for the
+ * needs of the gmm debug string copy.
+ */
+static __inline void _gmm_strcpy(const char *src)
+{
+ int i;
+
+ for(i=0; i<GMM_DEBUG_DESC_SIZE; i++) {
+ gmm_debug_desc[i] = src[i];
+ if(!gmm_debug_desc[i]) {
+ return;
+ }
+ }
+ gmm_debug_desc[GMM_DEBUG_DESC_SIZE-1] = '\0';
+ return;
+}
+
+static __inline void _gmm_strcpy2(char *dest, const char *src)
+{
+ int i;
+
+ for(i=0; i<GMM_DEBUG_DESC_SIZE; i++) {
+ dest[i] = src[i];
+ if(!dest[i]) {
+ return;
+ }
+ }
+ dest[GMM_DEBUG_DESC_SIZE-1] = '\0';
+ return;
+}
+
+#define GMM_SET_DEBUG_NAME(src) _gmm_strcpy(src)
+#define GMM_SET_DEBUG_NAME2(dest, src) _gmm_strcpy2(dest, src)
+#else
+#define GMM_SET_DEBUG_NAME(src)
+#define GMM_SET_DEBUG_NAME2(dest, src)
+#endif
+
+/*! @} */
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_init.h b/drivers/gpu/drm/emgd/include/igd_init.h
new file mode 100644
index 0000000..47045b6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_init.h
@@ -0,0 +1,895 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_init.h
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INIT_H_
+#define _IGD_INIT_H_
+
+#include <igd.h>
+
+
+/*!
+ * @addtogroup init_group
+ *
+ * The init module contains the entry points and data structures
+ * necessary to initialize the graphics driver HAL.
+ * The IAL will call several initialization functions to bring the HAL
+ * to a usable state, after which, the HAL is accessed through a dispatch
+ * table (data structure of function pointers).
+ *
+ * Typical initialization will follow these steps:
+ * - Initialize the HAL by calling igd_driver_init() to
+ * detect supported chipsets without altering the hardware. If a
+ * supported device is found the _igd_init_info data structure will be
+ * populated indicating the chipset name and PCI information for the device.
+ * A driver handle that should be used during the rest of the
+ * initialization process will be returned.
+ *
+ * - Call igd_driver_config() to prepare the hardware for use. Until this
+ * point there has been no alteration of the hardware. After the
+ * driver has been configured the igd_get_config_info() function can
+ * be used. Only a subset of the _igd_config_info data will be available
+ * at this time as the modular HAL components have not been initialized.
+ *
+ * - Call igd_module_init() to initialize the modular components of the
+ * driver. This function accepts a set of parameters that can alter
+ * default behavior. A provided dispatch table will be populated with
+ * the entry points used for hardware operations during the life of
+ * the driver. igd_get_config_info() may now be used to return full
+ * configuration details.
+ *
+ * @{
+ */
+
+/*!
+ * @brief Data populated by igd_driver_init().
+ *
+ * The init info is used as input/output to igd_driver_init(). Any non-zero
+ * members (with the exception of the name) will be used to limit the search
+ * for available devices, if all members are zero the first supported
+ * device found on the system will be used. In either case the data returned
+ * will reflect the to-be-controlled device found by the HAL.
+ *
+ * The name is a ASCII string that may be used in human readable output
+ * dialogs.
+ */
+typedef struct _igd_init_info {
+ /*! @brief PCI Vendor ID */
+ unsigned int vendor_id;
+ /*! @brief PCI Device ID */
+ unsigned int device_id;
+ /*! @brief PCI Bus ID */
+ unsigned int bus;
+ /*! @brief PCI Slot ID */
+ unsigned int slot;
+ /*! @brief PCI Function ID */
+ unsigned int func;
+ /*! @brief ASCII chipset name */
+ char *name;
+ /*! @brief ASCII chipset ID */
+ char *chipset;
+ /*! @brief ASCII default port driver list */
+ char *default_pd_list;
+} igd_init_info_t;
+
+/*!
+ * @brief Function to initialize the HAL and detect supported chipset.
+ *
+ * Initialize the driver and determine if the hardware is supported without
+ * altering the hardware state in any way. Init info is populated based on
+ * collected data.
+ *
+ * A driver handle is returned. This handle is an opaque data structure
+ * used with future HAL calls. The contents or meaning of the value are
+ * not known outside the HAL; however, a NULL value should be considered
+ * a failure.
+ *
+ * @param init_info Device details returned from the init process. This
+ * structure will be populated by the HAL during the call.
+ *
+ * @return igd_driver_h (Non-NULL) on Success
+ * @return NULL on failure
+ */
+igd_driver_h igd_driver_init(igd_init_info_t *init_info);
+
+
+/*!
+ * Configure the driver. This sets the driver for future operation, it
+ * may alter the hardware state. Must be called after driver init and
+ * before ANY other driver commands.
+ *
+ * @param driver_handle: A driver handle as returned by igd_driver_init()
+ *
+ * @return <0 on Error
+ * @return 0 On Success
+ */
+int igd_driver_config(igd_driver_h driver_handle);
+
+
+
+/*!
+ * @defgroup init_param Initialization Parameters
+ *
+ * Initialization parameters are passed to igd_module_init() to control
+ * configurable behavior of the HAL. Some parameters are global in that
+ * they have an effect on the entire driver. In addition, there are
+ * parameters that are specific to a display. These parameters are provided
+ * in a list with each list entry representing a defined "port number" as
+ * follows shown here:
+ *
+<PRE>
+ /|-----------|
+ / | Fp Info |
+ / |-----------|
+ |----------| /|---------| /
+ | Params | / | Display | / |-----------|
+ | | / | Param 1 |/ | DTD Array |
+ | |/ |---------|\ |-----------|
+ |----------|\ \
+ \ |---------| \ |-----------|
+ \ | Display | \ | Attribute |
+ \| Param N | \ | Array |
+ |---------| \|-----------|
+</PRE>
+ *
+ * The port numbers are mapped to hardware specific outputs as defined
+ * here:
+ *
+ * 830M and later Port numbers:
+ * - 1 DVO A port
+ * - 2 DVO B port
+ * - 3 DVO C port
+ * - 4 Internal LVDS port
+ * - 5 Analog port
+ *
+ * On 835: If RGBA is used (DVO B & C together), then use DVO B number
+ * to specify any parameter for it.
+ *
+ * 810/815 Port numbers:
+ * - 3 DVO port
+ * - 5 Analog port
+ *
+ * NOTE: The permanence of the Params data structure that is passed from
+ * the IAL to the HAL in igd_module_init API is not guaranteed by the IAL
+ * Therefore, the different HAL modules should use the data out of this
+ * data structure only until igd_module_init and not after that.
+ * @{
+ */
+
+/*!
+ * This parameter, when set, will cause the driver to save the current
+ * register state of the device prior to altering it in any way. This
+ * will allow the state of the device to be reapplied at exit time.
+ */
+#define IGD_DRIVER_SAVE_RESTORE 0x01
+
+/*!
+ * @name Per-Display Present Params Flags
+ * @anchor present_params_flags
+ *
+ * These flags are used to identify which parameters are being provided to
+ * the HAL. If a bit is not set in the _igd_display_params::present_params
+ * variable the parameters will not be read by the HAL and the default
+ * behavior will be used instead.
+ *
+ * - IGD_PARAM_DDC_GPIO Parameter to select non-standard GPIO pair for DDC.
+ * - IGD_PARAM_DDC_SPEED Parameter to select non-standard DDC speed.
+ * - IGD_PARAM_DDC_DAB Parameter to select the Device Address Byte to use for
+ * DDC communication
+ * - IGD_PARAM_I2C_GPIO Parameter to select non-standard GPIO pair for i2c.
+ * - IGD_PARAM_I2C_SPEED Parameter to select non-standard I2C speed.
+ * - IGD_PARAM_DAB Parameter to select the Device Address Byte to use for I2C
+ * communication.
+ * - IGD_PARAM_FP_INFO Parameter to provide non-detectable Flat Panel
+ * configuration data.
+ * - IGD_PARAM_DTD_LIST Parameter to provide a Detailed Timing List for a
+ * display.
+ * - IGD_PARAM_ATTR_LIST Parameter to provide a set of Port Driver Attributes
+ * to use during init.
+ *
+ * @{
+ */
+#define IGD_PARAM_DDC_GPIO 0x00000001
+#define IGD_PARAM_DDC_SPEED 0x00000002
+#define IGD_PARAM_DDC_DAB 0x00000004
+#define IGD_PARAM_I2C_GPIO 0x00000008
+#define IGD_PARAM_I2C_SPEED 0x00000010
+#define IGD_PARAM_DAB 0x00000020
+#define IGD_PARAM_FP_INFO 0x00000040
+#define IGD_PARAM_DTD_LIST 0x00000080
+#define IGD_PARAM_ATTR_LIST 0x00000100
+/*! @} */
+
+
+/*!
+ *
+ *
+ *
+ * @note Any changes to the above number assignment will break the driver.
+ * If change is required, make sure to change the port numbers in
+ * port tables.
+ *
+ */
+
+/* The method for controlling the flat panel power. The options include:
+ * no support or the Port Driver handles flat panel power. */
+#define IGD_PARAM_FP_PWR_METHOD_NONE 0
+#define IGD_PARAM_FP_PWR_METHOD_PD 1
+
+/*!
+ * @brief Port-specific color correction information
+ *
+ * Initialization parameter passed as part of igd_module_init() to provide
+ * information about an attached display device. One color_correct_info
+ * is provided for each display port.
+ *
+ */
+typedef struct _igd_param_color_correct_info {
+ /*! @brief RED value for GAMMA */
+ unsigned short gamma_r;
+ /*! @brief GREEN value for GAMMA */
+ unsigned short gamma_g;
+ /*! @brief BLUE value for GAMMA */
+ unsigned short gamma_b;
+ /*! @brief RED value for BRIGHTNESS */
+ unsigned short brightness_r;
+ /*! @brief GREEN value for BRIGHTNESS */
+ unsigned short brightness_g;
+ /*! @brief BLUE value for BRIGHTNESS */
+ unsigned short brightness_b;
+ /*! @brief RED value for CONTRAST */
+ unsigned short constrast_r;
+ /*! @brief GREEN value for CONTRAST */
+ unsigned short constrast_g;
+ /*! @brief BLUE value for CONTRAST */
+ unsigned short constrast_b;
+} igd_param_color_correct_info_t;
+
+
+
+/*!
+ * @brief Flat Panel Information
+ *
+ * Initialization parameter passed as part of igd_module_init() to provide
+ * information about an attached Flat Panel (typically LVDS). One fp_info
+ * is provided for each display port, and is only used when the
+ * IGD_PARAM_FP_INFO flag is set in the _igd_display_params::present_params
+ *
+ */
+typedef struct _igd_param_fp_info {
+ /*! @brief Flat panel width */
+ unsigned long fp_width;
+ /*! @brief Flat panel height */
+ unsigned long fp_height;
+ /*! @brief Flat Panel Power Method */
+ unsigned long fp_pwr_method;
+ /*!
+ * @brief Min time delay in miliseconds between VDD active and clock/data
+ * active.
+ */
+ unsigned long fp_pwr_t1;
+ /*!
+ * @brief Min time delay in miliseconds between clock/data active and
+ * backlight enable.
+ */
+ unsigned long fp_pwr_t2;
+ /*!
+ * @brief Min time delay in miliseconds between Backlight disable and
+ * clock/data inactive
+ */
+ unsigned long fp_pwr_t3;
+ /*!
+ * @brief Min time delay in miliseconds between clock/data inactive and
+ * VDD inactive.
+ */
+ unsigned long fp_pwr_t4;
+ /*!
+ * @brief Min time delay in miliseconds between VDD inactive and
+ * VDD active.
+ */
+ unsigned long fp_pwr_t5;
+} igd_param_fp_info_t;
+
+/*!
+ * @brief Per-display init-time list of DTDs.
+ *
+ * In the case of EDID-less display device, this parameter provides
+ * the DTD (Detailed Timing Descriptor) list to the HAL during initialization.
+ */
+typedef struct _igd_param_dtd_list {
+ /*! @brief number of DTDs */
+ unsigned long num_dtds;
+ /*! @brief DTD list */
+ igd_display_info_t *dtd;
+} igd_param_dtd_list_t;
+
+/*!
+ * @brief Port driver attribute
+ */
+typedef struct _igd_param_attr {
+ /*! @brief See @ref attr_id_defs for predefined IDs */
+ unsigned long id;
+ /*! @brief value or index(incase of list type attr) */
+ unsigned long value;
+} igd_param_attr_t;
+
+/*!
+ * @brief Port driver init-time attribute list
+ *
+ * This data structure is used during HAL initialization. It should be
+ * populated with any port driver attributes that were modified and saved
+ * in a prior use of the HAL.
+ */
+typedef struct _igd_param_attr_list {
+ /*! @brief number of attributes in the list */
+ unsigned long num_attrs;
+ /*! @brief IAL allocated attribute list */
+ igd_param_attr_t *attr;
+} igd_param_attr_list_t;
+
+
+
+/*!
+ * @brief Per-Display Init-time configuration parameters.
+ *
+ * These parameters are provided as an array during igd_module_init().
+ * They allow the default behavior of the driver to be altered on a
+ * per-display basis. They are input-only to provide data
+ * about non-standard hardware configurations and persistant driver state.
+ */
+typedef struct _igd_display_params {
+ /*! @brief Port to which these parameters apply. See @ref init_param */
+ unsigned long port_number;
+ /*! @brief parameters present bitfield: See @ref present_params_flags */
+ unsigned long present_params;
+ unsigned long flags;
+ /*!
+ * @brief Timing sources to use with Edid displays.
+ * See @ref advanced_edid
+ */
+ unsigned short edid_avail;
+ /*!
+ * @brief Timings sources to use with Edid-less displays.
+ * See @ref advanced_edid
+ */
+ unsigned short edid_not_avail;
+ unsigned long ddc_gpio; /* DDC GPIO pin pair number 0..6 */
+ unsigned long ddc_speed; /* DDC speed in KHz to read EDID */
+ unsigned long ddc_dab; /* DDC DAB to read EDID from display device */
+ unsigned long i2c_gpio; /* I2C GPIO pin pair number 0..6 */
+ unsigned long i2c_speed; /* I2C speed in KHz to read EDID */
+ unsigned long i2c_dab; /* I2C DAB to communicate with DVO device */
+ igd_param_fp_info_t fp_info; /* Connected FP Info */
+ /*!
+ * DTD parameter: Incase of EDID-less display device, this parameter
+ * provides the DTD (Detailed Timing Descriptor) list
+ */
+ igd_param_dtd_list_t dtd_list;
+
+ igd_param_attr_list_t attr_list;
+} igd_display_params_t;
+
+/*!
+ * @name Advanced Edid Flags
+ * @anchor advanced_edid
+ *
+ * Flags to use with edid_avail and edid_not_avail:
+ * perport edid_avail/edid_not_avail
+ *
+ * IGD_DISPLAY_USE_STD_TIMINGS:
+ * If not set: Do not use driver built-in standard timings
+ * If set: Use driver built-in standard timings
+ *
+ * IGD_DISPLAY_USE_EDID: not applicable to edid_not_avail
+ * If not set: Do not use EDID block
+ * If set: Use EDID block and filter modes
+ *
+ * IGD_DISPLAY_USE_USERDTDS:
+ * If not set: Do not use user-DTDs
+ * If set: Use user-DTDs.
+ *
+ * @{
+ */
+#define IGD_DISPLAY_USE_STD_TIMINGS 0x1
+#define IGD_DISPLAY_USE_EDID 0x2
+#define IGD_DISPLAY_USE_USERDTDS 0x4
+/*! @} */
+
+
+/* Flags for igd_display_params_t->flags*/
+#define IGD_DISPLAY_READ_EDID 0x00000001 /* igd_display_params_t.flags */
+
+/*!
+ * @anchor display_flags_def
+ *
+ * These flags may be used in the display_flags member of the
+ * igd_params_t data structure.
+ *
+ */
+#define IGD_DISPLAY_MULTI_DVO 0x00000002 /* igd_param_t.display_flags */
+#define IGD_DISPLAY_DETECT 0x00000004 /* igd_param_t.display_flags */
+#define IGD_DISPLAY_FB_BLEND_OVL 0x00000008 /* igd_param_t.display_flags */
+#define IGD_DISPLAY_BATCH_BLITS 0x00000010
+ /*! @brief enable dynamic blending of display frame buffer with overlay */
+
+
+
+/*!
+ * @brief Init-Time Driver Parameters
+ *
+ * The igd_param_t data structure contains global init-time static parameters
+ * to impact the behavior of the whole driver. They are provided to the driver
+ * during module initialization to control overall driver behavior.
+ *
+ *
+ * VERY IMPORTANT!!! CHANGES TO DEFINITION OF THIS STRUCTURE AND
+ * ITS MEMBER STRUCTURES MUST BE FOLLOWED BY UPDATES TO THE
+ * FOLLOWING COMPONENTS / FILES:
+ * 1. ssigd/ial/vbios/usrbld/igd_uinit.h
+ * 2. ssigd/ial/vbios/src/core/user_config.c
+ * 3. pcf2iegd tool (gens user_config.c/h for usr-bld)
+ * 4. CED tool (generates user_config.c/h for usr-bld)
+ *
+ *
+ *
+ * See igd_module_init()
+ */
+typedef struct _igd_param {
+ /*! @brief Maximum pages taken by the driver for offscreen memory */
+ unsigned long page_request;
+ /*! @brief Maximum pages reserved for the framebuffer. */
+ unsigned long max_fb_size;
+ /*! @brief Boolean option to preserve initial hardware state */
+ unsigned char preserve_regs;
+ /*! @ref display_flags_def "Display Flags" */
+ unsigned long display_flags;
+ /*!
+ * @brief Port detection order.
+ *
+ * HAL will detect the displays in the order mentioned and also allocate
+ * in the same order if found.
+ *
+ * Example: To detect/allocate in the order on 855:
+ * -# DVOB PORT
+ * -# ANALOG PORT
+ * -# LVDS PORT
+ * then specify port_number[] = {2, 5, 4, 0};
+ *
+ * @note Set port_number[] = {0, 0, 0, 0}; to work in the default order.
+ *
+ * @note If a invalid number is specified then it will be skipped.
+ */
+ unsigned long port_order[IGD_MAX_PORTS];
+
+ /*! Contains the Per-Display init-time parameters. */
+ igd_display_params_t display_params[IGD_MAX_PORTS];
+
+ /*! @brief RGB color that will be used while clearing the framebuffer */
+ unsigned long display_color;
+
+ unsigned long quickboot;
+ int qb_seamless;
+ unsigned long qb_video_input;
+ int qb_splash;
+
+ /*! Override interrupt support and revert to polling */
+ int polling;
+ unsigned long ref_freq;
+ int tuning_wa;
+ unsigned long clip_hw_fix;
+
+
+ /* Async flip flickering workaround enable */
+ unsigned long async_flip_wa;
+
+ /*
+ * Enable override of following registers when en_reg_override=1.
+ * Display Arbitration, FIFO Watermark Control, GVD HP_CONTROL,
+ * Bunit Chickenbits, Bunit Write Flush, Display Chickenbits
+ */
+ unsigned long en_reg_override;
+ unsigned long disp_arb;
+ unsigned long fifo_watermark1;
+ unsigned long fifo_watermark2;
+ unsigned long fifo_watermark3;
+ unsigned long fifo_watermark4;
+ unsigned long fifo_watermark5;
+ unsigned long fifo_watermark6;
+ unsigned long gvd_hp_control;
+ unsigned long bunit_chicken_bits;
+ unsigned long bunit_write_flush;
+ unsigned long disp_chicken_bits;
+ int punt_to_3dblit;
+
+} igd_param_t;
+
+typedef struct {
+ unsigned debug : 1;
+ unsigned ddk_version : 16;
+ unsigned emgd_version : 15;
+} igd_build_config_t;
+
+/*! @} */
+
+/*!
+ *
+ * Initializes individual modules to a runable state. Init time parameters
+ * may be provided to alter the default behavior of the driver.
+ * See @ref init_param
+ *
+ * The dispatch table for all graphics operations is returned. The dispatch
+ * table may return NULL pointers for unsupported functions due to
+ * optional modules. This dispatch table is used to access HAL functionality
+ * throughout the life of the driver.
+ * See @ref _igd_dispatch
+ *
+ * @param driver_handle as returned from igd_driver_init().
+ * @param dsp dispatch table to be populated during the call.
+ * @param params Input parameters to alter default behavior.
+ * See @ref init_param
+ *
+ * @return 0 Success
+ * @return <0 on Error
+ */
+int igd_module_init(igd_driver_h driver_handle,
+ igd_dispatch_t **dsp,
+ igd_param_t *params);
+
+
+
+/*!
+ * @name Framebuffer Capabilities
+ * @anchor fb_caps
+ *
+ * FB caps are an indication of large feature sets that will or will not
+ * be available based on FB pixel format. This allows an IAL to intelligently
+ * configure itself to the appropriate setup before setting a display
+ * mode.
+ * FB caps are returned from a call to igd_get_config_info().
+ *
+ * - IGD_CAP_BASIC_2D This capability bit indicates that the device is capable
+ * of performing basic 2d acceleration.
+ * - IGD_CAP_FULL_2D This capability bit indicates that the device is capable
+ * of performing full 2d acceleration.
+ * - IGD_CAP_BLEND This capability bit indicates that the device is capable of
+ * performing the blend() function to the framebuffer.
+ *
+ * @{
+ */
+#define IGD_CAP_BASIC_2D 0x01
+#define IGD_CAP_FULL_2D (0x02 | IGD_CAP_BASIC_2D)
+#define IGD_CAP_BLEND 0x04
+/*! @} */
+
+
+/*!
+ * @brief Device Capabilities based on FB mode
+ *
+ * This structure reports the Framebuffer capabilities on a pixel format
+ * basis. An IAL should check these capabilities before using acceleration
+ * features. This structure is returned as part of the _igd_config_info
+ * information from the igd_get_config_info() call.
+ *
+ * @see pixel_formats
+ */
+typedef struct _igd_fb_caps {
+ /*! @brief The framebuffer pixel format that these caps reference */
+ unsigned long pixel_format;
+ /*! @brief The capability bits as defined by @ref fb_caps */
+ unsigned long caps;
+} igd_fb_caps_t;
+
+/*!
+ * @brief Static HAL configuration data
+ *
+ * Config info contains the static configuration information for the device
+ * that is found during the call to igd_driver_config(). It is obtained
+ * with a call to igd_get_config_info() which may be done before or after
+ * module configuration with limited success.
+ */
+typedef struct _igd_config_info {
+ /*! @brief The Base MMIO physical (Bus) address. */
+ unsigned long mmio_base_phys;
+ /*! @brief The Base MMIO virtual address. */
+ unsigned char *mmio_base_virt;
+ /*! @brief The Base Video Memory physical (Bus) address. */
+ unsigned long gtt_memory_base_phys;
+ /*! @brief The Base Video Memory virtual address. */
+ unsigned char *gtt_memory_base_virt;
+ /*! @brief The Video Memory Size. */
+ unsigned long gtt_memory_size;
+ /*! @brief The number of display planes supported by the device. */
+ unsigned long num_dsp_planes;
+ /*! @brief The number of display pipes supported by the device. */
+ unsigned long num_dsp_pipes;
+ /*! @brief The number of currently active display ports. */
+ unsigned long num_act_dsp_ports;
+ /*! @brief Caps, terminated with PF = 0 */
+ igd_fb_caps_t *fb_caps;
+ /*! @brief The device revision id. */
+ unsigned long revision_id;
+ /*! @brief HW status page offset (priviledged use only) */
+ unsigned long hw_status_offset;
+ /*! @brief The base of stolen memory */
+ unsigned long stolen_memory_base_virt;
+ /* pixel format that matches the bpp that was passed in */
+ unsigned long pixel_format;
+ /* port-specific rotation read from DisplayID */
+ igd_DID_rotation_info_t displayid_rotation[IGD_MAX_PORTS];
+} igd_config_info_t;
+
+
+/*!
+ * @brief Static GTT configuration data
+ *
+ * This holds the configuration of the GTT and the information
+ * required to handle video memory allocation/free.
+ *
+ * FIXME: There is a lot of duplication with information stored
+ * else were (like igd_config_info_t) that needs to be cleaned up.
+ */
+typedef struct _igd_gtt_info_t {
+ unsigned long gatt_start;
+ unsigned long gatt_pages;
+ unsigned long gtt_start;
+ unsigned long gtt_pages;
+ unsigned long gtt_phys_start;
+ unsigned long stolen_mem_base;
+ unsigned long stolen_mem_size;
+ unsigned long stolen_pages;
+ unsigned long pge_ctl;
+ unsigned short gmch_ctl;
+ unsigned long *gtt_mmap;
+ void *vram_virt;
+ unsigned long initialzied;
+ void *scratch_page;
+} igd_gtt_info_t;
+
+
+
+/*!
+ * The igd_get_config_info() function call can be used to get static
+ * configuration information details that the IAL may need. This
+ * function may be called prior to igd_module_init() with limited
+ * success; however, it is recommeneded that it be called after the
+ * modular HAL components have been initialized.
+ *
+ * In addition to static configuration there may be dynamic configuration
+ * details that can be queried at any time after igd_driver_config().
+ * These are defined with unique identifiers and are queried one at a
+ * time with igd_get_param().
+ *
+ * @param driver_handle as retuned from igd_driver_init()
+ * @param config_info Populated with hardware information during the call..
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+int igd_get_config_info(igd_driver_h driver_handle,
+ igd_config_info_t *config_info);
+
+
+
+/*!
+ * @defgroup runtime_param Runtime Parameter Control
+ *
+ * HAL parameters may be queried and set at runtime using the
+ * _igd_dispatch::get_param() and _igd_dispatch::set_param() dispatch functions
+ * (when called after initialization) or the
+ * igd_get_param() and igd_set_param() functions when called during
+ * initialization.
+ * Some implemtations may not support all parameters so IAL's must handle
+ * errors. Additionally, some parameters are hardware specific and of no use to
+ * general purpose IALs. These should only be used by IALs with extensive
+ * hardware knowledge (OpenGL, D3D, etc)
+ *
+ * @{
+ */
+
+/*!
+ * @name Runtime Parameter Defines
+ *
+ * - IGD_PARAM_PANEL_ID Primary Panel ID
+ * This is a unique Flat Panel Identifier that is obtained from firmware.
+ * The IAL may use this information to send in Detailed Timing Descriptors
+ * to igd_module_init(). This facilitates the use of multiple local Flat
+ * panel configurations without EDID. When available this parameter may
+ * be queried prior to igd_module_init().
+ * - IGD_PARAM_MEM_RESERVATION Bios memory reservation.
+ * This is the amount (in bytes?) of memory that the bios has already
+ * installed in the Gart prior to driver load. It is used when a
+ * non-standard bios or firmware has pre-allocated an undetectable amount
+ * of video memory for splash screen use. When available this parameter can
+ * be queried prior to igd_module_init().
+ * - IGD_PARAM_DEBUG_MASK Debug Printing Mask.
+ * This parameter is read/write and may be altered at any time after
+ * igd_driver_init(). It is a bitfield to control different printing
+ * groups for debug builds.
+ * - IGD_PARAM_PORT_LIST A bitfield used by the vBIOS to override the
+ * display detect capabilities in the driver.
+ * - IGD_PARAM_HW_CONFIG Hardware configuration Bitfield
+ * contains one of these dependeing on platform:
+ * IGD_ALM_HW_CONFIG_BIN or IGD_NAP_HW_CONFIG_BIN both of which indicate
+ * the presence and availability of the hardware binner. This value should
+ * be queried and set (removing the bit) by an IAL claiming use of the
+ * binner.
+ * - IGD_PARAM_INTR_STATUS Unknown FIXME document this
+ *
+ * @{
+ */
+#define IGD_PARAM_PANEL_ID 0x01
+#define IGD_PARAM_MEM_RESERVATION 0x02
+#define IGD_PARAM_DEBUG_MASK 0x03
+#define IGD_PARAM_PORT_LIST 0x04
+#define IGD_PARAM_GFX_FREQ 0x05
+#define IGD_PARAM_SET_LVDS 0x06
+#define IGD_PARAM_HW_CONFIG 0x1000
+#define IGD_ALM_HW_CONFIG_BIN 0x1
+#define IGD_NAP_HW_CONFIG_BIN 0x1
+#define IGD_PARAM_INTR_STATUS 0x1001
+
+/*! @} */
+
+/*!
+ * Gets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * Note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @bug Runtime parameter documentation needs updates
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+int igd_get_param(igd_driver_h driver_handle,
+ unsigned long id,
+ unsigned long *value);
+
+/*!
+ * Sets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * Note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+int igd_set_param(igd_driver_h driver_handle,
+ unsigned long id,
+ unsigned long value);
+
+/*! @} Runtime Param Group */
+/*! @} Init Group */
+
+
+/*!
+ * @ingroup cleanup
+ * @brief Shuts down the HAL
+ *
+ * This function shuts down the HAL and frees and remaining resources.
+ * It should be called at driver exit to leave the hardware in a safe
+ * configuration.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_driver_shutdown(igd_driver_h driver_handle);
+
+/*!
+ * @ingroup cleanup
+ * @brief Shuts down the HAL
+ *
+ * This function shuts down the HAL and frees and remaining resources.
+ * It should be called at driver exit to leave the hardware in a safe
+ * configuration.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_driver_shutdown_hal(igd_driver_h driver_handle);
+
+
+/*!
+ * @ingroup cleanup
+ * @brief Query 2D capability of the hardware.
+ *
+ * This function query the hardware whether given capabilities value
+ * (caps_val) is supported by hardware.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_query_2d_caps_hwhint(igd_driver_h driver_handle,
+ unsigned long caps_val,
+ unsigned long *status);
+
+
+
+/* 2D capabilities to query */
+#define IGD_2D_CAPS_BLT 0
+
+/* Output of 2D capabilities to query */
+#define IGD_2D_HW_DISABLE 0
+#define IGD_2D_HW_ENABLE 1
+#define IGD_2D_CAPS_UNKNOWN 2
+
+
+
+/*!
+ * @addtogroup power_group
+ * @{
+ */
+
+/*!
+ * @name Driver Save Flags
+ * @anchor driver_save_flags
+ *
+ * Flags for use with dispatch->driver_save()
+ * @{
+ */
+#define IGD_REG_SAVE_VGA 0x00001
+#define IGD_REG_SAVE_DAC 0x00002
+#define IGD_REG_SAVE_MMIO 0x00004
+#define IGD_REG_SAVE_RB 0x00008
+#define IGD_REG_SAVE_VGA_MEM 0x00010
+#define IGD_REG_SAVE_MODE 0x00020
+#define IGD_REG_SAVE_BACKLIGHT 0x00040
+#define IGD_REG_SAVE_3D 0x00080
+#define IGD_REG_SAVE_GTT 0x00100
+#define IGD_REG_SAVE_TYPE_REG 0x10000
+#define IGD_REG_SAVE_TYPE_CON 0x20000
+#define IGD_REG_SAVE_TYPE_MISC 0x40000
+#define IGD_REG_SAVE_TYPE_MASK 0xF0000
+
+#define IGD_REG_SAVE_ALL (IGD_REG_SAVE_VGA | IGD_REG_SAVE_DAC | \
+ IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB | IGD_REG_SAVE_VGA_MEM | \
+ IGD_REG_SAVE_MODE | IGD_REG_SAVE_BACKLIGHT | IGD_REG_SAVE_3D | \
+ IGD_REG_SAVE_GTT )
+
+/*!
+ * @note: This macro does not save the mode (i2c) regs. You have to
+ * explicitly ask for that too if you want it.
+ */
+#define IGD_REG_SAVE_STATE (IGD_REG_SAVE_VGA | IGD_REG_SAVE_DAC | \
+ IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB | IGD_REG_SAVE_VGA_MEM | \
+ IGD_REG_SAVE_GTT )
+/*! @} */
+
+
+/*! @} */
+
+#endif /* _IGD_INIT_H_ */
diff --git a/drivers/gpu/drm/emgd/include/igd_interrupt.h b/drivers/gpu/drm/emgd/include/igd_interrupt.h
new file mode 100644
index 0000000..6886a20
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_interrupt.h
@@ -0,0 +1,300 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_interrupt.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * The is the IGD exported interrupt access functions. It should be included
+ * by client drivers making use of interrupt functionality of IGD.
+ * This file Should NOT be included by any IGD modules because in some
+ * IGD environments the interrupt module will not be available.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INTERRUPT_H
+#define _IGD_INTERRUPT_H
+
+#include <igd_mode.h>
+
+typedef struct _oal_callbacks {
+
+ void (*spin_lock_irqsave)(void *lock);
+ void (*spin_unlock_irqrestore)(void *lock);
+ void (*spin_lock_isr)(void *lock);
+ void (*spin_unlock_isr)(void *lock);
+ void (*spin_lock)(void *lock);
+ void (*spin_unlock)(void *lock);
+} oal_callbacks_t;
+
+#define CB_FUNC(a, b, c) if(a && a->b) { a->b(c); }
+
+/* Responses returned to the client from drm */
+#define INT_INVALID -1
+#define INT_NOOP 0
+#define INT_CLEARED 1
+#define INT_HANDLED 2
+#define INT_READ 3
+#define INT_STORED 4
+#define INT_TIMEOUT 5
+
+/* Response from the ISR helper to the ISR routine */
+#define ISR_NEED_DPC 0
+#define ISR_HANDLED 1
+#define ISR_NOT_OURS 2
+
+typedef struct _interrupt_data {
+
+ void *irqmask_lock;
+
+ unsigned char *msvdx_reg;
+ unsigned long sgx_irq_mask;
+ unsigned long sgx_irq_mask2;
+ unsigned long vdc_irq_mask;
+ unsigned long msvdx_irq_mask;
+ int irq_enabled;
+
+ /* condition to wake up on */
+ unsigned int event_present;
+
+ /* interrupts that have already occured */
+ unsigned int out_vdc;
+
+ unsigned int out_sgx;
+ unsigned int out_sgx2;
+
+ unsigned int out_mtx;
+} interrupt_data_t;
+
+
+/*----------------------------------------------------------------------
+ * Typedef: igd_interrupt_handler_t
+ *
+ * Description:
+ * This function type is used for OS independent interrupt handlers
+ * that will be called by the hal to handle a requested interrupt.
+ *
+ * Members:
+ *
+ *----------------------------------------------------------------------
+ */
+typedef void (igd_interrupt_handler_t)(unsigned long type,
+ void *call_data,
+ void *user_data);
+
+
+/*----------------------------------------------------------------------
+ * Typedef: igd_interrupt_t
+ *
+ * Description:
+ * An opaque handle to identify an interrupt to be handled
+ *
+ * Members:
+ *
+ *----------------------------------------------------------------------
+ */
+typedef void * igd_interrupt_t;
+
+#define IGD_INTERRUPT_VBLANK 0x1
+#define IGD_INTERRUPT_SYNC 0x2
+
+/*----------------------------------------------------------------------
+ * Function:
+ * isr_helper
+ *
+ * Description:
+ * This function helps the OAL/DRM module in doing all chipset specific
+ * functionality like register sets when an ISR is fired
+ * Parameters:
+ * void
+ * Returns:
+ * int - 0 on the interrupt was handled and we need to queue a DPC for it
+ * - 1 on the interrupt was handled but wasn't one to do further
+ * processing on
+ * - 2 on failure
+ *----------------------------------------------------------------------
+ */
+int isr_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * unmask_int_helper
+ *
+ * Description:
+ * This function helps the OAL/DRM module in unmasking the Interrupt
+ * registers for a particular chipset so that the Interrupts can start
+ * firing
+ * Parameters:
+ * void
+ * Returns:
+ * int - 0 on SUCCESS
+ * - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int unmask_int_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * mask_int_helper
+ *
+ * Description:
+ * This function helps the OAL/DRM module in masking the Interrupt
+ * registers for a particular chipset so that the Interrupts can stop
+ * firing
+ * Parameters:
+ * void
+ * Returns:
+ * int - 0 on SUCCESS
+ * - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int mask_int_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * request_int_info_helper
+ *
+ * Description:
+ * This function helps the OAL module to request interrupt information
+ * and status
+ * Parameters:
+ * void *int_info_data
+ * Returns:
+ * int - 1 on Interrupt events supported and previous events occured
+ * - 0 on Interrupt events supported but no previous events occured
+ * - -1 on FAILURE or Interrupt events type not supported
+ *----------------------------------------------------------------------
+ */
+int request_int_info_helper(void *int_info_data);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * clear_occured_int_helper
+ *
+ * Description:
+ * This function helps the OAL module to request interrupt information
+ * and status
+ * Parameters:
+ * void *int_info_data
+ * Returns:
+ * void
+ *----------------------------------------------------------------------
+ */
+void clear_occured_int_helper(void *int_info_data);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * mask_int_helper
+ *
+ * Description:
+ * This function helps the OAL/DRM module in clearing the cached copy
+ * of Interrupt data
+ * Parameters:
+ * void
+ * Returns:
+ * void
+ *----------------------------------------------------------------------
+ */
+void clear_interrupt_cache(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * dpc_helper
+ *
+ * Description:
+ * This function helps the OAL/DRM module in doing all chipset specific
+ * functionality like register sets when an DPC is fired
+ * Parameters:
+ * interrupt_data_t **int_data
+ * Returns:
+ * int - 0 on SUCCESS
+ * - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int dpc_helper(interrupt_data_t **int_data);
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * interrupt_init
+ *
+ * Description:
+ * This function initializees the interrupt helper module
+ * Parameters:
+ * unsigned short did - Device ID for main video device
+ * oal_callbacks_t *oal_callbacks_table - Callback for
+ * spin lock related functions
+ * Returns:
+ * int - 0 on SUCCESS
+ * - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int interrupt_init(unsigned short did,
+ oal_callbacks_t *oal_callbacks_table);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * pre_init_interrupt
+ *
+ * Description:
+ * This function helps the OAL/DRM module in doing all chipset specific
+ * functionality like register sets before an ISR is initialized
+ * Parameters:
+ * unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ * void
+ *----------------------------------------------------------------------
+ */
+void pre_init_interrupt(unsigned char *virt_mmadr);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * post_init_interrupt
+ *
+ * Description:
+ * This function helps the OAL/DRM module in doing all chipset specific
+ * functionality like register sets after an ISR is initialized
+ * Parameters:
+ * unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ * void
+ *----------------------------------------------------------------------
+ */
+void post_init_interrupt(unsigned char *virt_mmadr);
+
+/*----------------------------------------------------------------------
+ * Function:
+ * uninstall_interrupt
+ *
+ * Description:
+ * This function helps the OAL/DRM module in doing all chipset specific
+ * functionality like register sets for removing Interrupt support
+ * Parameters:
+ * unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ * void
+ *----------------------------------------------------------------------
+ */
+void uninstall_interrupt(void);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_mode.h b/drivers/gpu/drm/emgd/include/igd_mode.h
new file mode 100644
index 0000000..3eb9c11
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_mode.h
@@ -0,0 +1,936 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_mode.h
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_MODE_H_
+#define _IGD_MODE_H_
+
+/*!
+ * @defgroup pixel_formats Pixel Format Definitions
+ * @ingroup display_group
+ *
+ * Pixel Format Definitions used in FB info data structure and
+ * throughout IGD API functions. Pixel formats are comprised
+ * of a Depth and Colorspace component combined (OR'd) with
+ * a unique number. Pixel formats and their components are
+ * defined with the following defines.
+ *
+ * @{
+ */
+
+/*!
+ * This is a just to make use of the Pixel format explicit. This could
+ * be replaced with an ENUM in the future.
+ */
+typedef unsigned long igd_pf_t;
+
+/*!
+ * @name Masks
+ * Masks that may be used to seperate portions of the pixel format
+ * definitions.
+ *
+ * @note Pixel Formats are maintained such that
+ * (pixel_format & IGD_PF_FMT_MASK) >> IGD_PF_FMT_SHIFT
+ * will always provide a unique index that can be used in a
+ * lookup table.
+ * @{
+ */
+#define IGD_PF_MASK 0x0000FFFF
+#define IGD_PF_TYPE_MASK 0x0000FF00
+#define IGD_PF_DEPTH_MASK 0x000000FF
+#define IGD_PF_FMT_MASK 0x00FF0000
+#define IGD_PF_FMT_SHIFT 16
+/*! @} */
+
+/*!
+ * @name Depths
+ * Pixel Format depths in Bits per pixel.
+ * @{
+ */
+#define PF_DEPTH_1 0x00000001
+#define PF_DEPTH_2 0x00000002
+#define PF_DEPTH_4 0x00000004
+#define PF_DEPTH_8 0x00000008
+#define PF_DEPTH_12 0x0000000c
+#define PF_DEPTH_16 0x00000010
+#define PF_DEPTH_24 0x00000018
+#define PF_DEPTH_32 0x00000020
+#define PF_DEPTH_64 0x00000040
+/*! @} */
+
+/* Unknown Pixel Format */
+#define IGD_PF_UNKNOWN 0x00000000
+
+/*!
+ * @name Colorspace
+ * Colorspace components of the overall pixel format definition.
+ * Several types may be OR'd together.
+ * To check for equivalent types use IGD_PF_TYPE(pf) == TYPE
+ *
+ * @{
+ */
+#define PF_TYPE_ALPHA 0x00000100
+#define PF_TYPE_RGB 0x00000200
+#define PF_TYPE_YUV 0x00000400
+#define PF_TYPE_PLANAR 0x00000800
+#define PF_TYPE_OTHER 0x00001000
+#define PF_TYPE_RGB_XOR 0x00002000 /* Cursor */
+#define PF_TYPE_COMP 0x00004000 /* Compressed */
+
+#define PF_TYPE_ARGB (PF_TYPE_ALPHA | PF_TYPE_RGB)
+#define PF_TYPE_YUV_PACKED (PF_TYPE_YUV)
+#define PF_TYPE_YUV_PLANAR (PF_TYPE_YUV | PF_TYPE_PLANAR)
+
+/*! @} */
+
+/*!
+ * @name 8 Bit RGB Pixel Formats
+ * @note Depth is bits per index (8)
+ * @{
+*/
+#define IGD_PF_ARGB8_INDEXED (PF_DEPTH_8 | PF_TYPE_ARGB | 0x00010000)
+#define IGD_PF_ARGB4_INDEXED (PF_DEPTH_4 | PF_TYPE_ARGB | 0x00020000)
+/*! @} */
+
+/*!
+ * @name 16 Bit RGB Pixel Formats
+ * @note Depth is bits per pixel (16)
+ * @{
+ */
+#define IGD_PF_ARGB16_4444 (PF_DEPTH_16 | PF_TYPE_ARGB | 0x00030000)
+#define IGD_PF_ARGB16_1555 (PF_DEPTH_16 | PF_TYPE_ARGB | 0x00040000)
+#define IGD_PF_RGB16_565 (PF_DEPTH_16 | PF_TYPE_RGB | 0x00050000)
+#define IGD_PF_xRGB16_555 (PF_DEPTH_16 | PF_TYPE_RGB | 0x00060000)
+/*! @} */
+
+/*!
+ * @name 24 Bit RGB Pixel Formats
+ * @note Depth is bits per pixel (24)
+ * @{
+ */
+#define IGD_PF_RGB24 (PF_DEPTH_24 | PF_TYPE_RGB | 0x00070000)
+/*! @} */
+
+/*!
+ * @name 32 Bit RGB Pixel Formats
+ * @note Depth is bits per pixel including unused bits (32).
+ * @{
+ */
+#define IGD_PF_xRGB32_8888 (PF_DEPTH_32 | PF_TYPE_RGB | 0x00080000)
+#define IGD_PF_xRGB32 IGD_PF_xRGB32_8888
+#define IGD_PF_ARGB32 (PF_DEPTH_32 | PF_TYPE_ARGB | 0x00090000)
+#define IGD_PF_ARGB32_8888 IGD_PF_ARGB32
+#define IGD_PF_xBGR32_8888 (PF_DEPTH_32 | PF_TYPE_RGB | 0x000a0000)
+#define IGD_PF_xBGR32 IGD_PF_xBGR32_8888
+#define IGD_PF_ABGR32 (PF_DEPTH_32 | PF_TYPE_ARGB | 0x000b0000)
+#define IGD_PF_ABGR32_8888 IGD_PF_ABGR32
+/*! @} */
+
+/*!
+ * @name YUV Packed Pixel Formats
+ * @note Depth is Effective bits per pixel
+ *
+ * @{
+ */
+#define IGD_PF_YUV422_PACKED_YUY2 (PF_DEPTH_16| PF_TYPE_YUV_PACKED| 0x000c0000)
+#define IGD_PF_YUV422_PACKED_YVYU (PF_DEPTH_16| PF_TYPE_YUV_PACKED| 0x000d0000)
+#define IGD_PF_YUV422_PACKED_UYVY (PF_DEPTH_16| PF_TYPE_YUV_PACKED| 0x000e0000)
+#define IGD_PF_YUV422_PACKED_VYUY (PF_DEPTH_16| PF_TYPE_YUV_PACKED| 0x000f0000)
+#define IGD_PF_YUV411_PACKED_Y41P (PF_DEPTH_12| PF_TYPE_YUV_PACKED| 0x00100000)
+#define IGD_PF_YUV444_PACKED_AYUV (PF_DEPTH_32| PF_TYPE_YUV_PACKED| 0x00340000)
+/*! @} */
+
+/*!
+ * @name YUV Planar Pixel Formats
+ * @note Depth is Y plane bits per pixel
+ * @{
+ */
+#define IGD_PF_YUV420_PLANAR_I420 (PF_DEPTH_8| PF_TYPE_YUV_PLANAR| 0x00110000)
+#define IGD_PF_YUV420_PLANAR_IYUV IGD_PF_YUV420_PLANAR_I420
+#define IGD_PF_YUV420_PLANAR_YV12 (PF_DEPTH_8| PF_TYPE_YUV_PLANAR| 0x00120000)
+#define IGD_PF_YUV410_PLANAR_YVU9 (PF_DEPTH_8| PF_TYPE_YUV_PLANAR| 0x00130000)
+#define IGD_PF_YUV420_PLANAR_NV12 (PF_DEPTH_8| PF_TYPE_YUV_PLANAR| 0x00140000)
+/*! @} */
+
+/*!
+ * @name Cursor Pixel Formats
+ * @{
+ *
+ * RGB_XOR_2: Palette = {Color 0, Color 1, Transparent, Invert Dest }
+ * RGB_T_2: Palette = {Color 0, Color 1, Transparent, Color 2 }
+ * RGB_2: Palette = {Color 0, Color 1, Color 2, Color 3 }
+ */
+#define IGD_PF_RGB_XOR_2 (PF_DEPTH_2 | PF_TYPE_RGB_XOR | 0x00150000)
+#define IGD_PF_RGB_T_2 (PF_DEPTH_2 | PF_TYPE_RGB | 0x00160000)
+#define IGD_PF_RGB_2 (PF_DEPTH_2 | PF_TYPE_RGB | 0x00170000)
+/*! @} */
+
+/*!
+ * @name Bump Pixel Formats
+ * @note Depth is bits per pixel
+ * @{
+ */
+#define IGD_PF_DVDU_88 (PF_DEPTH_16 | PF_TYPE_OTHER | 0x00180000)
+#define IGD_PF_LDVDU_655 (PF_DEPTH_16 | PF_TYPE_OTHER | 0x00190000)
+#define IGD_PF_xLDVDU_8888 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x001a0000)
+/*! @} */
+
+/*!
+ * @name Compressed Pixel Formats
+ * @note Depth is effective bits per pixel
+ * @{
+ */
+#define IGD_PF_DXT1 (PF_DEPTH_4 | PF_TYPE_COMP | 0x001b0000)
+#define IGD_PF_DXT2 (PF_DEPTH_8 | PF_TYPE_COMP | 0x001c0000)
+#define IGD_PF_DXT3 (PF_DEPTH_8 | PF_TYPE_COMP | 0x001d0000)
+#define IGD_PF_DXT4 (PF_DEPTH_8 | PF_TYPE_COMP | 0x001e0000)
+#define IGD_PF_DXT5 (PF_DEPTH_8 | PF_TYPE_COMP | 0x001f0000)
+/*! @} */
+
+/*!
+ * @name Depth Buffer Formats
+ * @note Depth is bits per pixel
+ * @{
+ */
+#define IGD_PF_Z16 (PF_DEPTH_16 | PF_TYPE_OTHER | 0x00200000)
+#define IGD_PF_Z24 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x00210000)
+#define IGD_PF_S8Z24 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x00220000)
+/*! @} */
+
+/*!
+ * @name Other Pixel Formats
+ *
+ * - I8 8bit value replicated to all color channels.
+ * - L8 8bit value replicated to RGB color channels, Alpha is 1.0.
+ * - A8 8bit Alpha with RGB = 0.
+ * - AL88 8bit Alpha, 8bit color replicated to RGB channels.
+ * - AI44 4bit alpha 4bit palette color.
+ * - IA44 4bit alpha 4bit palette color.
+ * @{
+ */
+#define IGD_PF_I8 (PF_DEPTH_8 | PF_TYPE_OTHER | 0x00230000)
+#define IGD_PF_L8 (PF_DEPTH_8 | PF_TYPE_OTHER | 0x00240000)
+#define IGD_PF_A8 (PF_DEPTH_8 | PF_TYPE_ALPHA | 0x00250000)
+#define IGD_PF_AL88 (PF_DEPTH_16 | PF_TYPE_ALPHA | PF_TYPE_OTHER | 0x00260000)
+#define IGD_PF_AI44 (PF_DEPTH_8 | PF_TYPE_OTHER | 0x00270000)
+#define IGD_PF_IA44 (PF_DEPTH_8 | PF_TYPE_OTHER | 0x00280000)
+
+#define IGD_PF_L16 (PF_DEPTH_16 | PF_TYPE_OTHER | 0x00290000)
+#define IGD_PF_ARGB32_2101010 (PF_DEPTH_32 | PF_TYPE_ARGB | 0x002a0000)
+#define IGD_PF_AWVU32_2101010 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x002b0000)
+#define IGD_PF_QWVU32_8888 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x002c0000)
+#define IGD_PF_GR32_1616 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x002d0000)
+#define IGD_PF_VU32_1616 (PF_DEPTH_32 | PF_TYPE_OTHER | 0x002e0000)
+
+/*!
+ * @name Floating-Point formats
+ *
+ * - R16F Floating-point format 16-bits for the Red Channel
+ * - GR32_1616F 32-bit float format using 16 bits for red and green channel
+ * - R32F IEEE Floating-Point s23e8 32-bits for the Red Channel
+ * - ABGR32_16161616F - This is a 64-bit FP format.
+ * - Z32F 32-bit float 3D depth buffer format.
+ * @{
+ */
+#define IGD_PF_R16F (PF_DEPTH_16 | PF_TYPE_OTHER | 0x002f0000)
+#define IGD_PF_GR32_1616F (PF_DEPTH_32 | PF_TYPE_OTHER | 0x00300000)
+#define IGD_PF_R32F (PF_DEPTH_32 | PF_TYPE_OTHER | 0x00310000)
+#define IGD_PF_ABGR64_16161616F (PF_DEPTH_64 | PF_TYPE_ARGB | 0x00320000)
+#define IGD_PF_Z32F (PF_DEPTH_32 | PF_TYPE_OTHER | 0x00330000)
+/*! @} */
+
+/*!
+ * @name IGD_PF_NEXT array length helper
+ *
+ * This helper should always be set to the next available PF id. In this
+ * manner any array that uses the id as an index can be defined as
+ * unsigned long lookup_table[IGD_PF_NEXT] = {...}; and will then generate
+ * compile warnings if the pixel format list length changes.
+ */
+#define IGD_PF_NEXT 0x35
+/*!
+ * @name Helper Macros
+ * @{
+ */
+
+/*! Gets bits per pixel from pixel format */
+#define IGD_PF_BPP(pf) ((pf) & IGD_PF_DEPTH_MASK)
+/*! Gets bits per pixel from pixel format */
+#define IGD_PF_DEPTH(pf) IGD_PF_BPP(pf)
+/*! Gets Bytes per pixel from pixel format */
+#define IGD_PF_BYPP(pf) ((IGD_PF_DEPTH(pf)+0x7)>>3)
+/*! Gets Bytes required for line of pixels */
+#define IGD_PF_PIXEL_BYTES(pf, np) (((IGD_PF_BPP(pf)*np) +0x7)>>3)
+/*! Gets numeric pf */
+#define IGD_PF_NUM(pf) ((pf>>16) & 0xff)
+/*! Gets pf type */
+#define IGD_PF_TYPE(pf) (pf & IGD_PF_TYPE_MASK)
+
+/*! @} */
+/*! @} */
+
+
+/*
+ * NOTE: When Adding pixel formats you must add correct definitions to
+ * any pixel format lookup tables. See igd_2d.c
+ */
+
+
+/*!
+ * @addtogroup display_group
+ *
+ * <B>Relavent Dispatch Functions</B>
+ * - _igd_dispatch::query_dc()
+ * - _igd_dispatch::query_mode_list()
+ * - _igd_dispatch::free_mode_list()
+ * - _igd_dispatch::alter_displays()
+ *
+ * @{
+ */
+
+/*!
+ * The opaque display handle, returned from igd_alloc_display().
+ * A display handle is needed for each physical display device.
+ */
+typedef void* igd_display_h;
+
+/*!
+ * The opaque timing_info handle.
+ */
+typedef void* igd_timing_info_h;
+
+/*!
+ * The maximum number of displays available in the display configurations
+ * below.
+ */
+#define IGD_MAX_DISPLAYS 2
+
+/*!
+ * @brief An opaque driver handle.
+ *
+ * This is an opaque driver handle. It is returned during driver init
+ * and remains usable for the life of the driver.
+ */
+typedef void* igd_driver_h;
+
+/*!
+ * @name Display Configuration Definition
+ * @anchor dc_defines
+ *
+ * The display configuration (dc) is a unique 32bit identifier that fully
+ * describes all displays in use and how they are attached to planes and
+ * pipes to form Single, Clone, Twin and Extended display setups.
+ *
+ * The DC is treated as 8 nibbles of information (nibble = 4 bits). Each
+ * nibble position in the 32bit DC corresponds to a specific role as
+ * follows:
+ *
+<PRE>
+ 0x12345678
+ ||||||||-- Legacy Display Configuration (Single, Twin, Clone, Ext)
+ |||||||--- Port Number for Primary Pipe Master
+ ||||||---- Port Number for Primary Pipe Twin 1
+ |||||----- Port Number for Primary Pipe Twin 2
+ ||||------ Port Number for Primary Pipe Twin 3
+ |||------- Port Number for Secondary Pipe Master
+ ||-------- Port Number for Secondary Pipe Twin 1
+ |--------- Port Number for Secondary Pipe Twin 2
+</PRE>
+ *
+ * The legacy Display Configuration determines if the display is in Single
+ * Twin, Clone or extended mode using the following defines. When a complex
+ * (>2 displays) setup is defined, the legacy configuration will describe
+ * only a portion of the complete system.
+ *
+ * - IGD_DISPLAY_CONFIG_SINGLE: A single primary display only.
+ * - IGD_DISPLAY_CONFIG_CLONE: Two (or more) displays making use of two
+ * display pipes. In this configuration two sets of display timings are
+ * used with a single source data plane.
+ * - IGD_DISPLAY_CONFIG_TWIN: Two (or more) displays using a single display
+ * pipe. In this configuration a single set of display timings are
+ * used for multiple displays.
+ * - IGD_DISPLAY_CONFIG_VEXT: Two (or more) displays making use of two
+ * display pipes and two display planes, however only one contiguous
+ * Frame buffer has been allocated that spans bothe displays vertically.
+ * In this configuration two sets of display timings are used and two
+ * source data planes.
+ * - IGD_DISPLAY_CONFIG_EXTENDED: Two (or more) displays making use of two
+ * display pipes and two display planes. In this configuration two sets
+ * of display timings are used and two source data planes.
+ *
+ * @{
+ */
+#define IGD_DISPLAY_CONFIG_SINGLE 0x1
+#define IGD_DISPLAY_CONFIG_CLONE 0x2
+#define IGD_DISPLAY_CONFIG_TWIN 0x4
+#define IGD_DISPLAY_CONFIG_VEXT 0x5
+#define IGD_DISPLAY_CONFIG_EXTENDED 0x8
+#define IGD_DISPLAY_CONFIG_MASK 0xf
+/*! @} */
+
+/*!
+ * @name IGD_DC_PORT_NUMBER
+ *
+ * Given a display configuration value and an index, return the port
+ * number at that position.
+ */
+#define IGD_DC_PORT_NUMBER(dc, i) (unsigned short) ((dc >> (i * 4)) & 0x0f)
+#define IGD_DC_PRIMARY(dc) (IGD_DC_PORT_NUMBER(dc,1))
+#define IGD_DC_SECONDARY(dc) (IGD_DC_PORT_NUMBER(dc,5))
+
+
+/*!
+ * @name IGD_DC_SINGLE
+ * For a given dc, return true if it is in single display mode
+ */
+#define IGD_DC_SINGLE(dc) ((dc & 0xf) == IGD_DISPLAY_CONFIG_SINGLE)
+/*!
+ * @name IGD_DC_TWIN
+ * For a given dc, return true if it is in twin display mode
+ */
+#define IGD_DC_TWIN(dc) ((dc & 0xf) == IGD_DISPLAY_CONFIG_TWIN)
+/*!
+ * @name IGD_DC_CLONE
+ * For a given dc, return true if it is in clone display mode
+ */
+#define IGD_DC_CLONE(dc) ((dc & 0xf) == IGD_DISPLAY_CONFIG_CLONE)
+/*!
+ * @name IGD_DC_VEXT
+ * For a given dc, return true if it is in vertically extended display mode
+ */
+#define IGD_DC_VEXT(dc) ((dc & 0xf) == IGD_DISPLAY_CONFIG_VEXT)
+/*!
+ * @name IGD_DC_EXTENDED
+ * For a given dc, return true if it is in extended display mode
+ */
+#define IGD_DC_EXTENDED(dc) ((dc & 0xf) == IGD_DISPLAY_CONFIG_EXTENDED)
+
+/*!
+ * @name Query DC Flags
+ * @anchor query_dc_flags
+ *
+ * - IGD_QUERY_DC_ALL: Query All usable DCs.
+ * - IGD_QUERY_DC_PREFERRED: Returns only preferred dc's from the list
+ * of all usable dc's. Twin mode dc's are eliminated if an equivalent
+ * Clone dc is available. Only the most useful/flexible combination
+ * of 3 displays is returned rather than all combinations of the 3
+ * displays.
+ * - IGD_QUERY_DC_INIT: Returns a pointer to the initial dc to be used.
+ * - IGD_QUERY_DC_EXISTING: Returns a pointer to the initial dc that
+ * most closely matches the DC in use by the hardware. This can be
+ * used by an IAL to "discover" what the vBIOS has arranged and use
+ * that configuration. (NOT IMPLEMENTED)
+ * @{
+ */
+#define IGD_QUERY_DC_ALL 0x0
+#define IGD_QUERY_DC_PREFERRED 0x1
+#define IGD_QUERY_DC_INIT 0x2
+#define IGD_QUERY_DC_EXISTING 0x3
+/*! @} */
+
+
+/*!
+ * @name DC index Flags
+ * @anchor dc_index_flags
+ *
+ * - IGD_DC_IDX_PRIMARY_MASTER: index to the primary display pipe master
+ * - IGD_DC_IDX_PRIMARY_TWIN1: index to the first primary display pipe's twin
+ * - IGD_DC_IDX_PRIMARY_TWIN2: index to the second primary display pipe's twin
+ * - IGD_DC_IDX_PRIMARY_TWIN3: index to the third primary display pipe's twin
+ * - IGD_DC_IDX_SECONDARY_MASTER: index to the secondary display pipe master
+ * - IGD_DC_IDX_SECONDARY_TWIN1: index to the first secondary display pipe's
+ * twin
+ * - IGD_DC_IDX_SECONDARY_TWIN2: index to the second secondary display pipe's
+ * twin
+ * @{
+ */
+#define IGD_DC_IDX_PRIMARY_MASTER 0x1
+#define IGD_DC_IDX_PRIMARY_TWIN1 0x2
+#define IGD_DC_IDX_PRIMARY_TWIN2 0x3
+#define IGD_DC_IDX_PRIMARY_TWIN3 0x4
+#define IGD_DC_IDX_SECONDARY_MASTER 0x5
+#define IGD_DC_IDX_SECONDARY_TWIN1 0x6
+#define IGD_DC_IDX_SECONDARY_TWIN2 0x7
+/*! @} */
+
+
+/*!
+ * @name Framebuffer Info Flags
+ * @anchor fb_info_flags
+ *
+ * These bits may be set in the flags member of the _igd_framebuffer_info
+ * data structure to alter the HALs behavior when calling
+ * dispatch::alter_displays() All other flag bits must be 0 when calling.
+ *
+ * - IGD_VBIOS_FB: The framebuffer info is not populated because the mode
+ * is being set with a VGA/VESA mode number. The HAL should instead
+ * return the framebuffer information to the caller when the mode
+ * has been set.
+ * - IGD_ENABLE_DISPLAY_GAMMA: The framebuffer data will be color corrected
+ * by using the 3*256 entry palette lookup table. Red, Green, and Blue
+ * 8 bit color values will be looked up and converted to another value
+ * during display. The pixels are not modified. The caller must also
+ * set the palette using _igd_dispatch::set_palette_entries()
+ * - IGD_REUSE_FB: The HAL will use the incoming framebuffer info as the
+ * framebuffer. The HAL will allocate a framebuffer only if
+ * frambuffer_info.allocated == 0 and this is the first use of the
+ * display. If the offset has been changed, the caller is now responsible
+ * for freeing the previous framebuffer surface, and the HAL now fully
+ * owns the incoming surface, freeing it on shutdown etc.
+ * - IGD_MIN_PITCH: The allocation will use the input value
+ * of pitch as the minimum acceptable pitch. This allows a caller
+ * to allocate a surface with "extra" room between the width and
+ * pitch so that the width may later be expanded (use with caution).
+ *
+ * Additionally all surface flags will be populated by the HAL and
+ * returned.
+ * See: @ref surface_info_flags
+ *
+ * @{
+ */
+#define IGD_VBIOS_FB 0x80000000
+#define IGD_ENABLE_DISPLAY_GAMMA 0x40000000
+#define IGD_REUSE_FB 0x20000000
+#define IGD_MIN_PITCH 0x10000000
+#define IGD_FB_FLAGS_MASK 0xf0000000
+/* @} */
+
+/*
+ * Right now, these flags are only used by igd_alter_displays when calling into
+ * the 3rd party dc code to indicate which flip-chains to
+ * disable.
+ */
+#define IGD_DISPLAY_PRIMARY 0x1
+#define IGD_DISPLAY_SECONDARY 0x2
+#define IGD_DISPLAY_ALL (IGD_DISPLAY_PRIMARY | IGD_DISPLAY_SECONDARY)
+
+/*!
+ * @brief Framebuffer related mode setting data.
+ * See _igd_dispatch::alter_displays()
+ *
+ * Data structure that contains details relavent to the framebuffer
+ * configuration. Used with igd_alter_display() to alter the framebuffer
+ * size and format.
+ *
+ * The framebuffer may be larger or smaller than the display timings. When
+ * larger the output will be cropped and can be used in a panning
+ * configuration. When smaller the output will be centered.
+ *
+ */
+typedef struct _igd_framebuffer_info {
+ unsigned int width; /*!< @brief width of fb */
+ unsigned int height; /*!< @brief height of fb */
+ /*!
+ * @brief Output pitch in bytes of the fb
+ *
+ * The pitch is the number of bytes from the first pixel of a line to
+ * the first pixel of the next line. This can, and usually will, be
+ * larger than width * depth for alignment purposes.
+ */
+ unsigned int screen_pitch;
+ unsigned long fb_base_offset; /*!< @brief memory location of the fb */
+ /*!< @brief Memory location of the currently visible buffer
+ *
+ * This is what is being displayed on the port, which may be another buffer
+ * (e.g. a PVR services swap-chain buffer) and not the frame buffer.
+ */
+ unsigned long visible_offset;
+
+ /* this is the offset that will be restored when swithcing back to dih mode from
+ * dihclone mode and also when unlock_plane is called.
+ */
+
+ unsigned long saved_offset;
+ unsigned int lock;
+ /*!
+ * @brief pixel format of the fb. See @ref pixel_formats
+ *
+ * This member is an input to the _igd_dispatch::alter_displays()
+ * function and must therefore be set to a pixel format that the
+ * hardware is capable of displaying as a framebuffer. The list
+ * of framebuffer pixel formats that are available can be queried
+ * by calling igd_dispatch::get_pixelformats()
+ */
+ unsigned long pixel_format;
+ unsigned long flags; /*!< @brief See: @ref fb_info_flags */
+ unsigned int allocated; /*!< @brief 1 when allocated, 0 otherwise */
+} igd_framebuffer_info_t, *pigd_framebuffer_info_t;
+
+
+/*!
+ * @name Display Info Flags
+ *
+ * Flags used with Display Info data structure to control boolean information.
+ *
+ * @note These flags are identical to the flags used with the port driver
+ * SDK. If any of these flags change, the corresponding flag in pd.h must
+ * also change.
+ *
+ * @{
+ */
+
+/* Enable/Disable Display */
+#define IGD_DISPLAY_DISABLE 0x00000000
+#define IGD_DISPLAY_ENABLE 0x00000001
+
+#define IGD_SCAN_MASK 0x80000000
+#define IGD_SCAN_PROGRESSIVE 0x00000000
+#define IGD_SCAN_INTERLACE 0x80000000
+
+#define IGD_PIX_LINE_DOUBLE_MASK 0x60000000
+#define IGD_DOUBLE_LINE_AND_PIXEL 0x60000000
+#define IGD_LINE_DOUBLE 0x40000000
+#define IGD_PIXEL_DOUBLE 0x20000000
+#define IGD_MODE_TEXT 0x10000000
+
+#define IGD_VSYNC_HIGH 0x08000000
+#define IGD_HSYNC_HIGH 0x04000000
+#define IGD_BLANK_LOW 0x02000000
+#define IGD_MODE_VESA 0x01000000 /* VGA/VESA mode number is valid*/
+
+#define IGD_MODE_STALL 0x00800000 /* Flag to enable stall signal */
+#define IGD_MODE_SCALE 0x00400000 /* Request NATIVE pipe timings */
+
+#define IGD_ASPECT_16_9 0x00200000 /* 16:9 aspect ratio */
+
+#define IGD_MODE_DTD 0x00080000 /* Read from EDID */
+#define IGD_MODE_DTD_USER 0x00040000 /* User defined timing */
+#define IGD_MODE_DTD_FP_NATIVE 0x00020000 /* Native fp timing */
+#define IGD_MODE_SUPPORTED 0x00010000
+
+#define IGD_MODE_FACTORY 0x00008000 /* Factory supported mode */
+#define IGD_MODE_RB 0x00004000 /* Reduced blanking mode */
+
+/*
+ * Port type definitions to be used in display_info flags.
+ * Also used in port_type field of internal port data structure.
+ */
+#define IGD_PORT_MASK 0x000FF000
+#define IGD_PORT_ANY 0x000FF000
+#define IGD_PORT_ANALOG 0x00001000
+#define IGD_PORT_DIGITAL 0x00002000
+#define IGD_PORT_SDVO IGD_PORT_DIGITAL
+#define IGD_PORT_LVDS 0x00004000
+#define IGD_PORT_RGBA 0x00008000 /* Enhanced DVO (Sunizona) */
+#define IGD_PORT_TV 0x00010000 /* Integrated TV (Alviso) */
+#define IGD_PORT_SDVO_ST 0x00020000
+#define IGD_PORT_SDVO_ST_GPIO 0x00040000
+
+
+/* Atom E6xx requires LPC device, define a port type to differentiate
+ * with other devices such as 0:2:0, 0:3:0 */
+#define IGD_PORT_LPC 0x80000000 /* LPC device 0:31:0 */
+
+/*
+ * Standard port definitions
+ */
+#define IGD_PORT_TYPE_TV 0x1
+#define IGD_PORT_TYPE_SDVOB 0x2
+#define IGD_PORT_TYPE_SDVOC 0x3
+#define IGD_PORT_TYPE_LVDS 0x4
+#define IGD_PORT_TYPE_ANALOG 0x5
+
+/*! Max ports
+ * This is the maximum number of ports currently defined to encompass all
+ * hardware configurations. This should always match the largest defined
+ * port number in the port tables. Currently the largest port number is 5
+ * for the analog port. If a larger port number is defined, then this
+ * number must be increased.
+ */
+#define IGD_MAX_PORTS 5
+
+
+/*! @} */
+
+/*!
+ * @brief Display timing information for use with
+ * _igd_dispatch::alter_displays()
+ */
+typedef struct _igd_display_info {
+ unsigned short width;
+ unsigned short height;
+ unsigned short refresh;
+ unsigned long dclk; /* in KHz */
+ unsigned short htotal;
+ unsigned short hblank_start;
+ unsigned short hblank_end;
+ unsigned short hsync_start;
+ unsigned short hsync_end;
+ unsigned short vtotal;
+ unsigned short vblank_start;
+ unsigned short vblank_end;
+ unsigned short vsync_start;
+ unsigned short vsync_end;
+ short mode_number;
+ unsigned long flags;
+ unsigned short x_offset;
+ unsigned short y_offset;
+ /* unsigned short port_number; */
+ /* void *pd_private_ptr; */ /* Pointer for use by the PD for any purpose. */
+ void *private_ptr; /* INTERNAL pointer for use by main driver only */
+ unsigned short reserved_dd; /* Reserved for device dependant layer */
+ unsigned short reserved_dd_ext; /* Reserved for device dependant layer */
+} igd_display_info_t, *pigd_display_info_t;
+
+
+/*!
+ * @name Query Modes Flags (deprecated)
+ * @deprecated To be removed in IEGD 5.1
+ *
+ * Flags for use in igd_query_display function call
+ *
+ * @{
+ */
+#define IGD_QUERY_ALL_MODES 0x01
+#define IGD_QUERY_PORT_MODES 0x00
+/*! @} */
+
+
+/*!
+ * @name Query Mode List Flags
+ * @anchor query_mode_list_flags
+ *
+ * Flags for use with _igd_dispatch::query_mode_list()
+ * - IGD_QUERY_PRIMARY_MODES: Query mode list for the primary pipe.
+ * - IGD_QUERY_SECONDARY_MODES: Query modes list for the secondary pipe.
+ * - IGD_QUERY_LIVE_MODES: Query the live modes instead of filtering
+ * and allocing a new list. This may be ORed with other bits.
+ * @{
+ */
+#define IGD_QUERY_PRIMARY_MODES 0x0
+#define IGD_QUERY_SECONDARY_MODES 0x1
+#define IGD_QUERY_LIVE_MODES 0x2
+/*! @} */
+
+
+/*!
+ * @name timing table end of list marker
+ *
+ * This value is used to mark the end of a timing list (igd_display_info_t).
+ * It is stored in the width field. This must match the value for
+ * PD_TIMING_LIST_END in src/include/pd.h
+ *
+ * @{
+ */
+#define IGD_TIMING_TABLE_END 0xffff
+/*! @} */
+
+/*!
+ * @name Alter Displays Flags
+ * @anchor alter_displays_flags
+ *
+ * These flags are passed to _igd_dispatch::alter_displays() and are
+ * defined as follows:
+ * - IGD_TEST When set, this flag indicates that the mode should only be
+ * tested. The hardware will not be modified.
+ * - IGD_FORCE_ALTER When set the hardware will be modified even if the
+ * mode is the same as the current mode.
+ * - IGD_CLEAR_FB Clear the framebuffer to black after the mode set.
+ *
+ * These flags control which ring buffers are allocated for the display.
+ * These ring buffers are used with all rendering functions and designate
+ * the target for the rendering commands.
+ *
+ * - IGD_ALLOC_PRIORITY_NORMAL Command slot used for normal commands
+ * - IGD_ALLOC_PRIORITY_INTERRUPT Command slot with highest priority, often
+ * used to send commands during interrupt time. This command slot is
+ * not fully functional.
+ * - IGD_ALLOC_PRIORITY_POWER In theory this command slot could send power
+ * events with a higher priority than a regular command slot. In
+ * practice it is unused.
+ * - IGD_ALLOC_PRIORITY_BIN Binner ring buffer. This command slot requires
+ * knowledge of how the hardware binner works.
+ *
+ * @bug The Priority Flags overlap with other alter_displays flags and
+ * need to be relocated for IEGD 5.1
+ *
+ * @{
+ */
+#define IGD_TEST 0x08000000
+#define IGD_FORCE_ALTER 0x04000000
+#define IGD_CLEAR_FB 0x02000000
+
+#define IGD_ALLOC_PRIORITY_NORMAL 0x10000000
+#define IGD_ALLOC_PRIORITY_INTERRUPT 0x20000000
+#define IGD_ALLOC_PRIORITY_POWER 0x40000000
+#define IGD_ALLOC_PRIORITY_BIN 0x80000000
+/*! @} */
+
+/*!
+ * Display handle list and Display info list should be terminated with
+ * this tag. List may contain nulls, they will be skipped.
+ *
+ * @note This value is -1 so it will work the same on 32 and 64 bit platforms
+ */
+#define IGD_LIST_END -1
+
+
+
+
+/*!
+ * @name Cursor Info Flags
+ * @anchor cursor_info_flags
+ *
+ * Flags for use in the Cursor Info Structure
+ *
+ * @{
+ */
+#define IGD_CURSOR_ON 0x00000001
+#define IGD_CURSOR_OFF 0x00000000
+#define IGD_CURSOR_LOAD_ARGB_IMAGE 0x00000010
+#define IGD_CURSOR_LOAD_XOR_IMAGE 0x00000020
+
+#define IGD_CURSOR_GAMMA 0x00000002
+#define IGD_CURSOR_LOCAL 0x00000004 /* Local Memory */
+#define IGD_CLONE_CURSOR 0x00000001
+/*! @} */
+
+/*!
+ * @brief Cursor Plane information
+ *
+ * This data structure is used as input and output to the
+ * _igd_dispatch::alter_cursor() dispatch function.
+ */
+typedef struct _igd_cursor_info {
+ unsigned long width;
+ unsigned long height;
+ unsigned long pixel_format;
+ /*
+ * Use the XOR offset for all 2 bit formats, and the ARGB offset for
+ * 32bit formats. If either offset is 0 it should be assumed that the
+ * HAL cannot support it.
+ */
+ unsigned long xor_offset;
+ unsigned long xor_pitch;
+ unsigned long argb_offset;
+ unsigned long argb_pitch;
+ long x_offset;
+ long y_offset;
+ long hot_x;
+ long hot_y;
+ unsigned long palette[4];
+ unsigned long flags;
+ unsigned long rotation;
+ unsigned long render_scale_x;
+ unsigned long render_scale_y;
+ unsigned short off_screen;
+} igd_cursor_info_t;
+
+/*!
+ * @name Get Scanline Defines
+ * @anchor get_scanline_defs
+ *
+ * These defines are returned from the _igd_dispatch::get_scanline()
+ * dispatch function in the place of scanline number when no number exists.
+ *
+ * @{
+ */
+#define IGD_IN_VBLANK -1
+/*! @} */
+
+
+
+
+/*!
+ * @name Acess i2c Flags
+ * @anchor access_i2c_flags
+ *
+ * These flags are used to control the flow of data in the
+ * igd_dispatch::access_i2c() dispatch function.
+ *
+ * @{
+ */
+#define IGD_I2C_READ 0x00000001
+#define IGD_I2C_WRITE 0x00000002
+/*! @} */
+
+/*!
+ * @brief I2C data packet for use with _igd_dispatch::access_i2c()
+ */
+typedef struct _igd_i2c_reg {
+ /*! @brief Serial bus id [0..6] for alm core, and 0 for whitney core */
+ unsigned char bus_id;
+ /*! @brief Data address byte of the device */
+ unsigned char dab;
+ /*! @brief Device register */
+ unsigned char reg;
+ /*! @brief Buffer for register values */
+ unsigned char *buffer;
+ /*! @brief number of bytes to read or write */
+ unsigned char num_bytes;
+ /*! @brief i2c bus speed in KHz */
+ unsigned long i2c_speed;
+} igd_i2c_reg_t;
+
+
+
+typedef struct _igd_port_info {
+ char pd_name[64];
+ unsigned long driver_version; /* Formatted as pd_version_t */
+ unsigned long port_num; /* Port Number */
+ unsigned long display_type; /* Type of display */
+ int connected; /* 1 - Display connected, 0 - Otherwise */
+ char port_name[8]; /* Default port name (DVOA, sDVO-A, etc.) */
+ unsigned long flags; /* Attribute flags, currently used for interlace */
+} igd_port_info_t;
+
+
+
+typedef struct _kdrm_driver_set_sync_refresh {
+ igd_display_h display_handle;
+ unsigned int start_line;
+ unsigned int bottom_line;
+} emgd_drm_driver_set_sync_refresh_t;
+
+
+
+/*!
+ * @name Alloc Display Flags (deprecated)
+ *
+ * Flags for use with the igd_alloc_display function call.
+ * - IGD_NEW_ALL Default, request for new plane, pipe, port
+ * - IGD_NEW_PIPE Request for an additional pipe & port, using the same plane
+ * from previous allocation
+ * - IGD_NEW_PORT Request for an addition port, using the same pipe and plane
+ * from previous allocation
+ *
+ * @{
+ */
+#define IGD_NEW_MASK 0x00700000
+#define IGD_NEW_ALL 0x00400000
+#define IGD_NEW_PIPE 0x00200000
+#define IGD_NEW_PORT 0x00100000
+/*! @} */
+
+typedef int (*_igd_query_modes_fn_t)(igd_display_h display_handle,
+ igd_display_info_t **mode_list);
+/*! @} */
+
+#endif /* _IGD_MODE_H_ */
diff --git a/drivers/gpu/drm/emgd/include/igd_ovl.h b/drivers/gpu/drm/emgd/include/igd_ovl.h
new file mode 100755
index 0000000..67ffa85
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_ovl.h
@@ -0,0 +1,327 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_ovl.h
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the external header file for overlay. It should be included
+ * by ial and/or other HAL modules that require overlay interaction.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_OVL_H
+#define _IGD_OVL_H
+
+/*!
+ * @defgroup overlay_group Overlay
+ * @ingroup video_group
+ *
+ * The overlay module is responsible for the hardware overlay and the secondary
+ * overlay (sometimes referred to as plane C).
+ *
+ * <B>Relevent Dispatch Fucntions</B>
+ * - _igd_dispatch::alter_ovl()
+ * - _igd_dispatch::query_ovl()
+ * - _igd_dispatch::query_max_size_ovl()
+ * @{
+ */
+
+/*----------------------------------------------------------------------------
+ * Overlay Alter Flags
+ *--------------------------------------------------------------------------*/
+/*!
+ * @name Alter Overlay Flags
+ * @anchor alter_ovl_flags
+ *
+ * Flags for use with _igd_dispatch::alter_ovl()
+ * - IGD_OVL_ALTER_OFF: Turn the overlay off
+ * - IGD_OVL_ALTER_ON: Turn the overlay on
+ *
+ * - IGD_OVL_ALTER_PROGRESSIVE: The overlay is progressive. Only valid when
+ * the overlay is on
+ * - IGD_OVL_ALTER_INTERLEAVED: The overlay is interleaved/bobbed. Only valid
+ * when the overlay is on
+ *
+ * - IGD_OVL_ALTER_FLIP_EVEN: Flip the even field. Only valid when the overlay
+ * is on
+ * - IGD_OVL_ALTER_FLIP_ODD: Flip the odd field. Only valid when the overlay
+ * is on
+ * @{
+ */
+#define IGD_OVL_ALTER_OFF 0
+#define IGD_OVL_ALTER_ON 1
+
+#define IGD_OVL_ALTER_PROGRESSIVE 0
+#define IGD_OVL_ALTER_INTERLEAVED 2
+
+#define IGD_OVL_ALTER_FLIP_EVEN 0
+#define IGD_OVL_ALTER_FLIP_ODD 4
+
+#define IGD_FW_VIDEO_OFF 8
+
+#define IGD_OVL_FORCE_USE_DISP 0x10
+#define IGD_OVL_OSD_ON_SPRITEC 0x20
+#define IGD_OVL_GET_SURFACE_DATA 0x50
+
+/* Note: VEXT: Keep this bitwise! */
+#define IGD_OVL_ALTER_VEXT_PRIMARY 0x100
+#define IGD_OVL_ALTER_VEXT_SECONDARY 0x200
+/*! @} */
+
+/* These are not actually used by any IAL
+#define IGD_OVL_ALTER_MIRROR_NONE 0
+#define IGD_OVL_ALTER_MIRROR_H 0x10
+#define IGD_OVL_ALTER_MIRROR_V 0x20
+#define IGD_OVL_ALTER_MIRROR_HV (IGD_OVL_FLAGS_MIRROR_H|IGD_OVL_FLAGS_MIRROR_V) */
+
+/*----------------------------------------------------------------------------
+ * Overlay Query Flags
+ *--------------------------------------------------------------------------*/
+/*!
+ * @name Query Overlay Flags
+ * @anchor query_ovl_flags
+ *
+ * Flags for use with _igd_dispatch::query_ovl()
+ * These flags ARE EXCLUSIVE - ONLY ONE AT A TIME can be used during a
+ * single call to igd_query_ovl
+ *
+ * - IGD_OVL_QUERY_IS_HW_SUPPORTED: Can the hardware support an overlay for
+ * this display_h? This will return the same value no matter if the overlay
+ * is on or off, so the IAL must use some other method to determine if the
+ * overlay is in use.
+ * - IGD_OVL_QUERY_IS_LAST_FLIP_DONE: Has the last flip completed?
+ * - IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE: Wait until the last flip is complete.
+ * Returns TRUE if the last flip was successfully completed. Returns FALSE
+ * if there was a HW issue where the last flip did not occur.
+ * - IGD_OVL_QUERY_IS_ON: Is the hardware overlay currently on? This does not
+ * include the secondary overlay, only the hardware overlay.
+ * - IGD_OVL_QUERY_IS_GAMMA_SUPPORTED: Is the hardware supports GAMMA
+ * correction?
+ * - IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED: Is the hardware supports video
+ * parameters (brightness, contrast, saturation) correction?
+ * @{
+ */
+#define IGD_OVL_QUERY_IS_HW_SUPPORTED 0x00000001
+#define IGD_OVL_QUERY_IS_LAST_FLIP_DONE 0x00000002
+#define IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE 0x00000003
+#define IGD_OVL_QUERY_IS_ON 0x00000004
+#define IGD_OVL_QUERY_IS_GAMMA_SUPPORTED 0x00000005
+#define IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED 0x00000006
+#define IGD_OVL_QUERY_MASK 0x0000000F
+ /* Ensure no bits conflict with IGD_OVL_FORCE_USE_DISP above */
+/*! @} */
+
+/* This is now in igd_query_max_size_ovl
+ * Get the maximum width/height for the src_surface pixel format
+ * return: max width and height parameters; should always return TRUE.
+#define IGD_OVL_QUERY_MAX_WIDTH_HEIGHT 0x00000003
+ */
+
+/* This should not be needed. Since the IAL is always passing in valid
+ * gamma information, the IAL should not query the HAL for the information.
+#define IGD_OVL_QUERY_COLOR_CORRECT_INFO 0x00000005*/
+
+
+/*----------------------------------------------------------------------------
+ * Overlay Color Key
+ *--------------------------------------------------------------------------*/
+/*!
+ * @name Overlay Color Key Flags
+ * @anchor igd_ovl_color_key_info_flags
+ *
+ * Flags for use with @ref igd_ovl_color_key_info_t
+ * Enables and disables the src and dest color key for the overlay
+ *
+ * IGD_OVL_DST_BLEND_ENABLE enabled blending the contents of the overlay
+ * with the contents of the frambuffer using the alpha from the framebuffer.
+ * (As if the framebuffer was on top of the overlay) This feature requires
+ * that dest colorkey be enabled.
+ *
+ * @{
+ */
+#define IGD_OVL_SRC_COLOR_KEY_DISABLE 0x00000000
+#define IGD_OVL_SRC_COLOR_KEY_ENABLE 0x00000001
+
+#define IGD_OVL_DST_COLOR_KEY_DISABLE 0x00000000
+#define IGD_OVL_DST_COLOR_KEY_ENABLE 0x00000002
+
+#define IGD_OVL_DST_BLEND_ENABLE 0x00000004
+/*! @} */
+
+/*!
+ * @brief Overlay Color Key
+ *
+ * The src_lo, src_hi, and dest color key are in the following pixel format
+ * based on the pixel format of the src and dest surface.
+ * Note: Alpha is always ignored.
+ *
+ * - xRGB32 = x[31:24] R[23:16] G[15:8] B[7:0]
+ * - xRGB16_555 = x[31:15] R[14:10] G[9:5] B[4:0]
+ * - ARGB8_INDEXED = x[31:8] Index Color[7:0]
+ * - YUV surf = x[31:24] Y[23:16] U[15:8] V[7:0]
+ *
+ * If the source pixel (overlay) is within the src_lo and src_hi color key
+ * (inclusive) for all color components, then the destination pixel is
+ * displayed. Otherwise the source pixel is displayed.
+ *
+ * If the source and dest color key are both enabled, what happens???
+ */
+typedef struct _igd_ovl_color_key_info {
+ /*! Low end src color key value */
+ unsigned long src_lo;
+ /*! High end src color key value */
+ unsigned long src_hi;
+ /*! Dest color key value. If the destination pixel matches the
+ * dest color key then the souce pixel from the video surface is displayed.
+ * Otherwise, the destination pixel is displayed */
+ unsigned long dest;
+ /*! Enable and disable the src and dest color key.
+ * See @ref igd_ovl_color_key_info_flags */
+ unsigned long flags;
+} igd_ovl_color_key_info_t;
+
+/*----------------------------------------------------------------------------
+ * Overlay Video Quality
+ *--------------------------------------------------------------------------*/
+/*!
+ * @brief Overlay Video Quality
+ *
+ * All have a range between 0x0000 and 0xFFFF with default = 0x8000
+ */
+typedef struct _igd_ovl_video_quality_info{
+ unsigned short contrast;
+ unsigned short brightness;
+ unsigned short saturation;
+ unsigned short hue;
+} igd_ovl_video_quality_info_t;
+
+
+/*----------------------------------------------------------------------------
+ * Overlay Gamma
+ *--------------------------------------------------------------------------*/
+/*!
+ * @name Overlay Gamma Flags
+ * @anchor igd_ovl_gamma_info_flags
+ *
+ * Flags for use with @ref igd_ovl_gamma_info_t.
+ * Enables and disables the gamma for the overlay
+ *
+ * @{
+ */
+#define IGD_OVL_GAMMA_DISABLE 0x00000000
+#define IGD_OVL_GAMMA_ENABLE 0x00000001
+/* UM only flag to indicate individual
+ * plane color correction values should be applied */
+#define IGD_OVL_GAMMA_OVERRIDE 0x00000002
+/*! @} */
+
+/*!
+ * @name Overlay Gamma Min/Max
+ * @anchor igd_ovl_gamma_info_range
+ *
+ * Minimum and maximum gamma values for red, green, and blue with
+ * @ref igd_ovl_gamma_info_t. These values are in 24i.8f format.
+ * Minimum value is 0.6
+ * Maximum value is 6.0
+ *
+ * @{
+ */
+#define IGD_OVL_GAMMA_DEFAULT 0x100 /* 1.0 */
+#define IGD_OVL_GAMMA_MIN 0x09A /* 0.6 */
+#define IGD_OVL_GAMMA_MAX 0x600 /* 6.0 */
+/*! @} */
+
+/*!
+ * @brief Overlay Gamma
+ *
+ * Red, green, and blue values must be between min and max values.
+ * This value is in 24i.8f format.
+ * See @ref igd_ovl_gamma_info_range
+ */
+typedef struct _igd_ovl_gamma_info{
+ unsigned int red;
+ unsigned int green;
+ unsigned int blue;
+ /*! Enable and disable the gamma for the overlay.
+ * See @ref igd_ovl_gamma_info_flags */
+ unsigned int flags;
+} igd_ovl_gamma_info_t;
+/*! @} */
+
+/*----------------------------------------------------------------------------
+ * Overlay Info
+ *--------------------------------------------------------------------------*/
+/*!
+ * @brief Overlay Information (includes color key, video quality, and gamma)
+ */
+typedef struct _igd_ovl_info{
+ igd_ovl_color_key_info_t color_key;
+ igd_ovl_video_quality_info_t video_quality;
+ igd_ovl_gamma_info_t gamma;
+} igd_ovl_info_t;
+
+typedef struct _video_surface_data {
+ int flags;
+ void *file;
+} vid_surf_data_t;
+
+#define OVL_PRIMARY 0
+#define OVL_SECONDARY 1
+#define OVL_MAX_HW 2 /* Maximum number of overlays */
+
+/* Define the maximum number of blend surfaces which can be used */
+#define MAX_BLEND_SURF 3
+
+/* User mode overlay context */
+typedef struct _ovl_um_context {
+ /* OVLADD add additional overlay initialization parameters here. */
+
+ int in_dihclone;
+ int vext;
+ int chiptype;
+ void *dispatch; /* can't make this igd_dispatch_t due to circular reference */
+ unsigned long dc;
+ unsigned int state;
+
+ igd_display_h primary;
+ void *primary_pipe; /* intel_pipe_data_t */
+
+ igd_display_h secondary;
+ void *secondary_pipe; /*intel_pipe_data_t */
+
+ unsigned int blend_surf_num[OVL_MAX_HW];
+ igd_surface_t blend_surf[OVL_MAX_HW][MAX_BLEND_SURF];
+
+ vid_surf_data_t *vid_surf_data_ptr;
+ igd_display_h ovl_display_um[OVL_MAX_HW];
+ igd_ovl_info_t ovl_info_um[OVL_MAX_HW];
+ igd_display_h active_single_ovl;
+} ovl_um_context_t;
+
+
+
+#endif /*_IGD_OVL_H*/
+
+#define WAIT_FOR_FLIP 1
+#define FLIP_DONE 0
diff --git a/drivers/gpu/drm/emgd/include/igd_pd.h b/drivers/gpu/drm/emgd/include/igd_pd.h
new file mode 100644
index 0000000..2963620
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pd.h
@@ -0,0 +1,544 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pd.h
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_PD_H_
+#define _IGD_PD_H_
+
+#define PD_ATTR_LIST_END 0xFFFFFFFF
+
+#define PD_NAME_SIZE 64
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*!
+ * @addtogroup display_group
+ *
+ * @{
+ */
+
+/*
+ * Display attributes (igd_attr_t):
+ * id - Any associated id. See below list for known attribute ids.
+ *
+ * type - type of the attribute. (RANGE/LIST/BOOL/BUFFER)
+ *
+ * name - Name of the attribute. For example 'brightness', 'contrast'
+ *
+ * flags - any flags for the attribute
+ *
+ * PD_ATTR_FLAG_SETMODE - IGD will set this flag.
+ * If this flag is set, then changing
+ * the attribute value required set mode
+ * operation.
+ *
+ * Caller (IAL) should check for this flag
+ * after calling igd_set_attrs(). If this
+ * flag is set, then IAL has to do a setmode
+ * operation via igd_alter_display().
+ *
+ * PD_ATTR_FLAG_VALUE_CHANGED - Caller will set this flag.
+ * If this flag is set, means the
+ * attribute value was changed to
+ * the value mentioned.
+ *
+ * Caller will specify SS that the
+ * value was changed.
+ *
+ * PD_ATTR_FLAG_DONT_APPLY - If this flag is set, means the
+ * attribute value will be applied
+ * to new value at the time of next
+ * setmode operation.
+ *
+ *
+ * PD_ATTR_FLAG_USER_INVISIBLE - If this flag is set, means the
+ * attribute is invisible to end-user
+ * and not available for run-time
+ * changes.
+ *
+ * If the type is PD_ATTR_TYPE_RANGE, then this structure contains further
+ * details about this attribute (igd_range_attr_t):
+ * default_value - Default value
+ * current_value - Current value
+ * min - Minimum value for this attribute
+ * max - Maximum value for this attribute
+ * step - Value changes in increments of 'step'
+ *
+ * If the type is PD_ATTR_TYPE_LIST, then this structure contains further
+ * details about this attribute (igd_list_attr_t):
+ * default_index - this is the index into above list to point
+ * default value for this attribute
+ *
+ * current_index - this is the index into above list to point
+ * current value for this attribute
+ *
+ * num_entries - number values avaliable for this list attribute,
+ * for example, for TVFormat attribute, the available
+ * values can be NTSC, NTSC_M, PAL, PAL_D etc etc...
+ *
+ * _pad - [reserved] Pad bytes to make all attributes
+ * structures with same size.
+ *
+ * If the type is PD_ATTR_TYPE_LIST, then there are num_entries structures
+ * of igd_list_entry_attr_t will be there (igd_list_entry_attr_t):
+ * name - name is overloaded for example for TVFormat attribute
+ * the names will be "NTSC", "NTSC_M" etc etc...
+ *
+ * flags - same as above flags.
+ *
+ * value - Internal value for "NTSC", i.e., the #define value.
+ *
+ * _pad - [reserved] Pad bytes to make all attributes
+ * structures with same size.
+ *
+ * If the type is PD_ATTR_TYPE_BOOL, then this structure contains further
+ * details about this attribute (igd_bool_attr_t):
+ * default_value - Default value (TRUE/FALSE)
+ *
+ * current_value - Current value (TRUE/FALSE)
+ *
+ * _pad - [reserved] Pad bytes to make all attributes
+ * structures with same size.
+ *
+ * If the type is PD_ATTR_TYPE_BUFFER, then there is a buffer pointer
+ * in the structure to pass larger chunks of data. Originator owns the
+ * buffer.
+ * buffer_size - size of the buffer
+ *
+ * buffer - pointer to buffer
+ *
+ */
+#define PD_ATTR_TYPE_RANGE 0x1
+#define PD_ATTR_TYPE_LIST 0x2
+#define PD_ATTR_TYPE_BOOL 0x3
+#define PD_ATTR_TYPE_LIST_ENTRY 0x4
+#define PD_ATTR_TYPE_BUFFER 0x5
+
+/*!
+ * @name Attribute ID definitions
+ * @anchor attr_id_defs
+ *
+ * These IDs specify what the attribute is and also index into the list of
+ * attributes. See get_attrs() and set_attrs() for more information.
+ *
+ * @{
+ */
+#define PD_ATTR_ID_BRIGHTNESS 0x00
+#define PD_ATTR_ID_CONTRAST 0x01
+#define PD_ATTR_ID_HUE 0x02
+#define PD_ATTR_ID_FLICKER 0x03
+#define PD_ATTR_ID_HPOSITION 0x04
+#define PD_ATTR_ID_VPOSITION 0x05
+#define PD_ATTR_ID_HSCALE 0x06
+#define PD_ATTR_ID_VSCALE 0x07
+#define PD_ATTR_ID_TVFORMAT 0x08 /* See below for list of TV formats */
+#define PD_ATTR_ID_DISPLAY 0x09 /* See below for list of displays */
+#define PD_ATTR_ID_LUMA_FILTER 0x0A
+#define PD_ATTR_ID_CHROMA_FILTER 0x0B
+#define PD_ATTR_ID_TEXT_FILTER 0x0C
+#define PD_ATTR_ID_TVOUT_TYPE 0x0E
+#define PD_ATTR_ID_SATURATION 0x0F
+#define PD_ATTR_ID_PANEL_FIT 0x12 /* Up/Down scale yes/no */
+#define PD_ATTR_ID_SCALING_RATIO 0x13
+#define PD_ATTR_ID_FP_BACKLIGHT_EN 0x14 /* Enable Flat panel backlight */
+#define PD_ATTR_ID_FP_PWR_T1 0x15 /* VDD active - DVO CLK/DATA active */
+#define PD_ATTR_ID_FP_PWR_T2 0x16 /* DVO active - Backlight enable */
+#define PD_ATTR_ID_FP_PWR_T3 0x17 /* Backlight disable - DVO inactive */
+#define PD_ATTR_ID_FP_PWR_T4 0x18 /* DVO inactive - VDD inactive */
+#define PD_ATTR_ID_FP_PWR_T5 0x19 /* VDD inactive - VDD active */
+#define PD_ATTR_ID_PANEL_DEPTH 0x1A /* Range, 18/24 panel */
+#define PD_ATTR_ID_2_CHANNEL_PANEL 0x1B /* Boolean, dual-channel panel ? */
+#define PD_ATTR_ID_GANG_MODE 0x1C /* Boolean, gang display or not? */
+#define PD_ATTR_ID_GANG_MODE_EVEN_ODD 0x1D /* Boolean, gang display even/odd */
+#define PD_ATTR_ID_REVERSE_DVO_DATA 0x1E /* Request reverse DVO data order */
+#define PD_ATTR_ID_SHARPNESS 0x1F
+#define PD_ATTR_ID_HW_CONFIG 0x20
+#define PD_ATTR_ID_HORZ_FILTER 0x21
+#define PD_ATTR_ID_VERT_FILTER 0x22
+#define PD_ATTR_ID_FB_GAMMA 0x23
+#define PD_ATTR_ID_FB_BRIGHTNESS 0x24
+#define PD_ATTR_ID_FB_CONTRAST 0x25
+#define PD_ATTR_ID_EXTENSION 0x26
+#define PD_ATTR_ID_2D_FLICKER 0x27
+#define PD_ATTR_ID_ADAPTIVE_FLICKER 0x28
+#define PD_ATTR_ID_HORZ_OVERSCAN 0x29
+#define PD_ATTR_ID_VERT_OVERSCAN 0x2A
+#define PD_ATTR_ID_SSC 0x2B
+#define PD_ATTR_ID_DOT_CRAWL 0x2C
+#define PD_ATTR_ID_DITHER 0x2D
+#define PD_ATTR_ID_PANEL_PROTECT_HSYNC 0x2E
+#define PD_ATTR_ID_PANEL_PROTECT_VSYNC 0x2F
+#define PD_ATTR_ID_PANEL_PROTECT_PIXCLK 0x30
+#define PD_ATTR_ID_LVDS_PANEL_TYPE 0x31
+#define PD_ATTR_ID_ANALOG_SRC 0x34
+#define PD_ATTR_ID_SCAN_INFO 0x35
+#define PD_ATTR_ID_PICTURE_ASPECT_RATIO 0x36
+#define PD_ATTR_ID_ACTIVE_FORMAT 0x37
+#define PD_ATTR_ID_GANG_MODE_DVOCLKINV 0x38
+#define PD_ATTR_ID_VGA_2X_IMAGE 0x39
+#define PD_ATTR_ID_TEXT_TUNING 0x3A
+#define PD_ATTR_ID_MAINTAIN_ASPECT_RATIO 0x3B
+#define PD_ATTR_ID_FIXED_TIMING 0x3C
+#define PD_ATTR_ID_COLORIMETRY 0x3D /* HDMI Attributes */
+#define PD_ATTR_ID_PIXEL_REPLICATION 0x3E
+#define PD_ATTR_ID_INTERRUPT_TYPE 0x3F /* sdvo interrupt type */
+/* Port Driver alternative name */
+#define PD_ATTR_ID_PORT_NAME 0x44
+/* Port ddc_reg */
+#define PD_ATTR_ID_PORT_DDC_REG 0x45
+#define PD_ATTR_ID_PWM_INTENSITY 0x46
+#define PD_ATTR_ID_INVERTER_FREQ 0x47
+#define PD_ATTR_ID_BLM_LEGACY_MODE 0x48
+#define PD_ATTR_ID_RB_SWAP_MODE 0x49
+//************ port driver attributes defined for ch7036 port driver **************//
+#define PD_ATTR_ID_HFLIP 0x54
+#define PD_ATTR_ID_VFLIP 0x55
+
+//hdmi audio
+#define PD_ATTR_ID_AUDIO_I2S_FORMAT 0x56
+#define PD_ATTR_ID_AUDIO_I2S_POLARITY 0x57
+#define PD_ATTR_ID_AUDIO_I2S_LENGH 0x58
+
+#define PD_ATTR_ID_AUDIO_TYPE 0x59 //1- I2S, 0: SPDIF
+
+//display mode tables supported by ch7036
+#define PD_ATTR_ID_HDMI_OUT_MODE 0x5A
+#define PD_ATTR_ID_DVI_OUT_MODE 0x5B
+#define PD_ATTR_ID_CRT_OUT_MODE 0x5C
+
+
+#define PD_ATTR_ID_DITHER_BYPASS 0x5D //to bypass Dither block - note: PD_ATTR_ID_DITHER is for dither selection: 18-18, 18-24, etc...
+#define PD_ATTR_ID_EDID_BYPASS 0x5E //1: bypass (use fixed built-in table, 0: read panel EDID)
+
+//1:hdmi, 0: dvi- note: PD_ATTR_ID_HDMI_CHANNEL will be âinactiveâ after EDID reading is
+//implemented and selected, e.g. PD_ATTR_ID_EDID_BYPASS =0
+#define PD_ATTR_ID_HDMI_CHANNEL 0x5F
+#define PD_ATTR_ID_PLL_REF_DLY 0x60
+#define PD_ATTR_ID_PLL_REF_FBDLY 0x61
+#define PD_ATTR_ID_ROTATE 0x62
+#define PD_ATTR_ID_HSCALE_CRT 0x63
+#define PD_ATTR_ID_VSCALE_CRT 0x64
+
+#define PD_ATTR_ID_LOAD_FIRMWARE 0x65
+#define PD_ATTR_ID_REFRESH 0x66
+#define PD_ATTR_ID_DWNSCAL_BYPASS 0x57 //1.2.5.pd: new pd attributes to handle the downscalling quality issue
+
+
+//************ end of ch7036 defined port driver attribute ********** //
+
+#define PD_ATTR_ID_NUM_IDS 0x67 /* Always make this last */
+
+/*! @} */
+
+/* Bit fields. */
+#define PD_ATTR_FLAG_SETMODE 0x01
+#define PD_ATTR_FLAG_VALUE_CHANGED 0x02
+#define PD_ATTR_FLAG_DONT_SET_IMM 0x04
+#define PD_ATTR_FLAG_USER_INVISIBLE 0x08 /* Attr invisible to enduser */
+#define PD_ATTR_FLAG_PD_INVISIBLE 0x10 /* Attr invisible to PD */
+#define PD_ATTR_FLAG_DYNAMIC 0x20 /* Attribute queried from sDVO */
+#define PD_ATTR_FLAG_NOTUSED 0x80 /* Attribute not used, this flag
+ * supercedes all other flags */
+#define PD_ATTR_FLAG_NEED_RESTORE 0x100 /* Reset occured and register value is in limbo.
+ During this time we need to keep
+ the value of the attr in our table
+ unchanged. */
+#define PD_ATTR_FLAG_GENERAL 0x1000 /* This flag is used by HAL to querry
+ * general attributes */
+#define PD_QUERY_GENERAL_ATTR PD_ATTR_ID_NUM_IDS + 2
+/* TVoutput types PD_ATTR_ID_TVOUT_TYPE */
+#define PD_TVOUT_COMPOSITE 0x01
+#define PD_TVOUT_SVIDEO 0x02
+#define PD_TVOUT_COMPONENT 0x03
+#define PD_TVOUT_CPSTSV 0x04 /* Composite and S-Video */
+#define PD_TVOUT_SCARTRGB 0x05 /* SCART output */
+#define PD_TVOUT_VGADAC 0x06 /* VGA Outout */
+
+/* TV Standard Option */
+/* Similar TV formats need to have the same last nibble.
+ * Example for PAL the last nibble is 0x2, for NTSC it is
+ * 0x1 and so forth.
+ */
+#define PD_TV_STD_NTSC_M 0x01 /* USA, 75 IRE Setup */
+#define PD_TV_STD_NTSC_M_J 0x11 /* Japan, 0 IRE Setup */
+#define PD_TV_STD_NTSC_433 0x21
+#define PD_TV_STD_NTSC_N 0x31
+
+#define PD_TV_STD_PAL_B 0x02 /* Australia, U.K., N.Z etc */
+#define PD_TV_STD_PAL_G 0x12
+#define PD_TV_STD_PAL_D 0x22
+#define PD_TV_STD_PAL_H 0x32
+#define PD_TV_STD_PAL_I 0x42
+#define PD_TV_STD_PAL_M 0x52
+#define PD_TV_STD_PAL_N 0x62
+#define PD_TV_STD_PAL_60 0x72
+#define PD_TV_STD_PAL_NC 0x82
+
+#define PD_TV_STD_SECAM_L 0x03 /* France */
+#define PD_TV_STD_SECAM_L1 0x13
+#define PD_TV_STD_SECAM_B 0x23
+#define PD_TV_STD_SECAM_D 0x33
+#define PD_TV_STD_SECAM_G 0x43
+#define PD_TV_STD_SECAM_H 0x53
+#define PD_TV_STD_SECAM_K 0x63
+#define PD_TV_STD_SECAM_K1 0x73
+#define PD_TV_STD_SECAM_60 0x83
+
+#define PD_TV_STD_HDTV_480P 0x04
+#define PD_TV_STD_HDTV_720P 0x14
+#define PD_TV_STD_HDTV_1080I 0x24
+
+/* These HDTV defines are added for Int TV in 915GM */
+#define PD_TV_STD_HDTV_480I_59 0x34 /* 59Hz */
+#define PD_TV_STD_HDTV_480P_59 0x44
+#define PD_TV_STD_HDTV_480P_60 0x54
+
+#define PD_TV_STD_HDTV_576I_50 0x64
+#define PD_TV_STD_HDTV_576P_50 0x74
+
+#define PD_TV_STD_HDTV_720P_50 0x84
+#define PD_TV_STD_HDTV_720P_59 0x94
+#define PD_TV_STD_HDTV_720P_60 0xA4
+
+#define PD_TV_STD_HDTV_1080I_50 0xB4
+#define PD_TV_STD_HDTV_1080I_59 0xC4
+#define PD_TV_STD_HDTV_1080I_60 0xD4
+
+#define PD_TV_STD_HDTV_1080P_60 0xE4
+
+/* Defines for SDVO TV */
+#define PD_HDTV_STD_SMPTE_240M_1080i59 0x101
+#define PD_HDTV_STD_SMPTE_240M_1080i60 0x102
+
+#define PD_HDTV_STD_SMPTE_260M_1080i59 0x103
+#define PD_HDTV_STD_SMPTE_260M_1080i60 0x104
+
+#define PD_HDTV_STD_SMPTE_274M_1080i50 0x105
+#define PD_HDTV_STD_SMPTE_274M_1080i59 0x106
+#define PD_HDTV_STD_SMPTE_274M_1080i60 0x107
+#define PD_HDTV_STD_SMPTE_274M_1080p23 0x108
+#define PD_HDTV_STD_SMPTE_274M_1080p24 0x109
+#define PD_HDTV_STD_SMPTE_274M_1080p25 0x10A
+#define PD_HDTV_STD_SMPTE_274M_1080p29 0x10B
+#define PD_HDTV_STD_SMPTE_274M_1080p30 0x10C
+#define PD_HDTV_STD_SMPTE_274M_1080p50 0x10D
+#define PD_HDTV_STD_SMPTE_274M_1080p59 0x10E
+#define PD_HDTV_STD_SMPTE_274M_1080p60 0x10F
+
+#define PD_HDTV_STD_SMPTE_295M_1080i50 0x110
+#define PD_HDTV_STD_SMPTE_295M_1080p50 0x111
+
+#define PD_HDTV_STD_SMPTE_296M_720p59 0x112
+#define PD_HDTV_STD_SMPTE_296M_720p60 0x113
+#define PD_HDTV_STD_SMPTE_296M_720p50 0x114
+
+#define PD_HDTV_STD_SMPTE_293M_480p59 0x115
+#define PD_HDTV_STD_SMPTE_170M_480i59 0x116
+
+#define PD_HDTV_STD_ITURBT601_576i50 0x117
+#define PD_HDTV_STD_ITURBT601_576p50 0x118
+#define PD_HDTV_STD_EIA_7702A_480i60 0x119
+#define PD_HDTV_STD_EIA_7702A_480p60 0x11A
+
+/* Supported display types */
+/* Port drivers for DVO devices shouldn't use
+ * PD_DISPLAY_CRT,
+ * PD_DISPLAY_TVOUT_INT,
+ * and
+ * PD_DISPLAY_LVDS_INT. These are for internal on board GMCH displays..
+ *
+ * Only following display types are available for port drivers
+ * for DVO devices:
+ * PD_DISPLAY_CRT_EXT
+ * PD_DISPLAY_TVOUT
+ * PD_DISPLAY_TVFP (i.e., PD_DISPLAY_TVOUT|PD_DISPLAY_FP)
+ * PD_DISPLAY_LVDS_EXT
+ * PD_DISPLAY_FP
+ * PD_DISPLAY_RGBA
+ * PD_DISPLAY_DRGB
+ *
+ * Also port drivers can make new combinations, for example,
+ * if an DVO encoder supports both LVDS and TVOut displays, it can use
+ * PD_DISPLAY_LVDS_EXT | PD_DISPLAY_TVOUT
+ */
+#define PD_DISPLAY_CRT 0x00000001 /* GMCH on board CRT */
+#define PD_DISPLAY_TVOUT 0x00000002 /* TVOUT display type */
+#define PD_DISPLAY_FP 0x00000004 /* Flat panel type */
+#define PD_DISPLAY_TVFP 0x00000006 /* Codec supports TV + FP */
+#define PD_DISPLAY_RGBA 0x00000008 /* RGBA display */
+#define PD_DISPLAY_LVDS_EXT 0x00000010 /* External local flat panel */
+#define PD_DISPLAY_LVDS_INT 0x00000020 /* GMCH on board LVDS */
+#define PD_DISPLAY_CRT_EXT 0x00000040 /* External CRT display */
+#define PD_DISPLAY_TVOUT_INT 0x00000080 /* GMCH on board TVout */
+#define PD_DISPLAY_HDMI_INT 0x00000100 /* HDMI on board */
+#define PD_DISPLAY_HDMI_EXT 0x00000200 /* External HDMI */
+#define PD_DISPLAY_DP_INT 0x00000400 /* Display Port on board */
+#define PD_DISPLAY_DRGB 0x00000800 /* SDVO DRGB display */
+/* new display types introduced by LVDS converter chip, CH7036 */
+#define PD_DISPLAY_LVDS_LHDV 0x00001000 /* lvds converter- converts lvds signals to
+ lvds pass-thru, hdmi, dvi, or vga */
+
+
+#ifdef CONFIG_MICRO
+#define PD_MAKE_ATTR(id, type, name, flags, def, cur, a, b, c) \
+ {id, type, flags, def, cur, a, b, c}
+#else
+#define PD_MAKE_ATTR(id, type, name, flags, def, cur, a, b, c) \
+ {id, type, name, flags, def, cur, a, b, c}
+#endif
+
+typedef struct _igd_DID_rotation_info_t {
+ int rotation;
+ int flip;
+} igd_DID_rotation_info_t;
+
+/* IMP NOTE: All below structures should be with same size.
+ * igd_attr_t : General attribute structure
+ * igd_range_attr_t : Range type attribute structure
+ * igd_list_attr_t : List type attribute
+ * igd_list_entry_attr_t : Entry for a list
+ * igd_bool_attr_t : Boolean type attribute
+ * igd_extension_attr_t : Extension type attribute
+ * igd_buffer_attr_t : Buffer type attribute
+ */
+typedef struct _igd_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long default_value;
+ unsigned long current_value;
+ unsigned long _pad0;
+ unsigned long _pad1;
+ unsigned long _pad2;
+}igd_attr_t;
+
+typedef struct _igd_range_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long default_value;
+ unsigned long current_value;
+ unsigned long min;
+ unsigned long max;
+ unsigned long step;
+}igd_range_attr_t;
+
+typedef struct _igd_list_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long default_index;
+ unsigned long current_index;
+ unsigned long num_entries;
+ unsigned long _pad0;
+ unsigned long _pad1;
+}igd_list_attr_t;
+
+typedef struct _igd_list_entry_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long value;
+ unsigned long _pad0;
+ unsigned long _pad1;
+ unsigned long _pad2;
+ unsigned long _pad3;
+}igd_list_entry_attr_t;
+
+typedef struct _igd_bool_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long default_value;
+ unsigned long current_value;
+ unsigned long _pad0;
+ unsigned long _pad1;
+ unsigned long _pad2;
+}igd_bool_attr_t;
+
+typedef struct _igd_buffer_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long buffer_size;
+ void *buffer;
+ unsigned long _pad0;
+ unsigned long _pad1;
+ unsigned long _pad2;
+} igd_buffer_attr_t;
+
+typedef struct _igd_extension_attr {
+ unsigned long id;
+ unsigned long type;
+#ifndef CONFIG_MICRO
+ char name[32];
+#endif
+ unsigned long flags;
+ unsigned long default_value;
+ unsigned long current_value;
+ igd_attr_t *extension;
+} igd_extension_attr_t;
+
+
+/*! @} */
+
+#endif /* _IGD_PD_H_ */
diff --git a/drivers/gpu/drm/emgd/include/igd_pi.h b/drivers/gpu/drm/emgd/include/igd_pi.h
new file mode 100644
index 0000000..bc12a5b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pi.h
@@ -0,0 +1,130 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pi.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_PI_H
+#define _IGD_PI_H
+
+/* Typedefinitions */
+typedef int (*pd_register_p) (void *handle, void *driver);
+typedef void *(*pd_malloc_p)(unsigned long size);
+typedef void *(*pd_memset_p)(void *address, int c, unsigned long size);
+typedef void *(*pd_memcpy_p)(void *dst, void *src, unsigned long size);
+typedef void (*pd_free_p) (void *address);
+typedef void (*pd_usleep_p)(unsigned long usec);
+typedef void (*pd_ui_usleep_p)(unsigned long usec);
+typedef char *(*pd_strcpy_p)(char *dest, char const *src);
+typedef int *(*pd_printf_p)(const char *format, ...);
+typedef int (*pd_check_attr_p)(void *curr, void *in);
+typedef void *(*pd_get_attr_p)(void *attr_list,
+ unsigned long num_attrs, unsigned long attr_id, unsigned long flag);
+typedef void *(*pd_get_igd_debug_p)( void );
+typedef unsigned long *(*pd_get_dropped_debug_messages_p)( void );
+typedef void *(*pd_get_debug_log_mutex_p)( void );
+typedef int (*pd_filter_timings_p)(void *context, void *inlist,
+ void **olist, void *dvo_info, void *display_info);
+
+
+
+/* Data structures to pass callback functions from child to parent */
+typedef struct _igd_main_cb {
+ unsigned long version;
+ pd_register_p pd_register;
+ pd_malloc_p pd_malloc;
+ pd_memset_p pd_memset;
+ pd_memcpy_p pd_memcpy;
+ pd_free_p pd_free;
+ pd_usleep_p pd_usleep;
+ pd_ui_usleep_p pd_ui_usleep;
+ pd_strcpy_p pd_strcpy;
+ pd_check_attr_p pd_check_attr;
+ pd_get_attr_p pd_get_attr;
+ pd_filter_timings_p pd_filter_timings;
+ pd_get_igd_debug_p pd_get_igd_debug;
+ pd_get_debug_log_mutex_p pd_get_debug_log_mutex;
+ pd_get_dropped_debug_messages_p pd_get_dropped_debug_messages;
+} igd_main_cb_t;
+
+typedef struct _igd_dpd_cb {
+ unsigned long version;
+} igd_dpd_cb_t;
+
+
+/* Port driver init and exit function type definitions */
+typedef int (*pd_init_p) (void *);
+typedef int (*pd_exit_p) (void);
+
+/* Function to register with main driver. */
+int igd_pd_register(void *handle, void *pd_driver);
+
+/* Function to allocate memory */
+void *igd_pd_malloc(unsigned long size);
+
+/* Function to set the memory */
+void *igd_pd_memset(void *address, int c, unsigned long size);
+
+/* Function to copy block of memory */
+void *igd_pd_memcpy(void *dst, void *src, unsigned long size);
+
+/* Functions to free memory */
+void igd_pd_free(void *ptr);
+
+/* Function to sleep in micro seconds. This can be called with millisecond
+ * ranges. */
+void igd_pd_usleep(unsigned long usec);
+
+/* Function to sleep in micro seconds uniterrupted. This can be called with millisecond
+ * ranges. */
+void igd_pd_ui_usleep(unsigned long usec);
+
+
+/* Function to do a string copy */
+char *igd_pd_strcpy(char *dest, char const *src);
+
+/* Function to check value of an attribute */
+int igd_pd_check_attr(void *curr, void *in);
+
+/* This function searches for the requested attr_id in the attribute list
+ * and returns the pointer.
+ *
+ * In case of LIST attribute, it will return the proper list entry. */
+void *igd_pd_get_attr(void *attr_list, unsigned long num_attrs,
+ unsigned long attr_id, unsigned long flag);
+
+int igd_pd_filter_timings(
+ void *context,
+ void *ilist,
+ void **olist,
+ void *dvo,
+ void *display);
+
+void *igd_pd_get_igd_debug( void );
+
+#endif /* _IGD_PI_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_pwr.h b/drivers/gpu/drm/emgd/include/igd_pwr.h
new file mode 100644
index 0000000..3564031
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pwr.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pwr.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+
+#ifndef _IGD_PWR_H
+#define _IGD_PWR_H
+
+/*
+ * Device power state defines
+ */
+
+#define IGD_POWERSTATE_D0 0x0
+#define IGD_POWERSTATE_D1 0x1
+#define IGD_POWERSTATE_D2 0x2
+#define IGD_POWERSTATE_D3 0x3
+#define IGD_POWERSTATE_UNDEFINED 0xFFFFFFFF
+
+/*
+ * Graphics Adaptor Power State Defines
+ */
+#define IGD_ADAPTERPOWERSTATE_ON 0x10
+#define IGD_ADAPTERPOWERSTATE_STANDBY 0x11
+#define IGD_ADAPTERPOWERSTATE_SUSPEND 0x12
+#define IGD_ADAPTERPOWERSTATE_OFF 0x13
+#define IGD_ADAPTERPOWERSTATE_HIBERNATE 0x14
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ * int dispatch->pwr_alter(igd_driver_h driver_handle,
+ * unsigned int power_state);
+ *
+ * *----------------------------------------------------------------------
+ */
+
+#endif /*_IGD_PWR_H*/
diff --git a/drivers/gpu/drm/emgd/include/igd_rb.h b/drivers/gpu/drm/emgd/include/igd_rb.h
new file mode 100644
index 0000000..3008870
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_rb.h
@@ -0,0 +1,92 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_rb.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Example Usage:
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_RB_H
+#define _IGD_RB_H
+
+#include <igd_mode.h>
+
+/*
+ * Flags for igd_sync()
+ */
+#define IGD_SYNC_BLOCK 0x00000000
+#define IGD_SYNC_NONBLOCK 0x00000001
+/*
+ * No Flush pipe will not issue an MI Flush before the store dword
+ * There is no guarentee that the store dword will not complete before
+ * an earlier command unless the caller is sure that a store dword alone
+ * is sufficient.
+ */
+#define IGD_SYNC_NOFLUSH_PIPE 0x00000010
+/*
+ * Do not flush the render cache as part of this flush. Map Cache will
+ * be invalidated always.
+ */
+#define IGD_SYNC_NOFLUSH_CACHE 0x00000020
+/* Generate a user Interrupt after the sync completes */
+#define IGD_SYNC_INTERRUPT 0x00000040
+/*
+ * Flush the pipe now but delay the cache flush until the
+ * sync is checked.
+ */
+#define IGD_SYNC_DELAY_FLUSH 0x00000080
+/*
+ * Synchronize queue with video decode engine.
+ */
+#define IGD_SYNC_VIDEO 0x00000100
+
+
+/*!
+ * dispatch->get_sync_slot() returns the offset into the status page where
+ * the sync values can be found for a particular display handle.
+ *
+ * This function is to be used by a priviledged IAL only and requires some
+ * knowledge of the underlying behavior of the sync. The intention of this
+ * function is to allow an IAL that already has device knowledge to
+ * check the status of an issued sync call without calling through the HAL.
+ * In some cases (such as OGL) the address space seperation would otherwise
+ * make sync checking through the HAL a cost prohibitive operation.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ * from a successful call to dispatch->allocate_display().
+ *
+ * @param priority One of the IGD_PRIORITY_* defines. This must match
+ * the define used when issuing the sync. NORMAL priority is the
+ * only common use case.
+ *
+ * @return 0: Success.
+ * @return -IGD_ERROR_INVAL: Otherwise
+ */
+typedef int (*_igd_get_sync_slot_fn_t)(igd_display_h display_handle,
+ unsigned int priority,
+ unsigned int *offset);
+
+#endif /* _IGD_RB_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_render.h b/drivers/gpu/drm/emgd/include/igd_render.h
new file mode 100644
index 0000000..1d89ed4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_render.h
@@ -0,0 +1,573 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_render.h
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is a header file for the Intel GFX commands.
+ * This includes commands specific to Intel hardware and structures specific
+ * to Intel hardware. All other commands and structures are available
+ * through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_RENDER_H
+#define _IGD_RENDER_H
+
+#include <igd_mode.h>
+#include <igd_appcontext.h>
+
+/*
+ * Flags passed to 2d and 3d render functions.
+ * Note: These flags MUST not conflict the the blend flags in igd_blend.h
+ */
+#define IGD_RENDER_BLOCK 0x00000000
+#define IGD_RENDER_NONBLOCK 0x00000001
+/* Render to Framebuffer: Causes a flush afterward */
+#define IGD_RENDER_FRAMEBUFFER 0x00000002
+/* Should this be an immediate blit? */
+#define IGD_RENDER_IMMEDIATE 0x00000004
+/* Render should prevent on-screen tearing */
+#define IGD_RENDER_NOTEAR 0x00000008
+
+/*
+ * Command priority for use with 2d and 3d render functions.
+ */
+#define IGD_PRIORITY_NORMAL 0x0
+#define IGD_PRIORITY_INTERRUPT 0x1
+#define IGD_PRIORITY_POWER 0x2
+#define IGD_PRIORITY_BIN 0x3
+#define IGD_PRIORITY_BB 0x4
+
+
+typedef struct _igd_yuv_coeffs {
+ char ry;
+ char ru;
+ char rv;
+ char gy;
+ char gu;
+ char gv;
+ char by;
+ char bu;
+ char bv;
+
+ short r_const;
+ short g_const;
+ short b_const;
+
+ unsigned char r_shift;
+ unsigned char g_shift;
+ unsigned char b_shift;
+} igd_yuv_coeffs, *pigd_yuv_coeffs;
+
+typedef struct _igd_palette_info {
+ unsigned long *palette;
+ int palette_id;
+ int palette_type;
+ int size;
+
+ igd_yuv_coeffs yuv_coeffs;
+} igd_palette_info_t, *pigd_palette_info_t;
+
+/*
+ *
+ * 2D blit => igd_coord + igd_surface => igd_rect + igd_surface
+ * 3D blend => (igd_rect + igd_surface + igd_rect)*n => igd_rect + igd_surface
+ * Blend: N source surfaces with a source rect.
+ * N destination rects.
+ * 1 Destination surface.
+ * 1 Destination clip rect.
+ */
+
+typedef struct _igd_coord {
+ unsigned int x;
+ unsigned int y;
+} igd_coord_t, *pigd_coord_t;
+
+typedef struct _igd_rect {
+ unsigned int x1;
+ unsigned int y1;
+ unsigned int x2;
+ unsigned int y2;
+} igd_rect_t, *pigd_rect_t;
+
+/*
+ * Direct Display context for video-to-graphics bridge.
+ * (Added here for compatibility between User & Kernel space)
+ * Note: This structure must match EMGDHmiVideoContext.
+ */
+typedef struct _igd_dd_context {
+ unsigned int usage; /* requested display plane */
+ unsigned int screen; /* screen index for video output */
+ unsigned int screen_w; /* width of display screen */
+ unsigned int screen_h; /* height of display screen */
+ unsigned int video_w; /* width of IOH video frame */
+ unsigned int video_h; /* height of IOH video frame */
+ unsigned int video_pitch; /* pitch of IOH video frame */
+ igd_rect_t src; /* video input source rectangle */
+ igd_rect_t dest; /* display output dest rectangle */
+} igd_dd_context_t, *pigd_dd_context_t;
+
+/* planes where reconfiguration and Z-ordering is supported */
+typedef enum _igd_plane_usage {
+ IGD_PLANE_NONE,
+ IGD_PLANE_HMI,
+ IGD_PLANE_X11,
+ IGD_PLANE_OVERLAY_VIDEO,
+ IGD_PLANE_OVERLAY_POPUP,
+ IGD_PLANE_SPRITE_VIDEO,
+ IGD_PLANE_SPRITE_POPUP,
+} igd_plane_usage_t;
+
+typedef struct _igd_buffer_config {
+ igd_plane_usage_t plane; /* usage/ownership of this plane */
+ unsigned long offset; /* surface's GTT offset */
+ int stride; /* surface's stride (in bytes) */
+ igd_rect_t src; /* input source rectangle */
+ igd_rect_t dest; /* display destination rectangle */
+ int extended_screen;
+ int alpha_ena; /* enables/disables constant alpha */
+ int alpha_val; /* constant alpha opacity value */
+ int ckey_ena; /* enables/disables color keying */
+ int ckey_val; /* source color key value */
+} igd_buffer_config_t, *pigd_buffer_config_t;
+
+typedef struct _igd_surface {
+ unsigned long offset;
+ unsigned int pitch;
+ unsigned int width;
+ unsigned int height;
+ unsigned long u_offset; /* Needed for YUV Planar modes. */
+ unsigned int u_pitch; /* Needed for YUV Planar modes. */
+ unsigned long v_offset; /* Needed for YUV Planar modes. */
+ unsigned int v_pitch; /* Needed for YUV Planar modes. */
+ unsigned long pixel_format;
+ igd_palette_info_t *palette_info;
+ unsigned long flags; /* GMM Alignment flags (igd_gmm.h) */
+ unsigned int logic_ops;
+ unsigned int render_ops;
+ unsigned int alpha; /* Global Alpha:
+ * Surface is modulated by alpha prior
+ * to blend. Used with IGD_RENDER_OP_ALPHA.
+ * Used exclusive of diffuse which contains
+ * a full ARGB value.
+ */
+ unsigned int diffuse; /* Diffuse Color:
+ * Use with IGD_RENDER_OP_DIFFUSE.
+ * Used with alpha-only surfaces or
+ * constants color surfaces.
+ */
+ unsigned long chroma_high; /* Drop pixels between low and high */
+ unsigned long chroma_low;
+ unsigned char *virt_addr; /* Virtual memory address to be used for
+ * either Sys Mem to Vid Mem BLT operations
+ * or for per surface virtual memory.
+ */
+ void *pvr2d_mem_info; /* memory information, intended to be used only
+ * by kernel, that allows access to surface memory
+ * from variety of device memory perpectives.
+ */
+
+ void *pvr2d_context_h; /* TODO: This needs to be moved to the appcontext and needs to be
+ accessible by blend */
+
+ unsigned long FlipChainID;
+ void * hPVR2DFlipChain;
+
+ /* TODO: remove floating point use from code used by kernel. who needs this??? */
+ /* We do!! This is how these parameters are passed in to blend.
+ They are not processed on kernel side. */
+ float proc_amp_const[6]; /* Video ProcAmpControl parameter */
+} igd_surface_t, *pigd_surface_t;
+
+typedef struct _igd_surface_list {
+ unsigned long offset;
+ unsigned long size;
+} igd_surface_list_t, *pigd_surface_list_t;
+
+/*!
+ * @name Surface Render Ops
+ * @anchor render_ops
+ *
+ * These flags apply to a surface and indicate features of the surface
+ * that should be considered during render operations such as
+ * _igd_dispatch::blend()
+ *
+ * - IGD_RENDER_OP_BLEND: This surface should be blended with other
+ * surfaces during rendering. In calls to _igd_dispatch::blend() this
+ * surface will blend with those below it in the stack or the destination
+ * surface (when the surface is the bottom-most in the stack).
+ * Note: xRGB surfaces used with this render op will convert to ARGB
+ * surfaces with an alpha of 1.0. Without this render op xRGB surfaces
+ * will preserve the x value from the source.
+ *
+ * - IGD_RENDER_OP_PREMULT: The surface contains a pre-multipled alpha
+ * value. This indicates that the per-pixel color values have already been
+ * multipled by the per-pixel alpha value. Without this bit set it is
+ * necessary to perform this multiplication as part of a blend operation.
+ *
+ * - IGD_RENDER_OP_ALPHA: The surface contains a global alpha. All pixel
+ * values are multiplied against the global alpha as part of any blend
+ * operation. Global alpha is used exclusive of Diffuse color.
+ *
+ * - IGD_RENDER_OP_DIFFUSE: The surface contains a single diffuse color.
+ * This flag is used with alpha-only surfaces or surfaces of constant
+ * color. Diffuse is used exclusively of Global Alpha.
+ *
+ * - IGD_RENDER_OP_CHROMA: THe surface contains a chroma-key. Pixel
+ * values between chroma_high and chroma_low will be filtered out.
+ *
+ * - IGD_RENDER_OP_COLORKEY: The surface contains a colorkey. This is used
+ * on mask surfaces to indicate the location of pixels that may be drawn
+ * on the destination. Only pixels with values between chroma_high and
+ * chroma_low should "pass through" the mask to the destination. Other pixels
+ * will be filered out.
+ *
+ * @{
+ */
+
+#define IGD_RENDER_OP_BLEND 0x1
+#define IGD_RENDER_OP_PREMULT 0x2
+#define IGD_RENDER_OP_ALPHA 0x4
+#define IGD_RENDER_OP_DIFFUSE 0x8
+#define IGD_RENDER_OP_CHROMA 0x20
+#define IGD_RENDER_OP_COLORKEY 0x40
+
+/*
+ * Make sure rotate and flip flags are not moved. Blend uses them as
+ * array indexes
+ */
+#define IGD_RENDER_OP_ROT_MASK 0x000300
+#define IGD_RENDER_OP_ROT_0 0x000000
+#define IGD_RENDER_OP_ROT_90 0x000100
+#define IGD_RENDER_OP_ROT_180 0x000200
+#define IGD_RENDER_OP_ROT_270 0x000300
+#define IGD_RENDER_OP_FLIP 0x000400
+#define IGD_RENDER_OP_SKIP_ROT 0x000800
+#define IGD_RENDER_OP_SKIP_FLIP 0x008000
+
+/*
+ * flags for post process - Deinterlacing and ProcAmpControl.
+ */
+#define IGD_RENDER_OP_INTERLACED 0x00001000
+#define IGD_RENDER_OP_BOB_EVEN 0x00002000
+#define IGD_RENDER_OP_BOB_ODD 0x00004000
+#define IGD_RENDER_OP_PROCAMP 0x00010000
+
+/*
+ * Region structure. Holds information about non-surface memory
+ * allocations.
+ */
+
+#define IGD_REGION_UNFINISHED 0x00000000
+#define IGD_REGION_READY 0x00000001
+#define IGD_REGION_QUEUED 0x00000002
+#define IGD_REGION_ABANDONED 0x00000004
+
+typedef struct _igd_region {
+ unsigned long offset;
+ char *virt;
+ unsigned long size;
+ unsigned long type;
+ unsigned long flags;
+} igd_region_t;
+/* @} */
+
+typedef struct _igd_dma {
+ unsigned long offset;
+ char *virt;
+ unsigned long size;
+ unsigned long head;
+ unsigned long flags;
+ /* unsigned long phys;
+ - currently not used - maybe needed in future */
+} igd_dma_t;
+
+/*
+ * Functions for setting/getting the surface information for the
+ * Display, Color, Depth, and Aux buffers for a display.
+ */
+typedef enum _igd_buffertype {
+ IGD_BUFFER_DISPLAY = 0,
+ IGD_BUFFER_COLOR,
+ IGD_BUFFER_DEPTH,
+ IGD_BUFFER_SAVE
+} igd_buffertype_t;
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_get_suface_fn_t
+ *
+ * Description:
+ * This function, available from the top-level igd_dispatch_t as
+ * get_surface(), allows the client to query the parameters for
+ * the display, color, depth, and aux buffers for a given display.
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display.
+ *
+ * type - One of the igd_buffertype_t enums.
+ *
+ * surface - An igd_surface_t to return the information in.
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_get_surface_fn_t)(
+ igd_display_h display_handle,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext);
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_set_suface_fn_t
+ *
+ * Description:
+ * This function, available from the top-level igd_dispatch_t as
+ * set_surface(), allows the client to set the parameters for
+ * the display, color, and depth buffers for a given display.
+ *
+ * This command will happen asynchronously when possible. It will
+ * be placed in the command stream and will happen at some point
+ * after the command is parsed (The next vblank if it is the display
+ * buffer)
+ *
+ * When setting the depth buffer the setting will not take place
+ * until the next color buffer set. Therefore when changing the
+ * color buffer the depth buffer should always be changed first.
+ *
+ * If set_surface has been used to change the displayed surface, the
+ * original framebuffer should be replaced before changing modes.
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display.
+ *
+ * priority - The priority for the command.
+ *
+ * type - One of the igd_buffertype_t enums.
+ *
+ * flags - Additional bitfield of options for buffer.
+ *
+ * surface - An igd_surface_t that contains the parameters to apply.
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+#define IGD_BUFFER_ZERO_BIAS 0x1
+#define IGD_BUFFER_FIXED_Z 0x2
+#define IGD_BUFFER_ASYNC 0x4
+/* Issue a Wait for last flip only, do not flip again */
+#define IGD_BUFFER_WAIT 0x8
+/* Do not pan */
+#define IGD_BUFFER_NO_PAN 0x10
+
+/* ------ WARNING!!!! Read Before Changing ------ */
+/* Command should always be 32 Bit on all platforms including 64 bit */
+/* Int is assumed to be 32 bit on all the supported platforms */
+typedef unsigned int igd_command_t;
+
+typedef int (*_igd_set_surface_fn_t)(
+ igd_display_h display_handle,
+ int priority,
+ igd_buffertype_t type,
+ igd_surface_t *surface,
+ igd_appcontext_h appcontext,
+ unsigned long flags);
+
+typedef enum _igd_event {
+ IGD_EVENT_FLIP_PENDING = 1
+} igd_event_t;
+
+typedef int (*_igd_query_event_fn_t)(
+ igd_display_h display_handle,
+ igd_event_t event,
+ unsigned long *status);
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_alloc_ring_fn_t
+ *
+ * Description:
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display.
+ *
+ * flags - IGD_ALLOC_PRIORITY_*
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_alloc_ring_fn_t)(
+ igd_display_h display_handle,
+ unsigned long flags);
+
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_exec_buffer_fn_t
+ *
+ * Description:
+ * This function allows a privelidged IAL to place instructions directly
+ * into the HAL's command queue. Under normal circumstances an IAL does not
+ * have the knowledge necessary to do this; however, some IALs (D3D, OGL, MC)
+ * will have this knowledge. The contents referenced by the data parameter
+ * are device dependent and may be a data structure or other structured
+ * information.
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display.
+ *
+ * priority - The priority for the command.
+ *
+ * data - Pointer to the device dependent command data or data strucutre.
+ *
+ * size - Size in Dwords (4bytes).
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_exec_buffer_fn_t)(
+ igd_display_h display_handle,
+ int priority,
+ igd_appcontext_h appcontext,
+ const void *data,
+ unsigned long size);
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_query_buffer_fn_t
+ *
+ * Description:
+ * This function allows a privelidged IAL to query Topaz/MSVDX.
+ * Under normal circumstances an IAL does not have the knowledge
+ * necessary to do this; however, some IALs (D3D, OGL, MC)
+ * will have this knowledge. The contents referenced by the data parameter
+ * are device dependent and may be a data structure or other structured
+ * information.
+ *
+ * Parameters:
+ * in_size - in parameter size.
+ *
+ * in_buffer - input buffer.
+ *
+ * out_size - out parameter size.
+ *
+ * out_buffer - output buffer.
+ *
+ * command - query command.
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_query_buffer_fn_t) (
+ igd_display_h display_handle,
+ void *in_buffer,
+ void *out_buffer,
+ unsigned long command);
+
+/*
+ * Flags passed to (exclusive) igd_rb_reserve
+ * and igd_rb_update functions.
+ */
+#define IGD_RB_RESERVE_BLOCK 0x00000000
+#define IGD_RB_RESERVE_NONBLOCK 0x00000001
+#define IGD_RB_CACHELINE_PAD 0x00000002
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_rb_reserve_fn_t
+ *
+ * Description:
+ * This function allows a privelidged IAL to aquire space directly on
+ * the HAL's ring buffer. Under normal circumstances an IAL does not have
+ * the knowledge necessary to do this; however, some IALs (D3D, OGL, MC)
+ * will have this knowledge.
+ * Any IAL making use of this interface must have full knowledge of all
+ * hardware interactions, padding etc that are needed to safely access
+ * the ring directly.
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display.
+ *
+ * priority - The priority for the command.
+ *
+ * size - Size in Dwords (4bytes).
+ * Setting size to 0 will re-initialize the ring.
+ *
+ * block - Blocking or not 1 or 0
+ *
+ * addr - Virtual address returned from the call. Caller should begin
+ * writing commands at this address.
+ *
+ * avail - The amount (in dwords) of space that is available in the
+ * ring. This is just a hint in case it is helpful to the IAL.
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_rb_reserve_fn_t)(
+ igd_display_h display_handle,
+ int priority,
+ unsigned long size,
+ unsigned long flags,
+ igd_command_t **addr,
+ unsigned long *avail);
+
+/*----------------------------------------------------------------------
+ * Typedef: _igd_rb_update_fn_t
+ *
+ * Description:
+ * This function updates the ring pointer after a call to rb_reserve,
+ * and after the command data has been placed in the ring.
+ *
+ * Parameters:
+ * display_handle - Handle for the requested display. Must be the same
+ * display used with rb_reserve.
+ *
+ * priority - The priority for the command. Must be the same priority
+ * used with rb_reserve.
+ *
+ * addr - Virtual address after placing the commands into the ring. This
+ * should be equal to the returned addr + size from rb_reserve.
+ *
+ * Returns:
+ * 0: Success
+ * < 0: Error
+ *----------------------------------------------------------------------
+ */
+typedef int (*_igd_rb_update_fn_t)(
+ igd_display_h display_handle,
+ int priority,
+ igd_command_t *addr,
+ unsigned long flags);
+
+
+#endif /* _IGD_RENDER_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_reset.h b/drivers/gpu/drm/emgd/include/igd_reset.h
new file mode 100644
index 0000000..6150b6c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_reset.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_reset.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This is the external header file for the reset module. It should be included
+ * by above IAL for reset functionality on the ssigd HAL layers.
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_RESET_H
+#define _IGD_RESET_H
+
+
+/*----------------------------------------------------------------------------
+ * Function:
+ * int dispatch->reset_alter(igd_driver_h driver_handle);
+ *
+ * Description:
+ * .
+ * Parameters:
+ * driver_handle - pointer to main driver context structure.
+ *
+ * Return:
+ * !0: Pointer to a ring buffer structure upon successful allocation
+ * 0: A ring buffer of specified type can not be allocated, or an
+ * error occurred during memory allocation for the buffer.
+ *----------------------------------------------------------------------------
+ */
+
+
+#endif /*_IGD_RESET_H*/
diff --git a/drivers/gpu/drm/emgd/include/igd_version.h b/drivers/gpu/drm/emgd/include/igd_version.h
new file mode 100644
index 0000000..0b192a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_version.h
@@ -0,0 +1,41 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_version.h
+ * $Revision: 1.237 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains igd version number information. The build number
+ * is updated by the automated build process, DO NOT EDIT MANUALLY.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_VERSION_H
+#define _IGD_VERSION_H
+
+#define IGD_MAJOR_NUM 1
+#define IGD_MINOR_NUM 18
+#define IGD_BUILD_NUM 3398
+
+#define IGD_PCF_VERSION 0x00000400
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_vga.h b/drivers/gpu/drm/emgd/include/igd_vga.h
new file mode 100644
index 0000000..1f232f0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_vga.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_vga.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * Header file for common VGA registers and macros.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_VGA_H
+#define _IGD_VGA_H
+
+#ifdef CONFIG_MICRO
+#define VB_CODE_SEG __based( __segname("_CODE"))
+#else
+#define VB_CODE_SEG
+#endif
+
+/* The Maximum VGA Mode Number as specified in the IGD Mode Table. */
+#define VGA_MODE_NUM_MAX 0x1C
+
+typedef struct vga_mode_data {
+ unsigned char cols;
+ unsigned char rows; /* #rows-1 */
+ unsigned char char_height;
+ unsigned short video_buff_size;
+ unsigned char sr_regs[4];
+ unsigned char misc_reg;
+ unsigned char crtc_regs[25];
+ unsigned char ar_regs[20];
+ unsigned char gr_regs[9];
+} vga_mode_data_t;
+
+/* This contains the VGA Mode Table. A ptr to this exists in the
+ * Environment. */
+extern vga_mode_data_t VB_CODE_SEG vga_mode_data[];
+
+/* This contains a pointer to the VGA Mode_Table. This is necessary, so
+ * vga_mode.c can use this to program the mode, incase the user has
+ * changed the Environment Table. */
+extern vga_mode_data_t FAR (*vga_mode_data_ptr)[];
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/io.h b/drivers/gpu/drm/emgd/include/io.h
new file mode 100644
index 0000000..9b534df
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/io.h
@@ -0,0 +1,422 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: io.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains Linux user-space implementations for the OAL io.h
+ * abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <config.h>
+#include <igd_debug.h>
+
+
+#ifndef _OAL_LINUX_KERNEL_IO_H
+#define _OAL_LINUX_KERNEL_IO_H
+
+extern unsigned long _os_read_port8(unsigned long port);
+extern void _os_write_port8(unsigned long port, unsigned char value);
+extern unsigned long _os_read_port16(unsigned long port);
+extern void _os_write_port16(unsigned long port, unsigned short value);
+extern unsigned long _os_read_port32(unsigned long port);
+extern void _os_write_port32(unsigned long port, unsigned long value);
+
+/*
+ * Debug macros rely on the existence of emgd_debug pointer. It is defined
+ * in the HAL. If an IAL wishes to use the print routines and is not
+ * linked with the HAL it will need to provide an emgd_debug pointer.
+ */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+
+/*
+ * All files including io.h should define MODULE_NAME to be a bit
+ * within the emgd_debug_t data structure. If MODULE_NAME is not defined
+ * debug printing will be controlled by the global "debug" bit rather
+ * than a per-module bit.
+ */
+#ifndef MODULE_NAME
+#define MODULE_NAME hal.debug
+#endif
+
+/*
+ * Debug Print Macros use os_get_funcname to get the name of the
+ * function they are in. They cannot rely on __func__ alone because
+ * the function name may be overridden by the caller.
+ *
+ * If the caller wants to override the printed function name they may
+ * call os_set_funcname prior to each call to EMGD_DEBUG/ERROR/TRACE.
+ */
+static const char *_os_override_funcname = NULL;
+
+static __inline int os_set_funcname( const char *name )
+{
+ _os_override_funcname = name;
+ return 1;
+}
+
+static __inline const char *os_get_funcname( const char *name )
+{
+ const char *ret;
+ ret = (_os_override_funcname)?_os_override_funcname:name;
+ _os_override_funcname = NULL;
+ return ret;
+}
+
+
+
+/*
+ * EMGD_ERROR()
+ * Printing with EMGD_ERROR will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_ERROR printing is used for
+ * driver errors that should not happen under normal operation. As such,
+ * these messages cannot be disabled at runtime.
+ *
+ * All OAL implementations should result in EMGD_ERROR messsages in the
+ * following format:
+ * <OPTIONAL OS ERROR PREFIX> FUNCTION_NAME Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_ERROR
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_ERROR(...) \
+ do { \
+ printk(KERN_ERR "%s ERROR: ", __FUNCTION__); \
+ printk(__VA_ARGS__); \
+ printk("\n"); \
+ /*fflush(stderr);*/ \
+ } while(0);
+#else
+#define EMGD_ERROR(...) do {} while(0)
+#endif
+#endif
+
+
+/* The CONFIG_USE_INFO_PRIORITY macro is #define'd in "config.h" */
+#ifdef CONFIG_USE_INFO_PRIORITY
+#define EMGD_DEBUG_MSG_PRIORITY KERN_INFO
+#else
+#define EMGD_DEBUG_MSG_PRIORITY KERN_DEBUG
+#endif
+
+/*
+ * EMGD_DEBUG()
+ * Printing with EMGD_DEBUG will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_DEBUG printing is used for
+ * debug messages that give information useful for debugging problems.
+ * EMGD_DEBUG messages can be enabled/disabled at compile time and runtime
+ * on a per-module basis.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ * default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ * the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_DEBUG messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_DEBUG
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_DEBUG(...) if(emgd_debug &&emgd_debug-> MODULE_NAME) \
+ do { \
+ printk(EMGD_DEBUG_MSG_PRIORITY "[EMGD_DEBUG] %s ", __FUNCTION__); \
+ printk(__VA_ARGS__); \
+ printk("\n"); \
+ /*fflush(stdout);*/ \
+ } while(0);
+#else
+#define EMGD_DEBUG(...) do {} while(0)
+#endif
+#endif
+
+/*
+ * EMGD_DEBUG_S()
+ * Printing with EMGD_DEBUG_S will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_DEBUG_S printing is used for
+ * debug messages that give information useful for debugging problems in
+ * a shortened form (used by the HAL for multi-line prints).
+ * EMGD_DEBUG_S messages can be enabled/disabled at compile time and runtime
+ * on a per-module basis.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ * default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ * the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_DEBUG_S messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_DEBUG_S
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_DEBUG_S(...) if(emgd_debug && emgd_debug-> MODULE_NAME) \
+ do { \
+ printk(EMGD_DEBUG_MSG_PRIORITY __VA_ARGS__); \
+ printk("\n"); \
+ /* fflush(stdout);*/ \
+ } while(0);
+#else
+#define EMGD_DEBUG_S(...) do {} while(0)
+#endif
+#endif
+
+/*
+ * EMGD_TRACE_ENTER
+ * Tracing with EMGD_TRACE_ENTER will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_TRACE_ENTER will print a fixed
+ * "Enter" message when entering a function.
+ * EMGD_TRACE_ENTER messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ * default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ * the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_TRACE_ENTER messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name ENTER
+ */
+#ifndef EMGD_TRACE_ENTER
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_TRACE_ENTER if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("ENTER")
+#else
+#define EMGD_TRACE_ENTER
+#endif
+#endif
+
+/*
+ * EMGD_TRACE_EXIT
+ * Tracing with EMGD_TRACE_EXIT will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_TRACE_EXIT will print a fixed
+ * "Exit" message when exiting a function without error.
+ * EMGD_TRACE_EXIT messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ * default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ * the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_TRACE_EXIT messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name EXIT
+ */
+#ifndef EMGD_TRACE_EXIT
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_TRACE_EXIT if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("EXIT")
+#else
+#define EMGD_TRACE_EXIT
+#endif
+#endif
+
+/*
+ * EMGD_ERROR_EXIT()
+ * Tracing with EMGD_ERROR_EXIT will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_ERROR_EXIT will print an error
+ * as well as a fixed "Exit" message when exiting a function without error.
+ * EMGD_ERROR_EXIT messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Note: Only the Tracing message can be disabled, the error message will
+ * still print as with EMGD_ERROR().
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ * default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ * the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_ERROR_EXIT messsages in the
+ * following format:
+ * <OPTIONAL OS ERROR PREFIX> function_name EXIT Message
+ */
+#ifndef EMGD_ERROR_EXIT
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_ERROR_EXIT \
+ if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("EXIT With Error..."); \
+ EMGD_ERROR
+#else
+#define EMGD_ERROR_EXIT(...) do {} while(0)
+#endif
+#endif
+
+
+/*
+ * EMGD_VERBOSE()
+ * Verbose printing that is useful only when debugging specific problems
+ * or contains lots of text should be implemented in a single function and
+ * called from within the EMGD_VERBOSE macro. The default and runtime
+ * control of this output can be altered by changing the value of the
+ * global emgd_debug->verbose.
+ */
+#ifndef EMGD_VERBOSE
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_VERBOSE(opt, func) if(emgd_debug-> opt) func;
+#else
+#define EMGD_VERBOSE(opt, func)
+#endif
+#endif
+
+/*
+ * EMGD_ASSERT( Statement, Message, Error Code)
+ * EMGD_ASSERT should be used to verify the values of statements that
+ * should always be true. EMGD_ASSERT will generate code only in debug drivers
+ * and therefore should only be used for things that should never be false
+ * in production drivers. For example, testing for null parameters in
+ * an internal interface.
+ *
+ * Usage: EMGD_ASSERT(char_ptr, "Char Pointer is NULL", -IGD_ERROR_INVAL)
+ * Usage: EMGD_ASSERT(char_ptr, "Char Pointer is NULL", )
+ */
+#ifndef EMGD_ASSERT
+#ifdef EMGD_DEBUG
+#define EMGD_ASSERT(a, m, e) if(!(a)) { EMGD_ERROR_EXIT("ASSERT: " m); return e; }
+#else
+#define EMGD_ASSERT(a, m, e)
+#endif
+#endif
+
+/*
+ * This macro _may_ be defined by an OAL port to modify the mmio
+ * base address prior to use. Commonly this is used to make the base
+ * address 0 to remove code for vbios.
+ */
+#ifdef _EMGD_MMIO
+#define EMGD_MMIO(a) _EMGD_MMIO(a)
+#else
+#define EMGD_MMIO(a) a
+#endif
+
+
+
+#define EMGD_READ32(addr) *(volatile unsigned int *)(addr)
+#define EMGD_WRITE32(value, addr) \
+ (*(volatile unsigned long *)(addr) = (value))
+/* EMGD_DEBUG ("EMGD_WRITE32: 0x%p=0x%lx\n", (addr), (value)); \*/
+
+#define EMGD_READ8(addr) *(volatile unsigned char *)(addr)
+#define EMGD_WRITE8(value, addr) \
+ (*(volatile unsigned char *)(addr) = (value))
+/* EMGD_DEBUG ("EMGD_WRITE8: 0x%p=0x%x\n", (addr), (value)); \*/
+
+
+/* PORT IO Macros */
+#if 0
+// user mode. To be removed.
+#define _EMGD_READ_PORT8(port) _os_read_port8(port)
+#define _EMGD_WRITE_PORT8(port, value) _os_write_port8(port, value)
+
+#define _EMGD_READ_PORT16(port) _os_read_port16(port)
+#define _EMGD_WRITE_PORT16(port, value) _os_write_port16(port, value)
+
+#define _EMGD_READ_PORT32(port) _os_read_port32(port)
+#define _EMGD_WRITE_PORT32(port, value) _os_write_port32(port, value)
+#else
+// Linux kernel mode port I/O
+#define EMGD_READ_PORT8(port) inb(port)
+#define EMGD_WRITE_PORT8(port, value) outb(value, port)
+
+#define EMGD_READ_PORT16(port) inw(port)
+#define EMGD_WRITE_PORT16(port, value) outw(value, port)
+
+#define EMGD_READ_PORT32(port) inl(port)
+#define EMGD_WRITE_PORT32(port, value) outl(value, port)
+#endif
+
+#ifdef DEBUG_MEM
+extern unsigned long global_virt_mmadr;
+extern unsigned long global_virt_mmadr_offset;
+
+static __inline *(volatile unsigned int *) _EMGD_READ32(unsigned int addr)
+{
+ if ((addr < 0x10100000) && (addr > 0x10000000)) {
+ return *(volatile unsigned int *)(addr+global_virt_mmadr-global_virt_mmadr_offset);
+ } else {
+ return *(volatile unsigned int *)(addr);
+ }
+}
+
+static __inline void _EMGD_WRITE32(unsigned int value, unsigned int addr) \
+{
+ if ((addr < 0x10100000) && (addr > 0x10000000)) {
+ *(volatile unsigned int *)(addr+global_virt_mmadr-global_virt_mmadr_offset) = value;
+ } else {
+ *(volatile unsigned int *)addr = value;
+ }
+ printf("EMGD_WRITE32: *0x%x = 0x%x\n", addr, value);
+}
+
+static __inline *(volatile unsigned char *) _EMGD_READ8(unsigned int addr)
+{
+ if ((addr < 0x10100000) && (addr > 0x10000000)) {
+ return *(volatile unsigned char *)(addr+global_virt_mmadr-global_virt_mmadr_offset);
+ } else {
+ return *(volatile unsigned char *)addr;
+ }
+}
+
+static __inline void _EMGD_WRITE8(unsigned char value, unsigned int addr) \
+{
+ if ((addr < 0x10100000) && (addr > 0x10000000)) {
+ (*(volatile unsigned char *)(addr+global_virt_mmadr-global_virt_mmadr_offset) = value);
+ } else {
+ (*(volatile unsigned char *)(addr) = value);
+ }
+ printf("EMGD_WRITE8: *0x%x = 0x%c\n", addr, value);
+}
+#endif /* DEBUG_MEM */
+
+#define EMGD_PTR_TO_ULONG(ptr) (ptr)
+#define EMGD_ULONG_TO_PTR(ulong) (ulong)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/memmap.h b/drivers/gpu/drm/emgd/include/memmap.h
new file mode 100644
index 0000000..a02e943
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/memmap.h
@@ -0,0 +1,104 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ * This file contains OS abstractions for memory mapping of bus addresses.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_IO_MEMMAP_H
+#define _OAL_IO_MEMMAP_H
+
+void * os_map_io_to_mem_cache(
+ unsigned long base_address,
+ unsigned long size);
+void * os_map_io_to_mem_nocache(
+ unsigned long base_address,
+ unsigned long size);
+void os_unmap_io_from_mem(
+ void * virt_addr,
+ unsigned long size);
+
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ * This function will reserve a range of virtual memory space of "size" and
+ * map the that virtual address to the hardware "base_address" provided. This
+ * function call will enable caching of read write transactions to the region.
+ * Parameters:
+ * IN: base_address -> the base bus/hardware address that will be
+ * used as the target of the memory mapping.
+ * IN: size-> the size of the virtual memory range requested to
+ * be mapped
+ * Return Value:
+ * NULL for failure OR
+ * valid virtual address casted as a void *
+ *
+ ****************************************************************************/
+#define OS_MAP_IO_TO_MEM_CACHE(a, b) os_map_io_to_mem_cache(a, b)
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ * This function will reserve a range of virtual memory space of "size" and
+ * map the that virtual address to the hardware "base_address" provided. This
+ * function call will NOT cache any read/write transactions to the region and
+ * apply the access directly to the hardware bus address that is mapped.
+ * Parameters:
+ * IN: base_address -> the base bus/hardware address that will be
+ * used as the target of the memory mapping.
+ * IN: size-> the size of the virtual memory range requested to
+ * be mapped
+ * Return Value:
+ * NULL for failure OR
+ * valid virtual address casted as a void *
+ *
+ ****************************************************************************/
+#define OS_MAP_IO_TO_MEM_NOCACHE(a, b) os_map_io_to_mem_nocache(a, b)
+#define OS_MAP_IO_TO_LARGE_MEM_NOCACHE(a, b) os_map_io_to_mem_nocache(a, b)
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ * This function will unmap the range of virtual memory space of "size" that
+ * was previously mapped with any of the above functions.
+ * Parameters:
+ * IN: virt_address -> the base bus or hardware address that will
+ * be used as the target of the memory
+ * mapping.
+ * IN: size-> the size of the virtual memory range as requested in
+ * os_map_io*
+ * Return Value:
+ * none (N/A)
+ *
+ ****************************************************************************/
+#define OS_UNMAP_IO_FROM_MEM(a, b) os_unmap_io_from_mem(a, b)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h b/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
new file mode 100644
index 0000000..0527e7b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
@@ -0,0 +1,263 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#include "ioctldef.h"
+
+#define DEBUG_CAPMODE_FRAMED 0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS 0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY 0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG 0x00000001UL
+#define DEBUG_OUTMODE_MONO 0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE 0x00000004UL
+#define DEBUG_OUTMODE_ASYNC 0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA 0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM 0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION 0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE 0x00000004UL
+
+#define DEBUG_FLAGS_TEXTSTREAM 0x80000000UL
+
+#define DEBUG_LEVEL_0 0x00000001UL
+#define DEBUG_LEVEL_1 0x00000003UL
+#define DEBUG_LEVEL_2 0x00000007UL
+#define DEBUG_LEVEL_3 0x0000000FUL
+#define DEBUG_LEVEL_4 0x0000001FUL
+#define DEBUG_LEVEL_5 0x0000003FUL
+#define DEBUG_LEVEL_6 0x0000007FUL
+#define DEBUG_LEVEL_7 0x000000FFUL
+#define DEBUG_LEVEL_8 0x000001FFUL
+#define DEBUG_LEVEL_9 0x000003FFUL
+#define DEBUG_LEVEL_10 0x000007FFUL
+#define DEBUG_LEVEL_11 0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0 0x00000001UL
+#define DEBUG_LEVEL_SEL1 0x00000002UL
+#define DEBUG_LEVEL_SEL2 0x00000004UL
+#define DEBUG_LEVEL_SEL3 0x00000008UL
+#define DEBUG_LEVEL_SEL4 0x00000010UL
+#define DEBUG_LEVEL_SEL5 0x00000020UL
+#define DEBUG_LEVEL_SEL6 0x00000040UL
+#define DEBUG_LEVEL_SEL7 0x00000080UL
+#define DEBUG_LEVEL_SEL8 0x00000100UL
+#define DEBUG_LEVEL_SEL9 0x00000200UL
+#define DEBUG_LEVEL_SEL10 0x00000400UL
+#define DEBUG_LEVEL_SEL11 0x00000800UL
+
+#define DEBUG_SERVICE_IOCTL_BASE 0x800UL
+#define DEBUG_SERVICE_CREATESTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2 CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+ DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+typedef struct _DBG_IN_CREATESTREAM_
+{
+ IMG_UINT32 ui32Pages;
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+ IMG_CHAR *pszName;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+ IMG_BOOL bResetStream;
+ IMG_CHAR *pszName;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Level;
+ IMG_CHAR *pszString;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32StringLen;
+ IMG_CHAR *pszString;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Mode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32TransferSize;
+ IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+ IMG_VOID *pvStream;
+ IMG_BOOL bReadInitBuffer;
+ IMG_UINT32 ui32OutBufferSize;
+ IMG_UINT8 *pui8OutBuffer;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+ IMG_VOID *pvStream;
+ IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+ IMG_UINT32 ui32Flags;
+ IMG_VOID *pvStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32BufferSize;
+ IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+#define WRITELF_FLAGS_RESETBUF 0x00000001UL
+
+typedef struct _DBG_STREAM_
+{
+ struct _DBG_STREAM_ *psNext;
+ struct _DBG_STREAM_ *psInitStream;
+ IMG_BOOL bInitPhaseComplete;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32Base;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32RPtr;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT32 ui32DataWritten;
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+ IMG_UINT32 ui32DebugLevel;
+ IMG_UINT32 ui32DefaultMode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32Current;
+ IMG_UINT32 ui32Access;
+ IMG_UINT32 ui32SampleRate;
+ IMG_UINT32 ui32Reserved;
+ IMG_UINT32 ui32Timeout;
+ IMG_UINT32 ui32Marker;
+ IMG_CHAR szName[30];
+} DBG_STREAM,*PDBG_STREAM;
+
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+ IMG_UINT32 ui32Size;
+ IMG_VOID * (IMG_CALLCONV *pfnCreateStream) (IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+ IMG_VOID (IMG_CALLCONV *pfnDestroyStream) (PDBG_STREAM psStream);
+ IMG_VOID * (IMG_CALLCONV *pfnFindStream) (IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBIN) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadBIN) (PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+ IMG_VOID (IMG_CALLCONV *pfnSetCaptureMode) (PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+ IMG_VOID (IMG_CALLCONV *pfnSetOutputMode) (PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+ IMG_VOID (IMG_CALLCONV *pfnSetDebugLevel) (PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+ IMG_VOID (IMG_CALLCONV *pfnSetFrame) (PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnOverrideMode) (PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+ IMG_VOID (IMG_CALLCONV *pfnDefaultMode) (PDBG_STREAM psStream);
+ IMG_UINT32 (IMG_CALLCONV *pfnDBGDrivWrite2) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteStringCM) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBINCM) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_VOID (IMG_CALLCONV *pfnSetMarker) (PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetMarker) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStartInitPhase) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStopInitPhase) (PDBG_STREAM psStream);
+ IMG_BOOL (IMG_CALLCONV *pfnIsCaptureFrame) (PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteLF) (PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadLF) (PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetStreamOffset) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnSetStreamOffset) (PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+ IMG_BOOL (IMG_CALLCONV *pfnIsLastCaptureFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnWaitForEvent) (DBG_EVENT eEvent);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/img_defs.h b/drivers/gpu/drm/emgd/pvr/include4/img_defs.h
new file mode 100644
index 0000000..454a68f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/img_defs.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef enum img_tag_TriStateSwitch
+{
+ IMG_ON = 0x00,
+ IMG_OFF,
+ IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define IMG_SUCCESS 0
+
+#define IMG_NO_REG 1
+
+#if defined (NO_INLINE_FUNCS)
+ #define INLINE
+ #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+ #define INLINE inline
+ #define FORCE_INLINE inline
+#else
+#if !defined(INLINE)
+ #define INLINE __inline
+#endif
+ #define FORCE_INLINE static __inline
+#endif
+#endif
+
+
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short TCHAR, *PTCHAR, *PTSTR;
+#else
+typedef char TCHAR, *PTCHAR, *PTSTR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+
+ #if defined(__linux__) || defined(__METAG)
+
+ #define IMG_CALLCONV
+ #define IMG_INTERNAL __attribute__ ((visibility ("hidden")))
+ #define IMG_EXPORT
+ #define IMG_IMPORT
+ #define IMG_RESTRICT __restrict__
+
+ #else
+ #error("define an OS")
+ #endif
+
+#ifndef IMG_ABORT
+ #define IMG_ABORT() abort()
+#endif
+
+#ifndef IMG_MALLOC
+ #define IMG_MALLOC(A) malloc (A)
+#endif
+
+#ifndef IMG_FREE
+ #define IMG_FREE(A) free (A)
+#endif
+
+#define IMG_CONST const
+
+#define IMG_FORMAT_PRINTF(x,y)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/img_types.h b/drivers/gpu/drm/emgd/pvr/include4/img_types.h
new file mode 100644
index 0000000..a7b92e1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/img_types.h
@@ -0,0 +1,124 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS 32
+#endif
+
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS 32
+#endif
+
+typedef unsigned int IMG_UINT, *IMG_PUINT;
+typedef signed int IMG_INT, *IMG_PINT;
+
+typedef unsigned char IMG_UINT8, *IMG_PUINT8;
+typedef unsigned char IMG_BYTE, *IMG_PBYTE;
+typedef signed char IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+
+typedef unsigned short IMG_UINT16, *IMG_PUINT16;
+typedef signed short IMG_INT16, *IMG_PINT16;
+typedef unsigned long IMG_UINT32, *IMG_PUINT32;
+typedef signed long IMG_INT32, *IMG_PINT32;
+
+#if !defined(IMG_UINT32_MAX)
+ #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+ #if (defined(LINUX) || defined(__METAG))
+#if !defined(USE_CODE)
+ typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
+ typedef long long IMG_INT64, *IMG_PINT64;
+#endif
+ #else
+
+ #error("define an OS")
+
+ #endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+typedef float IMG_FLOAT, *IMG_PFLOAT;
+typedef double IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef enum tag_img_bool
+{
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void IMG_VOID, *IMG_PVOID;
+
+typedef IMG_INT32 IMG_RESULT;
+
+typedef IMG_UINT32 IMG_UINTPTR_T;
+
+typedef IMG_PVOID IMG_HANDLE;
+
+typedef void** IMG_HVOID, * IMG_PHVOID;
+
+typedef IMG_UINT32 IMG_SIZE_T;
+
+#define IMG_NULL 0
+
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+typedef struct
+{
+
+ IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef struct _IMG_CPU_PHYADDR
+{
+
+ IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+
+ IMG_UINTPTR_T uiAddr;
+#else
+ IMG_UINT32 uiAddr;
+ IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+typedef struct _IMG_SYS_PHYADDR
+{
+
+ IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h b/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
new file mode 100644
index 0000000..d7e494a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
@@ -0,0 +1,94 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i) (((i) >> 2) & 0xFFF)
+
+#ifndef CTL_CODE
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 )
+#define FILE_WRITE_ACCESS ( 0x0002 )
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h b/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
new file mode 100644
index 0000000..6285c6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+ PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+ PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+
+ PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+ PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+ PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+ PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+ PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+ PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+ PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+ PDUMP_POLL_OPERATOR_EQUAL = 0,
+ PDUMP_POLL_OPERATOR_LESS = 1,
+ PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+ PDUMP_POLL_OPERATOR_GREATER = 3,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+ PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h b/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
new file mode 100644
index 0000000..8459841
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
@@ -0,0 +1,123 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN (512)
+
+#define DBGPRIV_FATAL 0x01UL
+#define DBGPRIV_ERROR 0x02UL
+#define DBGPRIV_WARNING 0x04UL
+#define DBGPRIV_MESSAGE 0x08UL
+#define DBGPRIV_VERBOSE 0x10UL
+#define DBGPRIV_CALLTRACE 0x20UL
+#define DBGPRIV_ALLOC 0x40UL
+#define DBGPRIV_ALLLEVELS (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_MESSAGE | DBGPRIV_VERBOSE)
+
+
+
+#define PVR_DBG_FATAL DBGPRIV_FATAL,__FILE__, __LINE__
+#define PVR_DBG_ERROR DBGPRIV_ERROR,__FILE__, __LINE__
+#define PVR_DBG_WARNING DBGPRIV_WARNING,__FILE__, __LINE__
+#define PVR_DBG_MESSAGE DBGPRIV_MESSAGE,__FILE__, __LINE__
+#define PVR_DBG_VERBOSE DBGPRIV_VERBOSE,__FILE__, __LINE__
+#define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE,__FILE__, __LINE__
+#define PVR_DBG_ALLOC DBGPRIV_ALLOC,__FILE__, __LINE__
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+ #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+ IMG_UINT32 ui32Line);
+
+ #if defined(PVR_DBG_BREAK_ASSERT_FAIL)
+ #define PVR_DBG_BREAK PVRSRVDebugAssertFail("PVR_DBG_BREAK", 0)
+ #else
+ #define PVR_DBG_BREAK
+ #endif
+
+#else
+
+ #define PVR_ASSERT(EXPR)
+ #define PVR_DBG_BREAK
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+ #define PVR_DPF(X) PVRSRVDebugPrintf X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszFormat,
+ ...);
+
+#else
+
+ #define PVR_DPF(X)
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+ #define PVR_TRACE(X) PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... );
+
+#else
+
+ #define PVR_TRACE(X)
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h b/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
new file mode 100644
index 0000000..8aa4b20
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
@@ -0,0 +1,27 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _PVRMODULE_H_
+#define _PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support at imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h b/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
new file mode 100644
index 0000000..25bc19b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 5
+#define PVRVERSION_BRANCH 15
+#define PVRVERSION_BUILD 3226
+#define PVRVERSION_STRING "1.5.15.3226"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/regpaths.h b/drivers/gpu/drm/emgd/pvr/include4/regpaths.h
new file mode 100644
index 0000000..29a5574
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/regpaths.h
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __REGPATHS_H__
+#define __REGPATHS_H__
+
+#define POWERVR_REG_ROOT "Drivers\\Display\\PowerVR"
+#define POWERVR_CHIP_KEY "\\SGX1\\"
+
+#define POWERVR_EURASIA_KEY "PowerVREurasia\\"
+
+#define POWERVR_SERVICES_KEY "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\PowerVR\\"
+
+#define PVRSRV_REGISTRY_ROOT POWERVR_EURASIA_KEY "HWSettings\\PVRSRVKM"
+
+
+#define MAX_REG_STRING_SIZE 128
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/services.h b/drivers/gpu/drm/emgd/pvr/include4/services.h
new file mode 100644
index 0000000..0b8efbb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/services.h
@@ -0,0 +1,866 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+#define PVRSRV_4K_PAGE_SIZE 4096UL
+
+#define PVRSRV_MAX_CMD_SIZE 1024
+
+#define PVRSRV_MAX_DEVICES 16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ (1UL<<0)
+#define PVRSRV_MEM_WRITE (1UL<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT (1UL<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ (1UL<<3)
+#define PVRSRV_MEM_INTERLEAVED (1UL<<4)
+#define PVRSRV_MEM_DUMMY (1UL<<5)
+#define PVRSRV_MEM_EDM_PROTECT (1UL<<6)
+#define PVRSRV_MEM_ZERO (1UL<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR (1UL<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION (1UL<<9)
+#define PVRSRV_MEM_NO_RESMAN (1UL<<10)
+#define PVRSRV_MEM_EXPORTED (1UL<<11)
+
+
+#define PVRSRV_HAP_CACHED (1UL<<12)
+#define PVRSRV_HAP_UNCACHED (1UL<<13)
+#define PVRSRV_HAP_WRITECOMBINE (1UL<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK (PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY (1UL<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS (1UL<<16)
+#define PVRSRV_HAP_MULTI_PROCESS (1UL<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS (1UL<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL (1UL<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK (PVRSRV_HAP_KERNEL_ONLY \
+ |PVRSRV_HAP_SINGLE_PROCESS \
+ |PVRSRV_HAP_MULTI_PROCESS \
+ |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+ |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+#define PVRSRV_MEM_CACHED PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE PVRSRV_HAP_WRITECOMBINE
+
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT (24)
+
+#define PVRSRV_MAP_NOUSERVIRTUAL (1UL<<27)
+
+#define PVRSRV_NO_CONTEXT_LOSS 0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1
+#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80
+
+
+#define PVRSRV_DEFAULT_DEV_COOKIE (1)
+
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT (1UL<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1UL<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1UL<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1UL<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1UL<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT (1UL<<5)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT (1UL<<31)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 200
+
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT 0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA 0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG 0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC 0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC 0x00000002
+
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+ PVRSRV_DEVICE_TYPE_UNKNOWN = 0 ,
+ PVRSRV_DEVICE_TYPE_MBX1 = 1 ,
+ PVRSRV_DEVICE_TYPE_MBX1_LITE = 2 ,
+
+ PVRSRV_DEVICE_TYPE_M24VA = 3,
+ PVRSRV_DEVICE_TYPE_MVDA2 = 4,
+ PVRSRV_DEVICE_TYPE_MVED1 = 5,
+ PVRSRV_DEVICE_TYPE_MSVDX = 6,
+
+ PVRSRV_DEVICE_TYPE_SGX = 7,
+
+ PVRSRV_DEVICE_TYPE_VGX = 8,
+
+
+ PVRSRV_DEVICE_TYPE_EXT = 9,
+
+ PVRSRV_DEVICE_TYPE_LAST = 9,
+
+ PVRSRV_DEVICE_TYPE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ ) ( ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1)) )
+#define HEAP_IDX( _heap_id_ ) ( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ ) ( (_heap_id_)>>24 )
+
+#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+
+typedef enum
+{
+ IMG_EGL = 0x00000001,
+ IMG_OPENGLES1 = 0x00000002,
+ IMG_OPENGLES2 = 0x00000003,
+ IMG_D3DM = 0x00000004,
+ IMG_SRV_UM = 0x00000005,
+ IMG_OPENVG = 0x00000006,
+ IMG_SRVCLIENT = 0x00000007,
+ IMG_VISTAKMD = 0x00000008,
+ IMG_VISTA3DNODE = 0x00000009,
+ IMG_VISTAMVIDEONODE = 0x0000000A,
+ IMG_VISTAVPBNODE = 0x0000000B,
+ IMG_OPENGL = 0x0000000C,
+ IMG_D3D = 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL)
+ IMG_GRAPHICS_HAL = 0x0000000E
+#endif
+
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE 256
+
+typedef enum
+{
+ IMG_STRING_TYPE = 1,
+ IMG_FLOAT_TYPE ,
+ IMG_UINT_TYPE ,
+ IMG_INT_TYPE ,
+ IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+ IMG_UINT32 ui32DeviceIndex;
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];
+ PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+ PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+typedef struct _PVRSRV_CONNECTION_
+{
+ IMG_HANDLE hServices;
+ IMG_UINT32 ui32ProcessID;
+ PVRSRV_CLIENT_DEV_DATA sClientDevData;
+}PVRSRV_CONNECTION;
+
+
+typedef struct _PVRSRV_DEV_DATA_
+{
+ PVRSRV_CONNECTION sConnection;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_MEMUPDATE_
+{
+ IMG_UINT32 ui32UpdateAddr;
+ IMG_UINT32 ui32UpdateVal;
+} PVRSRV_MEMUPDATE;
+
+typedef struct _PVRSRV_HWREG_
+{
+ IMG_UINT32 ui32RegAddr;
+ IMG_UINT32 ui32RegVal;
+} PVRSRV_HWREG;
+
+typedef struct _PVRSRV_MEMBLK_
+{
+ IMG_DEV_VIRTADDR sDevVirtAddr;
+ IMG_HANDLE hOSMemHandle;
+ IMG_HANDLE hOSWrapMem;
+ IMG_HANDLE hBuffer;
+ IMG_HANDLE hResItem;
+ IMG_SYS_PHYADDR *psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddr;
+
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+
+
+
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+
+
+ IMG_UINT32 ui32ClientFlags;
+
+
+ IMG_SIZE_T ui32AllocSize;
+
+
+
+ struct _PVRSRV_CLIENT_SYNC_INFO_ *psClientSyncInfo;
+
+
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelMemInfo;
+
+
+ IMG_HANDLE hResItem;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+#endif
+
+ IMG_HANDLE hOSMapInfo;
+
+ struct _PVRSRV_CLIENT_MEM_INFO_ *psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+ IMG_UINT32 ui32HeapID;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+ IMG_UINT32 ui32HeapByteSize;
+ IMG_UINT32 ui32Attribs;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+
+ IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
+
+ IMG_HANDLE hOSEventKM;
+
+} PVRSRV_EVENTOBJECT;
+
+typedef struct _PVRSRV_MISC_INFO_
+{
+ IMG_UINT32 ui32StateRequest;
+ IMG_UINT32 ui32StatePresent;
+
+
+ IMG_VOID *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCTimerRegisterUM;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_HANDLE hSOCTimerRegisterMappingInfo;
+
+
+ IMG_VOID *pvSOCClockGateRegs;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+
+ IMG_CHAR *pszMemoryStr;
+ IMG_UINT32 ui32MemoryStrLen;
+
+
+ PVRSRV_EVENTOBJECT sGlobalEventObject;
+ IMG_HANDLE hOSGlobalEvent;
+
+
+ IMG_UINT32 aui32DDKVersion[4];
+
+
+
+ IMG_BOOL bCPUCacheFlushAll;
+
+ IMG_BOOL bDeferCPUCacheFlush;
+
+ IMG_PVOID pvRangeAddrStart;
+
+ IMG_PVOID pvRangeAddrEnd;
+
+} PVRSRV_MISC_INFO;
+
+
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+ PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
+} PVRSRV_CLIENT_EVENT;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *puiNumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 uiDevIndex,
+ PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_DEVICE_TYPE eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+#if 1
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent,
+ volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+ ": " logStr " (size = 0x%lx)", ui32Size)), \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_HANDLE *phMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hKernelMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_VOID *pvLinAddr,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo,
+ IMG_UINT32 ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_SYS_PHYADDR sSysPhysAddr,
+ IMG_UINT32 uiSizeInBytes,
+ IMG_PVOID *ppvUserAddr,
+ IMG_UINT32 *puiActualSize,
+ IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+ PVRSRV_SYNCVAL_READ = IMG_TRUE,
+ PVRSRV_SYNCVAL_WRITE = IMG_FALSE,
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID);
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat,
+ DISPLAY_DIMS *psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+ DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_UINT32 *pui32SwapChainID,
+ IMG_HANDLE *phSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain);
+
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+ BUFFER_INFO *psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_BOOL bIsRead,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelMemInfo,
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CONST IMG_CHAR *pszComment,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL bContinuous,
+ IMG_CONST IMG_CHAR *pszFormat, ...);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_CONST IMG_CHAR *pszFormat, ...);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CHAR *pszString,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CONST IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegOffset,
+ IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINT32 IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+ const IMG_CHAR *pszAppName,
+ IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+ IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID *pvHintState,
+ const IMG_CHAR *pszHintName,
+ IMG_DATA_TYPE eDataType,
+ const IMG_VOID *pvDefault,
+ IMG_VOID *pvReturn);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+#if (defined(DEBUG) && defined(__linux__))
+IMG_PVOID PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+IMG_PVOID PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+IMG_VOID PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+IMG_PVOID PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfo,
+ IMG_UINT32 ui32ModifyFlags,
+ IMG_UINT32 *pui32ReadOpsPending,
+ IMG_UINT32 *pui32WriteOpsPending);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfo,
+ IMG_UINT32 ui32ModifyFlags);
+
+
+#define TIME_NOT_PASSED_UINT32(a,b,c) ((a - b) < c)
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/servicesext.h b/drivers/gpu/drm/emgd/pvr/include4/servicesext.h
new file mode 100644
index 0000000..0f3dc1d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/servicesext.h
@@ -0,0 +1,647 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#define PVRSRV_LOCKFLG_READONLY (1)
+
+typedef enum _PVRSRV_ERROR_
+{
+ PVRSRV_OK = 0,
+ PVRSRV_ERROR_GENERIC = 1,
+ PVRSRV_ERROR_OUT_OF_MEMORY = 2,
+ PVRSRV_ERROR_TOO_FEW_BUFFERS = 3,
+ PVRSRV_ERROR_SYMBOL_NOT_FOUND = 4,
+ PVRSRV_ERROR_OUT_OF_HSPACE = 5,
+ PVRSRV_ERROR_INVALID_PARAMS = 6,
+ PVRSRV_ERROR_TILE_MAP_FAILED = 7,
+ PVRSRV_ERROR_INIT_FAILURE = 8,
+ PVRSRV_ERROR_CANT_REGISTER_CALLBACK = 9,
+ PVRSRV_ERROR_INVALID_DEVICE = 10,
+ PVRSRV_ERROR_NOT_OWNER = 11,
+ PVRSRV_ERROR_BAD_MAPPING = 12,
+ PVRSRV_ERROR_TIMEOUT = 13,
+ PVRSRV_ERROR_NO_PRIMARY = 14,
+ PVRSRV_ERROR_FLIP_CHAIN_EXISTS = 15,
+ PVRSRV_ERROR_CANNOT_ACQUIRE_SYSDATA = 16,
+ PVRSRV_ERROR_SCENE_INVALID = 17,
+ PVRSRV_ERROR_STREAM_ERROR = 18,
+ PVRSRV_ERROR_INVALID_INTERRUPT = 19,
+ PVRSRV_ERROR_FAILED_DEPENDENCIES = 20,
+ PVRSRV_ERROR_CMD_NOT_PROCESSED = 21,
+ PVRSRV_ERROR_CMD_TOO_BIG = 22,
+ PVRSRV_ERROR_DEVICE_REGISTER_FAILED = 23,
+ PVRSRV_ERROR_FIFO_SPACE = 24,
+ PVRSRV_ERROR_TA_RECOVERY = 25,
+ PVRSRV_ERROR_INDOSORLOWPOWER = 26,
+ PVRSRV_ERROR_TOOMANYBUFFERS = 27,
+ PVRSRV_ERROR_NOT_SUPPORTED = 28,
+ PVRSRV_ERROR_PROCESSING_BLOCKED = 29,
+
+
+ PVRSRV_ERROR_CANNOT_FLUSH_QUEUE = 31,
+ PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE = 32,
+ PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS = 33,
+ PVRSRV_ERROR_RETRY = 34,
+
+ PVRSRV_ERROR_DDK_VERSION_MISMATCH = 35,
+ PVRSRV_ERROR_BUILD_MISMATCH = 36,
+ PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+ PVRSRV_DEVICE_CLASS_3D = 0 ,
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1 ,
+ PVRSRV_DEVICE_CLASS_BUFFER = 2 ,
+ PVRSRV_DEVICE_CLASS_VIDEO = 3 ,
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1,
+ PVRSRV_SYS_POWER_STATE_D0 = 0,
+ PVRSRV_SYS_POWER_STATE_D1 = 1,
+ PVRSRV_SYS_POWER_STATE_D2 = 2,
+ PVRSRV_SYS_POWER_STATE_D3 = 3,
+ PVRSRV_SYS_POWER_STATE_D4 = 4,
+
+ PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+ PVRSRV_DEV_POWER_STATE_DEFAULT = -1,
+ PVRSRV_DEV_POWER_STATE_ON = 0,
+ PVRSRV_DEV_POWER_STATE_IDLE = 1,
+ PVRSRV_DEV_POWER_STATE_OFF = 2,
+
+ PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;
+
+
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+
+ PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
+ PVRSRV_PIXEL_FORMAT_RGB565 = 1,
+ PVRSRV_PIXEL_FORMAT_RGB555 = 2,
+ PVRSRV_PIXEL_FORMAT_RGB888 = 3,
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4,
+ PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+ PVRSRV_PIXEL_FORMAT_PAL12 = 13,
+ PVRSRV_PIXEL_FORMAT_PAL8 = 14,
+ PVRSRV_PIXEL_FORMAT_PAL4 = 15,
+ PVRSRV_PIXEL_FORMAT_PAL2 = 16,
+ PVRSRV_PIXEL_FORMAT_PAL1 = 17,
+ PVRSRV_PIXEL_FORMAT_ARGB1555 = 18,
+ PVRSRV_PIXEL_FORMAT_ARGB4444 = 19,
+ PVRSRV_PIXEL_FORMAT_ARGB8888 = 20,
+ PVRSRV_PIXEL_FORMAT_ABGR8888 = 21,
+ PVRSRV_PIXEL_FORMAT_YV12 = 22,
+ PVRSRV_PIXEL_FORMAT_I420 = 23,
+ PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+ PVRSRV_PIXEL_FORMAT_XRGB8888 = 26,
+ PVRSRV_PIXEL_FORMAT_XBGR8888,
+ PVRSRV_PIXEL_FORMAT_BGRA8888,
+ PVRSRV_PIXEL_FORMAT_XRGB4444,
+ PVRSRV_PIXEL_FORMAT_ARGB8332,
+ PVRSRV_PIXEL_FORMAT_A2RGB10,
+ PVRSRV_PIXEL_FORMAT_A2BGR10,
+ PVRSRV_PIXEL_FORMAT_P8,
+ PVRSRV_PIXEL_FORMAT_L8,
+ PVRSRV_PIXEL_FORMAT_A8L8,
+ PVRSRV_PIXEL_FORMAT_A4L4,
+ PVRSRV_PIXEL_FORMAT_L16,
+ PVRSRV_PIXEL_FORMAT_L6V5U5,
+ PVRSRV_PIXEL_FORMAT_V8U8,
+ PVRSRV_PIXEL_FORMAT_V16U16,
+ PVRSRV_PIXEL_FORMAT_QWVU8888,
+ PVRSRV_PIXEL_FORMAT_XLVU8888,
+ PVRSRV_PIXEL_FORMAT_QWVU16,
+ PVRSRV_PIXEL_FORMAT_D16,
+ PVRSRV_PIXEL_FORMAT_D24S8,
+ PVRSRV_PIXEL_FORMAT_D24X8,
+
+
+ PVRSRV_PIXEL_FORMAT_ABGR16,
+ PVRSRV_PIXEL_FORMAT_ABGR16F,
+ PVRSRV_PIXEL_FORMAT_ABGR32,
+ PVRSRV_PIXEL_FORMAT_ABGR32F,
+ PVRSRV_PIXEL_FORMAT_B10GR11,
+ PVRSRV_PIXEL_FORMAT_GR88,
+ PVRSRV_PIXEL_FORMAT_BGR32,
+ PVRSRV_PIXEL_FORMAT_GR32,
+ PVRSRV_PIXEL_FORMAT_E5BGR9,
+
+
+ PVRSRV_PIXEL_FORMAT_DUMMY1,
+ PVRSRV_PIXEL_FORMAT_DUMMY2,
+ PVRSRV_PIXEL_FORMAT_DUMMY3,
+ PVRSRV_PIXEL_FORMAT_DUMMY4,
+ PVRSRV_PIXEL_FORMAT_DUMMY5,
+
+
+ PVRSRV_PIXEL_FORMAT_R8G8_B8G8,
+ PVRSRV_PIXEL_FORMAT_G8R8_G8B8,
+
+
+ PVRSRV_PIXEL_FORMAT_NV11,
+ PVRSRV_PIXEL_FORMAT_NV12,
+
+
+ PVRSRV_PIXEL_FORMAT_YUY2,
+ PVRSRV_PIXEL_FORMAT_YUV420,
+ PVRSRV_PIXEL_FORMAT_YUV444,
+ PVRSRV_PIXEL_FORMAT_VUY444,
+ PVRSRV_PIXEL_FORMAT_YUYV,
+ PVRSRV_PIXEL_FORMAT_YVYU,
+ PVRSRV_PIXEL_FORMAT_UYVY,
+ PVRSRV_PIXEL_FORMAT_VYUY,
+
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV,
+
+
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT,
+
+
+ PVRSRV_PIXEL_FORMAT_B32G32R32,
+ PVRSRV_PIXEL_FORMAT_B32G32R32F,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT,
+
+
+ PVRSRV_PIXEL_FORMAT_G32R32,
+ PVRSRV_PIXEL_FORMAT_G32R32F,
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT,
+
+
+ PVRSRV_PIXEL_FORMAT_D32F,
+ PVRSRV_PIXEL_FORMAT_R32,
+ PVRSRV_PIXEL_FORMAT_R32F,
+ PVRSRV_PIXEL_FORMAT_R32_UINT,
+ PVRSRV_PIXEL_FORMAT_R32_SINT,
+
+
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_G16R16,
+ PVRSRV_PIXEL_FORMAT_G16R16F,
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT,
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM,
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT,
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_R16,
+ PVRSRV_PIXEL_FORMAT_R16F,
+ PVRSRV_PIXEL_FORMAT_R16_UINT,
+ PVRSRV_PIXEL_FORMAT_R16_UNORM,
+ PVRSRV_PIXEL_FORMAT_R16_SINT,
+ PVRSRV_PIXEL_FORMAT_R16_SNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB,
+
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB,
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_G8R8,
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT,
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT,
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_A8,
+ PVRSRV_PIXEL_FORMAT_R8,
+ PVRSRV_PIXEL_FORMAT_R8_UINT,
+ PVRSRV_PIXEL_FORMAT_R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_R8_SINT,
+ PVRSRV_PIXEL_FORMAT_R8_SNORM,
+
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT,
+
+
+ PVRSRV_PIXEL_FORMAT_B10G11R11,
+ PVRSRV_PIXEL_FORMAT_B10G11R11F,
+
+
+ PVRSRV_PIXEL_FORMAT_X24G8R32,
+ PVRSRV_PIXEL_FORMAT_G8R24,
+ PVRSRV_PIXEL_FORMAT_X8R24,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9,
+ PVRSRV_PIXEL_FORMAT_R1,
+
+ PVRSRV_PIXEL_FORMAT_DUMMY6,
+ PVRSRV_PIXEL_FORMAT_DUMMY7,
+ PVRSRV_PIXEL_FORMAT_DUMMY8,
+ PVRSRV_PIXEL_FORMAT_DUMMY9,
+ PVRSRV_PIXEL_FORMAT_DUMMY10,
+ PVRSRV_PIXEL_FORMAT_DUMMY11,
+ PVRSRV_PIXEL_FORMAT_DUMMY12,
+ PVRSRV_PIXEL_FORMAT_DUMMY13,
+ PVRSRV_PIXEL_FORMAT_DUMMY14,
+ PVRSRV_PIXEL_FORMAT_DUMMY15,
+ PVRSRV_PIXEL_FORMAT_DUMMY16,
+ PVRSRV_PIXEL_FORMAT_DUMMY17,
+ PVRSRV_PIXEL_FORMAT_DUMMY18,
+ PVRSRV_PIXEL_FORMAT_DUMMY19,
+ PVRSRV_PIXEL_FORMAT_DUMMY20,
+
+
+ PVRSRV_PIXEL_FORMAT_L_F16,
+ PVRSRV_PIXEL_FORMAT_L_F16_REP,
+ PVRSRV_PIXEL_FORMAT_L_F16_A_F16,
+ PVRSRV_PIXEL_FORMAT_A_F16,
+ PVRSRV_PIXEL_FORMAT_B16G16R16F,
+
+ PVRSRV_PIXEL_FORMAT_L_F32,
+ PVRSRV_PIXEL_FORMAT_A_F32,
+ PVRSRV_PIXEL_FORMAT_L_F32_A_F32,
+
+
+ PVRSRV_PIXEL_FORMAT_PVRTC2,
+ PVRSRV_PIXEL_FORMAT_PVRTC4,
+ PVRSRV_PIXEL_FORMAT_PVRTCII2,
+ PVRSRV_PIXEL_FORMAT_PVRTCII4,
+ PVRSRV_PIXEL_FORMAT_PVRTCIII,
+ PVRSRV_PIXEL_FORMAT_PVRO8,
+ PVRSRV_PIXEL_FORMAT_PVRO88,
+ PVRSRV_PIXEL_FORMAT_PT1,
+ PVRSRV_PIXEL_FORMAT_PT2,
+ PVRSRV_PIXEL_FORMAT_PT4,
+ PVRSRV_PIXEL_FORMAT_PT8,
+ PVRSRV_PIXEL_FORMAT_PTW,
+ PVRSRV_PIXEL_FORMAT_PTB,
+ PVRSRV_PIXEL_FORMAT_MONO8,
+ PVRSRV_PIXEL_FORMAT_MONO16,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUYV,
+ PVRSRV_PIXEL_FORMAT_C0_UYVY,
+ PVRSRV_PIXEL_FORMAT_C0_YVYU,
+ PVRSRV_PIXEL_FORMAT_C0_VYUY,
+ PVRSRV_PIXEL_FORMAT_C1_YUYV,
+ PVRSRV_PIXEL_FORMAT_C1_UYVY,
+ PVRSRV_PIXEL_FORMAT_C1_YVYU,
+ PVRSRV_PIXEL_FORMAT_C1_VYUY,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_3P,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_3P,
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10F,
+ PVRSRV_PIXEL_FORMAT_B8G8R8_SINT,
+ PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK,
+
+ PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff,
+} PVRSRV_PIXEL_FORMAT;
+
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+ PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
+ PVRSRV_ALPHA_FORMAT_NONPRE = 0x00000002,
+ PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000,
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+typedef enum _PVRSRV_ROTATION_ {
+ PVRSRV_ROTATE_0 = 0,
+ PVRSRV_ROTATE_90 = 1,
+ PVRSRV_ROTATE_180 = 2,
+ PVRSRV_ROTATE_270 = 3,
+ PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+
+typedef struct _PVRSRV_SYNC_DATA_
+{
+
+ IMG_UINT32 ui32WriteOpsPending;
+ volatile IMG_UINT32 ui32WriteOpsComplete;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ volatile IMG_UINT32 ui32ReadOpsComplete;
+
+
+ IMG_UINT32 ui32LastOpDumpVal;
+ IMG_UINT32 ui32LastReadOpDumpVal;
+
+} PVRSRV_SYNC_DATA;
+
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelSyncInfo;
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+
+typedef struct PVRSRV_RESOURCE_TAG
+{
+ volatile IMG_UINT32 ui32Lock;
+ IMG_UINT32 ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+typedef struct _IMG_RECT_
+{
+ IMG_INT32 x0;
+ IMG_INT32 y0;
+ IMG_INT32 x1;
+ IMG_INT32 y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+ IMG_INT16 x0;
+ IMG_INT16 y0;
+ IMG_INT16 x1;
+ IMG_INT16 y1;
+}IMG_RECT_16;
+
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_SYS_PHYADDR**,
+ IMG_SIZE_T*,
+ IMG_VOID**,
+ IMG_HANDLE*,
+ IMG_BOOL*,
+ IMG_BOOL*);
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ID_FROM_TAG)(IMG_HANDLE, IMG_UINT32, IMG_HANDLE);
+
+typedef struct DISPLAY_DIMS_TAG
+{
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+} DISPLAY_DIMS;
+
+
+typedef struct DISPLAY_FORMAT_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+} DISPLAY_FORMAT;
+
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+ IMG_UINT32 ui32Reseved;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+
+ IMG_UINT32 ui32RefreshHZ;
+
+ IMG_UINT32 ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE (50)
+
+typedef struct DISPLAY_INFO_TAG
+{
+
+ IMG_UINT32 ui32MaxSwapChains;
+
+ IMG_UINT32 ui32MaxSwapChainBuffers;
+
+ IMG_UINT32 ui32MinSwapInterval;
+
+ IMG_UINT32 ui32MaxSwapInterval;
+
+ IMG_UINT32 ui32PhysicalWidthmm;
+ IMG_UINT32 ui32PhysicalHeightmm;
+
+ IMG_CHAR szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+
+ IMG_UINT16 ui32CursorWidth;
+ IMG_UINT16 ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+}ACCESS_INFO;
+
+
+typedef struct PVRSRV_CURSOR_SHAPE_TAG
+{
+ IMG_UINT16 ui16Width;
+ IMG_UINT16 ui16Height;
+ IMG_INT16 i16XHot;
+ IMG_INT16 i16YHot;
+
+
+ IMG_VOID* pvMask;
+ IMG_INT16 i16MaskByteStride;
+
+
+ IMG_VOID* pvColour;
+ IMG_INT16 i16ColourByteStride;
+ PVRSRV_PIXEL_FORMAT eColourPixelFormat;
+} PVRSRV_CURSOR_SHAPE;
+
+#define PVRSRV_SET_CURSOR_VISIBILITY (1<<0)
+#define PVRSRV_SET_CURSOR_POSITION (1<<1)
+#define PVRSRV_SET_CURSOR_SHAPE (1<<2)
+#define PVRSRV_SET_CURSOR_ROTATION (1<<3)
+
+typedef struct PVRSRV_CURSOR_INFO_TAG
+{
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_BOOL bVisible;
+
+
+ IMG_INT16 i16XPos;
+ IMG_INT16 i16YPos;
+
+
+ PVRSRV_CURSOR_SHAPE sCursorShape;
+
+
+ IMG_UINT32 ui32Rotation;
+
+} PVRSRV_CURSOR_INFO;
+
+
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+ IMG_UINT32 ui32DevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+ IMG_PCHAR pszBuf;
+ IMG_UINT32 ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE (50)
+
+typedef struct BUFFER_INFO_TAG
+{
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32BufferDeviceID;
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+ WEAVE=0x0,
+ BOB_ODD,
+ BOB_EVEN,
+ BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h b/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
new file mode 100644
index 0000000..75d1286
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
@@ -0,0 +1,220 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET OPTIONS_BIT0
+#define OPTIONS_BIT0 0x1
+#else
+#define OPTIONS_BIT0 0x0
+#endif
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET OPTIONS_BIT1
+#define OPTIONS_BIT1 (0x1 << 1)
+#else
+#define OPTIONS_BIT1 0x0
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET OPTIONS_BIT2
+#define OPTIONS_BIT2 (0x1 << 2)
+#else
+#define OPTIONS_BIT2 0x0
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
+#define OPTIONS_BIT3 (0x1 << 3)
+#else
+#define OPTIONS_BIT3 0x0
+#endif
+
+
+
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET OPTIONS_BIT4
+#define OPTIONS_BIT4 (0x1 << 4)
+#else
+#define OPTIONS_BIT4 0x0
+#endif
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT5
+#define OPTIONS_BIT5 (0x1 << 5)
+#else
+#define OPTIONS_BIT5 0x0
+#endif
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET OPTIONS_BIT6
+#define OPTIONS_BIT6 (0x1 << 6)
+#else
+#define OPTIONS_BIT6 0x0
+#endif
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET OPTIONS_BIT8
+#define OPTIONS_BIT8 (0x1 << 8)
+#else
+#define OPTIONS_BIT8 0x0
+#endif
+
+#if defined(SGX_FEATURE_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET OPTIONS_BIT9
+#define OPTIONS_BIT9 (0x1 << 9)
+#else
+#define OPTIONS_BIT9 0x0
+#endif
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET OPTIONS_BIT10
+#define OPTIONS_BIT10 (0x1 << 10)
+#else
+#define OPTIONS_BIT10 0x0
+#endif
+
+#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET OPTIONS_BIT11
+#define OPTIONS_BIT11 (0x1 << 11)
+#else
+#define OPTIONS_BIT11 0x0
+#endif
+
+
+
+#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET OPTIONS_BIT12
+#define OPTIONS_BIT12 (0x1 << 12)
+#else
+#define OPTIONS_BIT12 0x0
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT13
+#define OPTIONS_BIT13 (0x1 << 13)
+#else
+#define OPTIONS_BIT13 0x0
+#endif
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET OPTIONS_BIT14
+#define OPTIONS_BIT14 (0x1 << 14)
+#else
+#define OPTIONS_BIT14 0x0
+#endif
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET OPTIONS_BIT15
+#define OPTIONS_BIT15 (0x1 << 15)
+#else
+#define OPTIONS_BIT15 0x0
+#endif
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET OPTIONS_BIT16
+#define OPTIONS_BIT16 (0x1 << 16)
+#else
+#define OPTIONS_BIT16 0x0
+#endif
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET OPTIONS_BIT17
+#define OPTIONS_BIT17 (0x1 << 17)
+#else
+#define OPTIONS_BIT17 0x0
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET OPTIONS_BIT18
+#define OPTIONS_BIT18 (0x1 << 18)
+#else
+#define OPTIONS_BIT18 0x0
+#endif
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET OPTIONS_BIT19
+#define OPTIONS_BIT19 (0x1 << 19)
+#else
+#define OPTIONS_BIT19 0x0
+#endif
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET OPTIONS_BIT20
+#define OPTIONS_BIT20 (0x1 << 20)
+#else
+#define OPTIONS_BIT20 0x0
+#endif
+
+#if defined(SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET OPTIONS_BIT21
+#define OPTIONS_BIT21 (0x1 << 21)
+#else
+#define OPTIONS_BIT21 0x0
+#endif
+
+#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
+#define OPTIONS_BIT22 (0x1 << 22)
+#else
+#define OPTIONS_BIT22 0x0
+#endif
+
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET 28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
+#else
+#define OPTIONS_HIGHBYTE 0x0
+#endif
+
+
+
+#define SGX_BUILD_OPTIONS \
+ OPTIONS_BIT0 |\
+ OPTIONS_BIT1 |\
+ OPTIONS_BIT2 |\
+ OPTIONS_BIT3 |\
+ OPTIONS_BIT4 |\
+ OPTIONS_BIT5 |\
+ OPTIONS_BIT6 |\
+ OPTIONS_BIT8 |\
+ OPTIONS_BIT9 |\
+ OPTIONS_BIT10 |\
+ OPTIONS_BIT11 |\
+ OPTIONS_BIT12 |\
+ OPTIONS_BIT13 |\
+ OPTIONS_BIT14 |\
+ OPTIONS_BIT15 |\
+ OPTIONS_BIT16 |\
+ OPTIONS_BIT17 |\
+ OPTIONS_BIT18 |\
+ OPTIONS_BIT19 |\
+ OPTIONS_BIT20 |\
+ OPTIONS_BIT21 |\
+ OPTIONS_HIGHBYTE
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h b/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
new file mode 100644
index 0000000..5302204
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
@@ -0,0 +1,323 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if defined(__linux__) && !defined(USE_CODE)
+ #if defined(__KERNEL__)
+ #include <asm/unistd.h>
+ #else
+ #include <unistd.h>
+ #endif
+#endif
+
+#define SGX_UNDEFINED_HEAP_ID (~0LU)
+#define SGX_GENERAL_HEAP_ID 0
+#define SGX_TADATA_HEAP_ID 1
+#define SGX_KERNEL_CODE_HEAP_ID 2
+#define SGX_KERNEL_DATA_HEAP_ID 3
+#define SGX_PIXELSHADER_HEAP_ID 4
+#define SGX_VERTEXSHADER_HEAP_ID 5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID 6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID 7
+#define SGX_SYNCINFO_HEAP_ID 8
+#define SGX_3DPARAMETERS_HEAP_ID 9
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID 10
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID 11
+#else
+#if defined(FIX_HW_BRN_26915)
+#define SGX_CGBUFFER_HEAP_ID 12
+#endif
+#endif
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+#define SGX_VIDEO_HEAP_ID 13
+#define SGX_MAX_HEAP_ID 14
+#else
+#define SGX_MAX_HEAP_ID 13
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS 3
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+#define SGX_MAX_TA_DST_SYNCS 1
+#define SGX_MAX_TA_SRC_SYNCS 1
+#define SGX_MAX_3D_SRC_SYNCS 4
+#else
+#define SGX_MAX_SRC_SYNCS 4
+#endif
+
+#ifdef SUPPORT_SGX_HWPERF
+
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 9
+
+#define PVRSRV_SGX_HWPERF_INVALID 0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER 0x2
+#define PVRSRV_SGX_HWPERF_TA 0x3
+#define PVRSRV_SGX_HWPERF_3D 0x4
+#define PVRSRV_SGX_HWPERF_2D 0x5
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT 0x101
+#define PVRSRV_SGX_HWPERF_MK_TA 0x102
+#define PVRSRV_SGX_HWPERF_MK_3D 0x103
+#define PVRSRV_SGX_HWPERF_MK_2D 0x104
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT 28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK ((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START (0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END (1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_OFF (0x0)
+#define PVRSRV_SGX_HWPERF_GRAPHICS_ON (1UL << 0)
+#define PVRSRV_SGX_HWPERF_MK_EXECUTION_ON (1UL << 1)
+
+
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32Clocksx16;
+ IMG_UINT32 ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+typedef struct _PVRSRV_SGX_HWPERF_CBDATA_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32StartTimeWraps;
+ IMG_UINT32 ui32StartTime;
+ IMG_UINT32 ui32EndTimeWraps;
+ IMG_UINT32 ui32EndTime;
+ IMG_UINT32 ui32ClockSpeed;
+ IMG_UINT32 ui32TimeMax;
+} PVRSRV_SGX_HWPERF_CBDATA;
+
+
+typedef struct _SGX_MISC_INFO_HWPERF_RETRIEVE_CB
+{
+ PVRSRV_SGX_HWPERF_CBDATA* psHWPerfData;
+ IMG_UINT32 ui32ArraySize;
+ IMG_UINT32 ui32DataCount;
+ IMG_UINT32 ui32Time;
+} SGX_MISC_INFO_HWPERF_RETRIEVE_CB;
+#endif
+
+
+typedef struct _CTL_STATUS_
+{
+ IMG_DEV_VIRTADDR sStatusDevAddr;
+ IMG_UINT32 ui32StatusValue;
+} CTL_STATUS;
+
+
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+ SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+ SGX_MISC_INFO_REQUEST_SGXREV,
+ SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ SGX_MISC_INFO_REQUEST_MEMREAD,
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+ SGX_MISC_INFO_REQUEST_HWPERF_CB_ON,
+ SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF,
+ SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB,
+#endif
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+#endif
+ SGX_MISC_INFO_DUMP_DEBUG_INFO,
+ SGX_MISC_INFO_PANIC,
+ SGX_MISC_INFO_REQUEST_FORCE_I16 = 0x7fff
+} SGX_MISC_INFO_REQUEST;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+ IMG_UINT32 ui32CoreRev;
+ IMG_UINT32 ui32CoreID;
+ IMG_UINT32 ui32DDKVersion;
+ IMG_UINT32 ui32DDKBuild;
+ IMG_UINT32 ui32CoreIdSW;
+ IMG_UINT32 ui32CoreRevSW;
+ IMG_UINT32 ui32BuildOptions;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_UINT32 ui32DeviceMemValue;
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+typedef struct _SGX_BREAKPOINT_INFO
+{
+
+ IMG_BOOL bBPEnable;
+
+
+
+ IMG_UINT32 ui32BPIndex;
+
+ IMG_DEV_VIRTADDR sBPDevVAddr;
+} SGX_BREAKPOINT_INFO;
+#endif
+
+typedef struct _SGX_MISC_INFO_
+{
+ SGX_MISC_INFO_REQUEST eRequest;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_HANDLE hDevMemContext;
+#endif
+ union
+ {
+ IMG_UINT32 reserved;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ IMG_UINT32 ui32SGXClockSpeed;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_BREAKPOINT_INFO sSGXBreakpointInfo;
+#endif
+#ifdef SUPPORT_SGX_HWPERF
+ IMG_UINT32 ui32NewHWPerfStatus;
+ SGX_MISC_INFO_HWPERF_RETRIEVE_CB sRetrieveCB;
+#endif
+ } uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_MAX_BLT_SRC_SYNCS 3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH 256
+
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Stride;
+ IMG_UINT32 ui32PDUMPFormat;
+ IMG_UINT32 ui32BytesPP;
+ IMG_CHAR pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE (16)
+
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+
+ IMG_UINT32 ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+ IMG_HANDLE hKernelMemInfo;
+ IMG_UINT32 uiAllocIndex;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_PCHAR pszName;
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+{
+ IMG_UINT32 ui32SpaceUsed;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32BufferSize;
+ IMG_UINT32 ui32BackEndLength;
+ IMG_UINT32 uiAllocIndex;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_PVOID pvLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ IMG_HANDLE hCtrlKernelMemInfo;
+ IMG_DEV_VIRTADDR sCtrlDevVAddr;
+#endif
+ IMG_PCHAR pszName;
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+typedef struct _SGX_KICKTA_PDUMP_
+{
+
+ PSGX_KICKTA_DUMPBITMAP psPDumpBitmapArray;
+ IMG_UINT32 ui32PDumpBitmapSize;
+
+
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray;
+ IMG_UINT32 ui32BufferArraySize;
+
+
+ PSGX_KICKTA_DUMP_ROFF psROffArray;
+ IMG_UINT32 ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_MAX_2D_BLIT_CMD_SIZE 26
+#define SGX_MAX_2D_SRC_SYNC_OPS 3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS 2
+#define SGX_MAX_TRANSFER_SYNC_OPS 5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h b/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
new file mode 100644
index 0000000..c6d080b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
@@ -0,0 +1,77 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_MAX_INIT_COMMANDS 64
+#define SGX_MAX_DEINIT_COMMANDS 16
+
+typedef enum _SGX_INIT_OPERATION
+{
+ SGX_INIT_OP_ILLEGAL = 0,
+ SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+ SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+ SGX_INIT_OP_HALT
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+ SGX_INIT_OPERATION eOp;
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sWriteHWReg;
+#if defined(PDUMP)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sPDumpHWReg;
+#endif
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ } sWorkaroundBRN22997;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct _SGX_INIT_SCRIPTS_
+{
+ SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
new file mode 100755
index 0000000..80fac89
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
@@ -0,0 +1,390 @@
+/***************************************************************************
+ *
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#define MODULE_NAME hal.buf_class
+
+#if defined(__linux__)
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#if 0
+#if defined(LMA)
+#include <linux/pci.h>
+#else
+#include <linux/dma-mapping.h>
+#endif
+#endif
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "emgd_drv.h"
+#include "io.h"
+
+#include "pvrmodule.h"
+#include "emgd_bc.h"
+/*
+** Device Name Space is for device name, steam tag and device state.
+** Format
+** [Name]...[Video ID][Device Status]
+** From Device Name Space tail,
+** Device Status - one Byte
+** Video ID - four Byte
+** Device Name - variation according to device name set.
+*/
+#define TSBUFFERCLASS_DEVICE_NAME "BC Texture Stream Device"
+
+unsigned int bc_video_id[BUFCLASS_DEVICE_MAX_ID];
+unsigned int bc_video_id_usage[BUFCLASS_DEVICE_MAX_ID];
+
+void *gp_bc_Anchor[BUFCLASS_DEVICE_MAX_ID];
+
+static PFN_BC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+
+BC_DEVINFO *GetAnchorPtr (int id){
+ BC_DEVINFO *AnchorPtr = NULL;
+ if (id < BUFCLASS_DEVICE_MAX_ID)
+ AnchorPtr = gp_bc_Anchor[id];
+ return AnchorPtr;
+}
+
+static void SetAnchorPtr(BC_DEVINFO *psDevInfo, int id) {
+ if (id < BUFCLASS_DEVICE_MAX_ID) {
+ gp_bc_Anchor[id] = (void *) psDevInfo;
+ }
+}
+
+static PVRSRV_ERROR OpenBCDevice (IMG_UINT32 uDeviceID, IMG_HANDLE * phDevice){
+ BC_DEVINFO *psDevInfo = NULL;
+ int i = 0;
+
+ EMGD_TRACE_ENTER;
+ if (NULL == phDevice) {
+ EMGD_ERROR("Invliad Input parameter");
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+ *phDevice = NULL;
+
+ EMGD_DEBUG("Try to Open Device ID - %lu", uDeviceID);
+
+ for (i = 0; i < BUFCLASS_DEVICE_MAX_ID; i++) {
+ psDevInfo = GetAnchorPtr(i);
+ if (NULL != psDevInfo && uDeviceID == psDevInfo->Device_ID) {
+ *phDevice = (IMG_HANDLE)psDevInfo;
+ EMGD_DEBUG("psDevInfo - 0x%lx", (unsigned long)psDevInfo);
+ break;
+ }
+ }
+
+ if (NULL == *phDevice) {
+ EMGD_ERROR("Invliad Device ID - %lu", uDeviceID);
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ EMGD_TRACE_EXIT;
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR CloseBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE hDevice){
+ UNREFERENCED_PARAMETER (uDeviceID);
+ UNREFERENCED_PARAMETER (hDevice);
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR GetBCBuffer(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32BufferNumber,
+ PVRSRV_SYNC_DATA * psSyncData, IMG_HANDLE * phBuffer){
+
+ BC_DEVINFO *psDevInfo = NULL;
+ PVRSRV_ERROR ret = PVRSRV_ERROR_INVALID_PARAMS;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == hDevice || NULL == phBuffer){
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (BC_DEVINFO *) hDevice;
+
+ EMGD_DEBUG("Device - 0x%lx, Device ID - %lu, Buffer ID - %lu\n",
+ (unsigned long)psDevInfo,
+ psDevInfo->Device_ID,
+ ui32BufferNumber);
+
+ if (ui32BufferNumber < psDevInfo->sBufferInfo.ui32BufferCount) {
+ psDevInfo->psSystemBuffer[ui32BufferNumber].psSyncData = psSyncData;
+ *phBuffer = (IMG_HANDLE) &psDevInfo->psSystemBuffer[ui32BufferNumber];
+ EMGD_DEBUG("Assign System Buffer address - 0x%lx to phBuffer", (unsigned long)(*phBuffer));
+ ret = PVRSRV_OK;
+ } else {
+ EMGD_ERROR("PVRSRV_ERROR_INVALID_PARAMS\n");
+ ret= PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return ret;
+}
+
+static PVRSRV_ERROR GetBCInfo(IMG_HANDLE hDevice, BUFFER_INFO *psBCInfo){
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (!hDevice || !psBCInfo){
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (BC_DEVINFO *)hDevice;
+
+ EMGD_DEBUG("psDevInfo - 0x%lx, Device ID - %lu", (unsigned long)psDevInfo, psDevInfo->Device_ID);
+
+ memcpy((void *)psBCInfo, (void *)&psDevInfo->sBufferInfo, sizeof(BUFFER_INFO));
+
+ EMGD_TRACE_EXIT;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCBufferAddr (IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_SYS_PHYADDR ** ppsSysAddr,
+ IMG_UINT32 * pui32ByteSize,
+ IMG_VOID ** ppvCpuVAddr,
+ IMG_HANDLE * phOSMapInfo,
+ IMG_BOOL * pbIsContiguous, IMG_BOOL *pbMapped){
+ BC_BUFFER *psBuffer;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == hDevice || NULL == hBuffer){
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psBuffer = (BC_BUFFER *)hBuffer;
+
+ if (IMG_NULL != pbMapped) {
+
+ if(psBuffer->mapped)
+ *pbMapped = IMG_TRUE;
+ else
+ *pbMapped = IMG_FALSE;
+ }
+
+
+ EMGD_DEBUG("Buffer 0x%lx", (IMG_UINT32)psBuffer);
+ if (NULL != ppsSysAddr) {
+ *ppsSysAddr = psBuffer->psSysAddr;
+ }
+ if (NULL != pui32ByteSize) {
+ *pui32ByteSize = (IMG_UINT32)psBuffer->ulSize;
+ }
+ if (NULL != ppvCpuVAddr) {
+ *ppvCpuVAddr = psBuffer->sCPUVAddr;
+ }
+
+ if (NULL != phOSMapInfo) {
+ *phOSMapInfo = IMG_NULL;
+ }
+
+ if (NULL != pbIsContiguous) {
+ *pbIsContiguous = psBuffer->is_conti_addr;
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR GetBCBufferIdFromTag(IMG_HANDLE hDevice, IMG_UINT32 tag, IMG_HANDLE idx){
+ BC_DEVINFO *psDevInfo = NULL;
+ IMG_UINT32 i = 0;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == hDevice || NULL == idx){
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (BC_DEVINFO *)hDevice;
+
+ EMGD_DEBUG("hDevice - 0x%lx, Device ID - %lu", (unsigned long)psDevInfo, psDevInfo->Device_ID);
+
+ for (i = 0; i < psDevInfo->sBufferInfo.ui32BufferCount; i++) {
+ if (psDevInfo->psSystemBuffer[i].tag == tag) {
+ EMGD_DEBUG("Found the Buffer: Id - %lu, Tag - %lu", i, tag);
+ *((IMG_UINT32 *) idx) = i;
+ break;
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return (PVRSRV_OK);
+}
+
+emgd_error_t bc_ts_init(IMG_UINT32 id) {
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ psDevInfo = GetAnchorPtr(id);
+
+ if (psDevInfo == NULL){
+ EMGD_DEBUG("To Allocate Device with Index - %lu", id);
+ psDevInfo = (BC_DEVINFO *)BCAllocKernelMem(sizeof(BC_DEVINFO));
+ EMGD_DEBUG("psDevInfo - %lx", (unsigned long)psDevInfo);
+ if (NULL == psDevInfo){
+ return (EMGD_ERROR_OUT_OF_MEMORY);
+ }
+ memset((void *)psDevInfo, 0, sizeof(BC_DEVINFO));
+
+ psDevInfo->Device_ID = id; /* device index amond device list */
+ psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+
+ SetAnchorPtr((void *)psDevInfo, id);
+
+ if (BCOpenPVRServices(&psDevInfo->hPVRServices) != EMGD_OK){
+ return (EMGD_ERROR_INIT_FAILURE);
+ }
+ /* Initialize PVR JTable Function */
+ if (BCGetLibFuncAddr(psDevInfo->hPVRServices, "PVRGetBufferClassJTable",
+ &pfnGetPVRJTable) != EMGD_OK) {
+ return (EMGD_ERROR_INIT_FAILURE);
+ }
+
+ if (!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable)){
+ return (EMGD_ERROR_INIT_FAILURE);
+ }
+ if (TSBUFFERCLASS_DEV_NAME_LEN < 0) {
+ EMGD_ERROR("BufferClass Device Name Space is too small!");
+ return EMGD_ERROR_INIT_FAILURE;
+ }
+ strncpy(psDevInfo->sBufferInfo.szDeviceName, TSBUFFERCLASS_DEVICE_NAME, TSBUFFERCLASS_DEV_NAME_LEN);
+ /* Initialize BC JTable */
+ psDevInfo->sBCJTable.ui32TableSize = sizeof (PVRSRV_BC_SRV2BUFFER_KMJTABLE);
+
+ psDevInfo->sBCJTable.pfnOpenBCDevice = (PFN_OPEN_BC_DEVICE)OpenBCDevice;
+ psDevInfo->sBCJTable.pfnCloseBCDevice = (PFN_CLOSE_BC_DEVICE)CloseBCDevice;
+ psDevInfo->sBCJTable.pfnGetBCBuffer = (PFN_GET_BC_BUFFER)GetBCBuffer;
+ psDevInfo->sBCJTable.pfnGetBCInfo = (PFN_GET_BC_INFO)GetBCInfo;
+ psDevInfo->sBCJTable.pfnGetBufferAddr = (PFN_GET_BUFFER_ADDR)GetBCBufferAddr;
+ psDevInfo->sBCJTable.pfnGetBufferIdFromTag = (PFN_GET_BUFFER_ID_FROM_TAG)GetBCBufferIdFromTag;
+
+ if (PVRSRV_OK != psDevInfo->sPVRJTable.pfnPVRSRVRegisterBCDevice(&psDevInfo->sBCJTable,
+ &(psDevInfo->Device_ID))){
+ return (EMGD_ERROR_DEVICE_REGISTER_FAILED);
+ } else {
+ EMGD_DEBUG("Got Device ID - %lu", psDevInfo->Device_ID);
+ }
+ } else {
+ EMGD_ERROR("Duplicate register Device - %lu", psDevInfo->Device_ID);
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return (EMGD_OK);
+}
+emgd_error_t bc_ts_uninit(IMG_UINT32 id) {
+ BC_DEVINFO *psDevInfo = NULL;
+ int i = 0;
+
+ EMGD_TRACE_ENTER;
+
+ psDevInfo = (BC_DEVINFO *)GetAnchorPtr(id);
+
+ if (psDevInfo == NULL){
+ return (EMGD_ERROR_GENERIC);
+ }
+ EMGD_DEBUG("To Unregister the Device: ID - %lu, RefCount - %lu, idx - %lu",
+ psDevInfo->Device_ID,
+ psDevInfo->ulRefCount,
+ psDevInfo->sBufferInfo.ui32BufferDeviceID);
+
+ if (id != psDevInfo->sBufferInfo.ui32BufferDeviceID) {
+ EMGD_ERROR("Index mis-matcheh input idx vs. device idx: %lu vs. %lu", id, psDevInfo->sBufferInfo.ui32BufferDeviceID);
+ }
+
+ if (0 != psDevInfo->ulRefCount) {
+ psDevInfo->ulRefCount--;
+ }
+
+ if (1 /*psDevInfo->ulRefCount == 0*/){
+ PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
+
+ if (psJTable->pfnPVRSRVRemoveBCDevice(psDevInfo->Device_ID) !=
+ PVRSRV_OK) {
+ return (EMGD_ERROR_GENERIC);
+ }
+
+ if (BCClosePVRServices(psDevInfo->hPVRServices) != EMGD_OK){
+ psDevInfo->hPVRServices = NULL;
+ return (EMGD_ERROR_GENERIC);
+ }
+ if (NULL != psDevInfo->psSystemBuffer) {
+ for (i = 0; i < BUFCLASS_BUFFER_MAX; i++) {
+ bc_ts_free_bcbuffer(&(psDevInfo->psSystemBuffer[i]));
+ }
+ BCFreeKernelMem(psDevInfo->psSystemBuffer);
+ }
+ BCFreeKernelMem(psDevInfo);
+
+ SetAnchorPtr(NULL, id);
+ bc_video_id_usage[id] = 0;
+ }
+ EMGD_TRACE_EXIT;
+
+ return (EMGD_OK);
+}
+void bc_ts_free_bcbuffer(BC_BUFFER *bc_buf) {
+ if (NULL == bc_buf) {
+ return;
+ }
+
+ BCFreeKernelMem(bc_buf->psSysAddr);
+ bc_buf->psSysAddr = NULL;
+#if 0 /* Cause Kernel Error */
+ BCFreeKernelMem(bc_buf->psSyncData);
+ bc_buf->psSyncData = NULL;
+#endif
+ return;
+}
+
+void *BCAllocKernelMem (unsigned long ulSize){
+ return vmalloc(ulSize); /* kmalloc*/
+}
+
+void BCFreeKernelMem(void *pvMem){
+ if (NULL != pvMem) { /* kfree -> vfree*/
+ vfree(pvMem);
+ }
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
new file mode 100755
index 0000000..9fad016
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
@@ -0,0 +1,174 @@
+/**********************************************************************
+ *
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#ifndef __EMGD_BC__H__
+#define __EMGD_BC__H__
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kernelbuffer.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+ enum BC_memory
+ {
+ BC_MEMORY_MMAP = 1,
+ BC_MEMORY_USERPTR = 2,
+ };
+
+ /*
+ * the following types are tested for fourcc in struct bc_buf_params_t
+ * NV12
+ * UYVY
+ * RGB565 - not tested yet
+ * YUYV
+ */
+ typedef struct bc_buf_params
+ {
+ int count; /*number of buffers, [in/out] */
+ int width; /*buffer width in pixel, multiple of 8 or 32 */
+ int height; /*buffer height in pixel */
+ int stride;
+ unsigned int fourcc; /*buffer pixel format */
+ enum BC_memory type;
+ } bc_buf_params_t;
+
+ extern IMG_IMPORT IMG_BOOL
+ PVRGetBufferClassJTable (PVRSRV_BC_BUFFER2SRV_KMJTABLE * psJTable);
+
+#define BUFCLASS_DEVICE_MAX_ID 6
+#define BUFCLASS_BUFFER_MAX 64
+/*
+** Device Name Space is for device name, steam tag and device state.
+** Format
+** [Name]...[Video ID][Device Status]
+** From Device Name Space tail,
+** Device Status - one Byte
+** Video ID - four Byte
+** Device Name - variation according to device name set.
+*/
+#define TSBUFFERCLASS_DEV_NAME_LEN (MAX_BUFFER_DEVICE_NAME_SIZE - sizeof(IMG_UINT32) - sizeof(IMG_CHAR) - 1)
+#define TSBUFFERCLASS_VIDEOID_OFFSET (MAX_BUFFER_DEVICE_NAME_SIZE - sizeof(IMG_UINT32) - sizeof(IMG_CHAR))
+#define TSBUFFERCLASS_DEVSTATUS_OFFSET (MAX_BUFFER_DEVICE_NAME_SIZE - sizeof(IMG_CHAR))
+
+ typedef void *BCE_HANDLE;
+
+ typedef enum tag_bce_bool
+ {
+ BCE_FALSE = 0,
+ BCE_TRUE = 1,
+ } BCE_BOOL, *BCE_PBOOL;
+
+ typedef struct BC_BUFFER_TAG
+ {
+ IMG_UINT32 ulSize;
+ IMG_HANDLE hMemHandle;
+
+ IMG_SYS_PHYADDR *psSysAddr;
+ IMG_UINT32 SysAddr;
+
+ IMG_CPU_VIRTADDR sCPUVAddr;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ struct BC_BUFFER_TAG *psNext;
+ IMG_UINT32 sBufferHandle;
+ IMG_BOOL is_conti_addr;
+ IMG_UINT32 tag; /* Buffer Tag. -- Surface ID*/
+ IMG_BOOL mapped;
+ } BC_BUFFER;
+
+ typedef struct BC_DEVINFO_TAG
+ {
+ BC_BUFFER *psSystemBuffer;
+ PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
+ PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
+ BCE_HANDLE hPVRServices;
+ IMG_UINT32 ulRefCount;
+ BUFFER_INFO sBufferInfo;
+ enum BC_memory buf_type;
+ IMG_UINT32 Device_ID;
+ } BC_DEVINFO;
+
+ typedef enum emgd_bc_error_
+ {
+ EMGD_OK = 0,
+ EMGD_ERROR_GENERIC = 1,
+ EMGD_ERROR_OUT_OF_MEMORY = 2,
+ EMGD_ERROR_TOO_FEW_BUFFERS = 3,
+ EMGD_ERROR_INVALID_PARAMS = 4,
+ EMGD_ERROR_INIT_FAILURE = 5,
+ EMGD_ERROR_CANT_REGISTER_CALLBACK = 6,
+ EMGD_ERROR_INVALID_DEVICE = 7,
+ EMGD_ERROR_DEVICE_REGISTER_FAILED = 8,
+ EMGD_ERROR_NO_PRIMARY = 9
+ } emgd_error_t;
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+#if 0
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+emgd_error_t bc_ts_init(IMG_UINT32 id);
+emgd_error_t bc_ts_uninit(IMG_UINT32 id);
+
+emgd_error_t BCOpenPVRServices(BCE_HANDLE * phPVRServices);
+emgd_error_t BCClosePVRServices(BCE_HANDLE hPVRServices);
+
+void *BCAllocKernelMem(unsigned long ulSize);
+void BCFreeKernelMem(void *pvMem);
+#if 0
+ BCE_ERROR BCAllocDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ * phMemHandle,
+ IMG_CPU_VIRTADDR * pLinAddr,
+ IMG_SYS_PHYADDR ** ppPhysAddr);
+
+ void BCFreeDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr,
+ IMG_SYS_PHYADDR * pPhysAddr);
+
+ IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr);
+ IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr);
+
+ void *MapPhysAddr(IMG_SYS_PHYADDR sSysAddr, unsigned long ulSize);
+ void UnMapPhysAddr(void *pvAddr, unsigned long ulSize);
+#endif
+emgd_error_t BCGetLibFuncAddr(BCE_HANDLE hExtDrv, char *szFunctionName,
+ PFN_BC_GET_PVRJTABLE * ppfnFuncTable);
+BC_DEVINFO *GetAnchorPtr(int id);
+
+void bc_ts_free_bcbuffer(BC_BUFFER *bc_buf);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
new file mode 100755
index 0000000..65a5162
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
@@ -0,0 +1,1055 @@
+/****************************************************************************
+ *
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************/
+
+#define MODULE_NAME hal.buf_class
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#if 0
+#if defined(LMA)
+#include <linux/pci.h>
+#else
+#include <linux/dma-mapping.h>
+#endif
+#endif
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "emgd_drv.h"
+#include "io.h"
+#include "pvrmodule.h"
+#include "emgd_drm.h"
+#include "igd_gmm.h"
+#include "emgd_bc.h"
+#if 0
+#define DEVNAME "bc_video"
+#define DRVNAME DEVNAME
+#endif
+#define BC_FOURCC(a,b,c,d) \
+ ((unsigned long) ((a) | (b)<<8 | (c)<<16 | (d)<<24))
+
+#define BC_PIX_FMT_NV12 BC_FOURCC('N', 'V', '1', '2') /*YUV 4:2:0 */
+#define BC_PIX_FMT_UYVY BC_FOURCC('U', 'Y', 'V', 'Y') /*YUV 4:2:2 */
+#define BC_PIX_FMT_YUYV BC_FOURCC('Y', 'U', 'Y', 'V') /*YUV 4:2:2 */
+#define BC_PIX_FMT_RGB565 BC_FOURCC('R', 'G', 'B', 'P') /*RGB 5:6:5 */
+#define BC_PIX_FMT_ARGB BC_FOURCC('A','R', 'G', 'B') /*ARGB*/
+#define BC_PIX_FMT_xRGB BC_FOURCC('x','R', 'G', 'B') /*xRGB*/
+#define BC_PIX_FMT_RGB4 BC_FOURCC('R', 'G', 'B', '4') /*RGB4*/
+#if 0
+#if defined(BCE_USE_SET_MEMORY)
+#undef BCE_USE_SET_MEMORY
+#endif
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) && defined(SUPPORT_LINUX_X86_PAT) && defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+#include <asm/cacheflush.h>
+#define BCE_USE_SET_MEMORY
+#endif
+
+static int width_align;
+#endif
+extern unsigned int bc_video_id[BUFCLASS_DEVICE_MAX_ID];
+extern unsigned int bc_video_id_usage[BUFCLASS_DEVICE_MAX_ID];
+extern void* gp_bc_Anchor[BUFCLASS_DEVICE_MAX_ID];
+
+/* Stream Tag. To be stored on Buffer class name array. */
+#define MAX_STREAM_TAG 0xFFFFFFF0
+unsigned long bc_stream_tag = 0;
+
+typedef enum _BC_DEVICE_STATE {
+ BC_DEV_READY = 0xF0,
+ BC_DEV_NOT_READY,
+} BC_Dev_Status;
+
+#if 0
+MODULE_SUPPORTED_DEVICE (DEVNAME);
+
+int FillBuffer(unsigned int uiBufferIndex);
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+static struct class *psPvrClass;
+#endif
+
+static int AssignedMajorNumber;
+
+#define unref__ __attribute__ ((unused))
+
+#if defined(LMA)
+#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
+#define PVR_BUFFERCLASS_MEMSIZE (4 * 1024 * 1024)
+
+unsigned long g_ulMemBase = 0;
+unsigned long g_ulMemCurrent = 0;
+
+#define VENDOR_ID_PVR 0x1010
+#define DEVICE_ID_PVR 0x1CF1
+
+#define PVR_MEM_PCI_BASENUM 2
+#endif
+
+#define file_to_id(file) (iminor(file->f_path.dentry->d_inode))
+#endif
+/* FCB #17711*/
+/* flag indicates whether BC_Video Module Initialized or not
+* 0 - Uninitialized, 1 - Initialized.
+*/
+static int flg_bc_ts_init = 0;
+
+/*
+** Function: Set device state
+** state: 0 - enable; 1 - disable
+*/
+void emgd_bc_ts_set_state(BC_DEVINFO *psDevInfo, const IMG_CHAR state);
+
+int emgd_bc_ts_init(void){
+ int i, j;
+#if 0
+ /*LDM_PCI is defined, while LDM_PLATFORM and LMA are not defined.*/
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ struct device *psDev;
+#endif
+
+#if defined(LMA)
+ struct pci_dev *psPCIDev;
+ int error;
+#endif
+#endif
+ EMGD_TRACE_ENTER;
+
+ if (0 != flg_bc_ts_init) {
+ EMGD_ERROR("BC already been initialized!");
+ return 0;
+ }
+#if 0
+ /* video width is 4 byte aligned */
+ width_align = 4;
+#endif
+ memset(bc_video_id, 0, sizeof(bc_video_id));
+ memset(bc_video_id_usage, 0, sizeof(bc_video_id_usage));
+ memset(gp_bc_Anchor, 0, sizeof(gp_bc_Anchor));
+#if 0
+#if defined(LMA)
+ psPCIDev = pci_get_device (VENDOR_ID_PVR, DEVICE_ID_PVR, NULL);
+ if (psPCIDev == NULL){
+ EMGD_ERROR("pci_get_device failed");
+ goto ExitError;
+ }
+
+ if ((error = pci_enable_device (psPCIDev)) != 0){
+ EMGD_ERROR("pci_enable_device failed (%d)", error);
+ goto ExitError;
+ }
+#endif
+#endif
+#if 0
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ psPvrClass = class_create(THIS_MODULE, "bc_video");
+ if (IS_ERR (psPvrClass)) {
+ EMGD_ERROR("unable to create class (%ld)",
+ PTR_ERR(psPvrClass));
+ goto ExitUnregister;
+ }
+
+ psDev = device_create (psPvrClass, NULL, MKDEV (AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DEVNAME);
+ if (IS_ERR (psDev)){
+ EMGD_ERROR("unable to create device (%ld)",
+ PTR_ERR (psDev));
+ goto ExitDestroyClass;
+ }
+#endif
+
+#if defined(LMA)
+ g_ulMemBase =
+ pci_resource_start (psPCIDev,
+ PVR_MEM_PCI_BASENUM) + PVR_BUFFERCLASS_MEMOFFSET;
+#endif
+#endif
+ for (i = 0; i < BUFCLASS_DEVICE_MAX_ID; i++) {
+ bc_video_id[i] = i;
+ bc_video_id_usage[i] = 0;
+ if (bc_ts_init(bc_video_id[i]) != EMGD_OK) {
+ EMGD_ERROR("can't init video bc device %d.", i);
+ for (j = i; j >= 0; j--) {
+ bc_ts_uninit(bc_video_id[j]);
+ }
+ goto ExitUnregister;
+ }
+ }
+#if 0
+#if defined(LMA)
+ pci_disable_device (psPCIDev);
+#endif
+#endif
+ flg_bc_ts_init = 1;
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+#if 0
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ExitDestroyClass:
+ class_destroy (psPvrClass);
+#endif
+#endif
+ExitUnregister:
+#if 0
+ unregister_chrdev (AssignedMajorNumber, DEVNAME);
+ //ExitDisable:
+#if defined(LMA)
+ pci_disable_device (psPCIDev);
+ExitError:
+#endif
+#endif
+ return -EBUSY;
+}
+
+int emgd_bc_ts_uninit(void){
+ int i = 0;
+#if 0
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ device_destroy (psPvrClass, MKDEV (AssignedMajorNumber, 0));
+ class_destroy (psPvrClass);
+#endif
+#endif
+ EMGD_TRACE_ENTER;
+
+ if (1 != flg_bc_ts_init) {
+ EMGD_ERROR("BC not been initialized yet");
+ return 0;
+ }
+
+ for (i = 0; i < BUFCLASS_DEVICE_MAX_ID; i++){
+ if (1 == bc_video_id_usage[i]) {
+ if (bc_ts_uninit(bc_video_id[i]) != EMGD_OK) {
+ EMGD_ERROR("can't deinit video device %d.", i);
+ return -1;
+ }
+ }
+ }
+
+ flg_bc_ts_init = 0;
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+#if 0
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#define VMALLOC_TO_PAGE_PHYS(vAddr) page_to_phys(vmalloc_to_page(vAddr))
+
+BCE_ERROR BCAllocDiscontigMemory (unsigned long ulSize,
+ BCE_HANDLE unref__ *phMemHandle,
+ IMG_CPU_VIRTADDR *pLinAddr,
+ IMG_SYS_PHYADDR **ppPhysAddr){
+ unsigned long ulPages = RANGE_TO_PAGES (ulSize);
+ IMG_SYS_PHYADDR *pPhysAddr = IMG_NULL;
+ unsigned long ulPage = 0;
+ IMG_CPU_VIRTADDR LinAddr = IMG_NULL;
+
+ EMGD_TRACE_ENTER;
+
+ LinAddr =
+ __vmalloc (ulSize, GFP_KERNEL | __GFP_HIGHMEM,
+ pgprot_noncached (PAGE_KERNEL));
+ if (!LinAddr){
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+
+ pPhysAddr = vmalloc (ulPages * sizeof (IMG_SYS_PHYADDR));
+ if (!pPhysAddr) {
+ vfree(LinAddr);
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pLinAddr = LinAddr;
+
+ for (ulPage = 0; ulPage < ulPages; ulPage++){
+ pPhysAddr[ulPage].uiAddr = VMALLOC_TO_PAGE_PHYS (LinAddr);
+
+ LinAddr += PAGE_SIZE;
+ }
+
+ *ppPhysAddr = pPhysAddr;
+ EMGD_TRACE_EXIT;
+
+ return BCE_OK;
+}
+
+void BCFreeDiscontigMemory (unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr, IMG_SYS_PHYADDR * pPhysAddr){
+
+ BCFreeKernelMem(pPhysAddr);
+
+ if (NULL != LinAddr) {
+ vfree(LinAddr);
+ }
+}
+
+BCE_ERROR BCAllocContigMemory (unsigned long ulSize,
+ BCE_HANDLE unref__ *phMemHandle,
+ IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr){
+#if defined(LMA)
+ void *pvLinAddr = NULL;
+
+ if (g_ulMemCurrent + ulSize >= PVR_BUFFERCLASS_MEMSIZE){
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pvLinAddr = ioremap(g_ulMemBase + g_ulMemCurrent, ulSize);
+
+ if (pvLinAddr)
+ {
+ pPhysAddr->uiAddr = g_ulMemBase + g_ulMemCurrent;
+ *pLinAddr = pvLinAddr;
+
+ g_ulMemCurrent += ulSize;
+ return (BCE_OK);
+ }
+ return (BCE_ERROR_OUT_OF_MEMORY);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+ void *pvLinAddr = NULL;
+ unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
+ int iPages = (int) (ulAlignedSize >> PAGE_SHIFT);
+ int iError;
+
+ pvLinAddr = kmalloc(ulAlignedSize, GFP_KERNEL);
+ if(!pvLinAddr) {
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+ BUG_ON (((unsigned long) pvLinAddr) & ~PAGE_MASK);
+
+ iError = set_memory_wc((unsigned long) pvLinAddr, iPages);
+ if (iError != 0){
+ EMGD_ERROR("set_memory_wc failed (%d)", iError);
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pPhysAddr->uiAddr = virt_to_phys (pvLinAddr);
+ *pLinAddr = pvLinAddr;
+
+ return (BCE_OK);
+#else
+ dma_addr_t dma;
+ void *pvLinAddr = NULL;
+
+ pvLinAddr = dma_alloc_coherent (NULL, ulSize, &dma, GFP_KERNEL);
+ if (NULL == pvLinAddr){
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pPhysAddr->uiAddr = dma;
+ *pLinAddr = pvLinAddr;
+
+ return (BCE_OK);
+#endif
+#endif
+}
+
+void BCFreeContigMemory (unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr){
+#if defined(LMA)
+ g_ulMemCurrent -= ulSize;
+ iounmap(LinAddr);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+ unsigned long ulAlignedSize = PAGE_ALIGN (ulSize);
+ int iError;
+ int iPages = (int) (ulAlignedSize >> PAGE_SHIFT);
+
+ iError = set_memory_wb ((unsigned long) LinAddr, iPages);
+ if (iError != 0) {
+ EMGD_ERROR("set_memory_wb failed (%d)", iError);
+ }
+ BCFreeKernelMem(LinAddr);
+#else
+ dma_free_coherent (NULL, ulSize, LinAddr, (dma_addr_t)PhysAddr.uiAddr);
+#endif
+#endif
+}
+
+IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC (IMG_CPU_PHYADDR cpu_paddr){
+ IMG_SYS_PHYADDR sys_paddr;
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC (IMG_SYS_PHYADDR sys_paddr){
+ IMG_CPU_PHYADDR cpu_paddr;
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+#endif
+emgd_error_t BCOpenPVRServices (BCE_HANDLE * phPVRServices){
+ *phPVRServices = 0;
+ return (EMGD_OK);
+}
+
+
+emgd_error_t BCClosePVRServices (BCE_HANDLE unref__ hPVRServices){
+ return (EMGD_OK);
+}
+
+emgd_error_t BCGetLibFuncAddr (BCE_HANDLE unref__ hExtDrv, char *szFunctionName,
+ PFN_BC_GET_PVRJTABLE * ppfnFuncTable) {
+ if (strcmp ("PVRGetBufferClassJTable", szFunctionName) != 0){
+ return (EMGD_ERROR_INVALID_PARAMS);
+ }
+
+ *ppfnFuncTable = PVRGetBufferClassJTable;
+
+ return (EMGD_OK);
+}
+
+int BC_CreateBuffers(BC_DEVINFO *psDevInfo, bc_buf_params_t *p, IMG_BOOL is_conti_addr) {
+ IMG_UINT32 i = 0, j = 0;
+ IMG_UINT32 stride = 0;
+ IMG_UINT32 size = 0;
+ PVRSRV_PIXEL_FORMAT pixel_fmt = 0;
+ BC_BUFFER *bufnode = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (p->count < 1) {
+ return -1;
+ }
+
+ if (p->count > BUFCLASS_BUFFER_MAX) {
+ return -1;
+ }
+
+ if (p->width <= 1 || p->height <= 1 || p->stride <=1 ) {
+ return -1;
+ }
+
+ if (p->width > 2048 || p->height > 1536 || p->stride >2048*4) {
+ return -1;
+ }
+
+ switch (p->fourcc) {
+ case BC_PIX_FMT_NV12:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_NV12;
+ break;
+ case BC_PIX_FMT_UYVY:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY;
+ break;
+ case BC_PIX_FMT_RGB565:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_RGB565;
+ p->stride = p->stride << 1; /* stride for RGB from user space is uncorrect */
+ break;
+ case BC_PIX_FMT_YUYV:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV;
+ break;
+ case BC_PIX_FMT_ARGB:
+ case BC_PIX_FMT_RGB4:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_ARGB8888;
+ break;
+ case BC_PIX_FMT_xRGB:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_XRGB8888;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ stride = p->stride;
+
+ if (p->type != BC_MEMORY_MMAP && p->type != BC_MEMORY_USERPTR) {
+ return -1;
+ }
+
+ if (0 == psDevInfo->sBufferInfo.ui32BufferCount && NULL == psDevInfo->psSystemBuffer) {
+ psDevInfo->psSystemBuffer = (BC_BUFFER *)BCAllocKernelMem(sizeof(BC_BUFFER) * BUFCLASS_BUFFER_MAX);
+ if (NULL != psDevInfo->psSystemBuffer) {
+ memset((void *)psDevInfo->psSystemBuffer, 0, sizeof(BC_BUFFER) * BUFCLASS_BUFFER_MAX);
+ } else {
+ return -1;
+ }
+ } else {
+
+ if ((psDevInfo->sBufferInfo.ui32BufferCount + p->count) > BUFCLASS_BUFFER_MAX) {
+ EMGD_ERROR("No avaiable Buffers");
+ return -1;
+ }
+ }
+
+ if (0 != psDevInfo->sBufferInfo.ui32BufferCount) {
+ if (psDevInfo->sBufferInfo.ui32Width != p->width
+ || psDevInfo->sBufferInfo.ui32Height != p->height
+ || psDevInfo->sBufferInfo.ui32ByteStride != p->stride
+ || psDevInfo->sBufferInfo.pixelformat != pixel_fmt
+ || psDevInfo->buf_type != p->type) {
+
+ EMGD_ERROR("Request invalid buffers");
+ return -ENODEV;
+ }
+ }
+
+ psDevInfo->buf_type = p->type;
+
+ size = p->height * stride;
+
+ if (pixel_fmt == PVRSRV_PIXEL_FORMAT_NV12) {
+ size += (stride >> 1) * (p->height >> 1) << 1;
+ }
+
+ /* Append new nodes*/
+ for (i = 0; i < p->count; i++) {
+ bufnode = &(psDevInfo->psSystemBuffer[psDevInfo->sBufferInfo.ui32BufferCount + i]);
+ EMGD_DEBUG("Buffer idx - %lu", psDevInfo->sBufferInfo.ui32BufferCount + i);
+ bufnode->ulSize = size;
+ EMGD_DEBUG("Buffer size - %lu", size);
+
+ bufnode->tag = psDevInfo->sBufferInfo.ui32BufferCount + i;
+
+ bufnode->psSyncData = NULL;
+
+ bufnode->is_conti_addr = is_conti_addr;
+ EMGD_DEBUG("Buffer IsCont. - %d", is_conti_addr);
+
+ bufnode->psNext = NULL;
+ if (is_conti_addr){
+ bufnode->psSysAddr = (IMG_SYS_PHYADDR *)BCAllocKernelMem (sizeof(IMG_SYS_PHYADDR));
+ if (NULL == bufnode->psSysAddr) {
+ /* Free the previously successfully allocated memeory */
+ for(j=0;j<i;j++) {
+ bufnode =
+ &(psDevInfo->psSystemBuffer[psDevInfo->sBufferInfo.ui32BufferCount + j]);
+ bc_ts_free_bcbuffer(bufnode);
+ }
+ return EMGD_ERROR_OUT_OF_MEMORY;
+ }
+ memset(bufnode->psSysAddr, 0, sizeof(IMG_SYS_PHYADDR));
+ } else {
+ return EMGD_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ if (0 == psDevInfo->sBufferInfo.ui32BufferCount) {
+ psDevInfo->sBufferInfo.pixelformat = pixel_fmt;
+ psDevInfo->sBufferInfo.ui32Width = p->width;
+ psDevInfo->sBufferInfo.ui32Height = p->height;
+ psDevInfo->sBufferInfo.ui32ByteStride = stride;
+ psDevInfo->sBufferInfo.ui32Flags = PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE |
+ PVRSRV_BC_FLAGS_YUVCSC_BT601;
+ }
+
+ psDevInfo->sBufferInfo.ui32BufferCount += p->count;
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+int BC_DestroyBuffers(void *psDevInfo) {
+ BC_DEVINFO *DevInfo = NULL;
+ IMG_UINT32 i = 0;
+ BC_BUFFER *bufnode = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psDevInfo) {
+ return -1;
+ }
+
+ DevInfo = (BC_DEVINFO *)psDevInfo;
+ EMGD_DEBUG("To Free %lu buffers", DevInfo->sBufferInfo.ui32BufferCount);
+
+ if (DevInfo->sBufferInfo.ui32BufferCount > BUFCLASS_BUFFER_MAX) {
+ EMGD_ERROR("Wrong number of buffers");
+ }
+
+ for (i = 0; i < DevInfo->sBufferInfo.ui32BufferCount; i++) {
+ if(i < BUFCLASS_BUFFER_MAX) {
+ bufnode = &(DevInfo->psSystemBuffer[i]);
+ bc_ts_free_bcbuffer(bufnode);
+ }
+ }
+ BCFreeKernelMem(DevInfo->psSystemBuffer);
+ DevInfo->psSystemBuffer = NULL;
+
+ if (0 != DevInfo->ulRefCount) {
+ DevInfo->ulRefCount--;
+ }
+ DevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
+ DevInfo->sBufferInfo.ui32Width = 0;
+ DevInfo->sBufferInfo.ui32Height = 0;
+ DevInfo->sBufferInfo.ui32ByteStride = 0;
+ DevInfo->sBufferInfo.ui32Flags = 0;
+ DevInfo->sBufferInfo.ui32BufferCount = 0;
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+/*
+** For Buffer Class of Texture Stream
+*/
+static __inline int emgd_bc_ts_bridge_init(struct drm_device *drv, void* arg, struct drm_file *file_priv){
+ int err = -EFAULT;
+ int i;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *) arg;
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!\n");
+ return err;
+ }
+ psBridge->rtn = 1;
+
+ /* search available device */
+ for (i = 0; i < BUFCLASS_DEVICE_MAX_ID; i++) {
+ if (0 == bc_video_id_usage[i]) {
+ bc_video_id_usage[i] = 1;
+ psDevInfo = (BC_DEVINFO *)GetAnchorPtr(bc_video_id[i]);
+ if (NULL == psDevInfo) {
+ EMGD_ERROR("System Error");
+ return err;
+ }
+ psBridge->dev_id = psDevInfo->sBufferInfo.ui32BufferDeviceID;
+ if (MAX_STREAM_TAG == bc_stream_tag) {
+ bc_stream_tag = 0;
+ } else {
+ bc_stream_tag++;
+ }
+
+ *(IMG_UINT32 *)(psDevInfo->sBufferInfo.szDeviceName + TSBUFFERCLASS_VIDEOID_OFFSET) = bc_stream_tag;
+
+ /* Disable device*/
+ emgd_bc_ts_set_state(psDevInfo, 0);
+
+ EMGD_DEBUG("Grab a Device - 0x%lx , ID %lu, idx - %d\n",
+ (unsigned long)psDevInfo,
+ psBridge->dev_id,
+ bc_video_id[i]);
+ psBridge->rtn = 0;
+ err = 0;
+ break;
+ }
+ }
+
+ if (BUFCLASS_DEVICE_MAX_ID == i) {
+ EMGD_ERROR("Do you really need to run more than 6 video simulateously.");
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return err;
+}
+
+static __inline int emgd_bc_ts_bridge_uninit(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+ int i;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *) arg;
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!\n");
+ return err;
+ }
+
+ psDevInfo = (BC_DEVINFO *)GetAnchorPtr(psBridge->dev_id);
+ if (NULL == psDevInfo) {
+ EMGD_ERROR("System Error");
+ return err;
+ }
+
+ /* To disable buffer class device*/
+ emgd_bc_ts_set_state(psDevInfo, 0);
+
+ if (EMGD_OK == BC_DestroyBuffers((void *)psDevInfo)) {
+ EMGD_DEBUG("Free Device - %lu", psBridge->dev_id);
+ bc_video_id_usage[i] = 0,
+ psBridge->rtn = 0;
+ err = 0;
+ } else {
+ EMGD_ERROR("Uninit device with id %lu failure!\n", psBridge->dev_id);
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return err;
+}
+
+static __inline int emgd_bc_ts_bridge_request_buffers(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *) arg;
+ bc_buf_params_t p;
+ BC_DEVINFO *bc_devinfo = NULL;
+ IMG_BOOL is_continous = IMG_FALSE;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!\n");
+ return err;
+ }
+
+ is_continous = psBridge->is_continous ? IMG_TRUE : IMG_FALSE;
+
+ bc_devinfo = (BC_DEVINFO *)GetAnchorPtr(psBridge->dev_id);
+ if (NULL == bc_devinfo
+ || (NULL != bc_devinfo && psBridge->dev_id != bc_devinfo->sBufferInfo.ui32BufferDeviceID)) {
+ EMGD_ERROR("input device id is invalid");
+ return err;
+ }
+ if (NULL != bc_devinfo && 1 == bc_video_id_usage[bc_devinfo->sBufferInfo.ui32BufferDeviceID]) {
+ psBridge->buf_id = bc_devinfo->sBufferInfo.ui32BufferCount;
+ p.width = psBridge->width;
+ p.height = psBridge->height;
+ p.count = psBridge->num_buf;
+ p.fourcc = psBridge->pixel_format;
+ p.stride = psBridge->stride;
+ p.type = BC_MEMORY_MMAP;
+ if (0 == BC_CreateBuffers(bc_devinfo, &p, is_continous)) {
+ psBridge->rtn = 0;
+ err = 0;
+ } else {
+ EMGD_ERROR("Request Buffers failure!\n");
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return err;
+}
+
+static __inline int emgd_bc_ts_bridge_release_buffers(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *) arg;
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!\n");
+ return err;
+ }
+
+ psDevInfo = (BC_DEVINFO *)GetAnchorPtr(psBridge->dev_id);
+
+ if (NULL == psDevInfo
+ || (NULL != psDevInfo && psBridge->dev_id != psDevInfo->sBufferInfo.ui32BufferDeviceID)) {
+ EMGD_ERROR("input device id is invalid");
+ return err;
+ }
+
+ if (NULL != psDevInfo && 1 == bc_video_id_usage[psDevInfo->sBufferInfo.ui32BufferDeviceID]) {
+ emgd_bc_ts_set_state(psDevInfo, 0);
+
+ if (EMGD_OK == BC_DestroyBuffers((void *)psDevInfo)) {
+ psBridge->rtn = 0;
+ err = EMGD_OK;
+ } else {
+ EMGD_ERROR("Release Buffers failure!\n");
+ }
+ }
+ EMGD_TRACE_EXIT;
+
+ return EMGD_OK;
+}
+
+static __inline int emgd_bc_ts_bridge_set_buffer_info(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *) arg;
+ BC_DEVINFO *devinfo = IMG_NULL;
+ BC_BUFFER *bcBuf = NULL;
+ unsigned long virt=0;
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!");
+ return err;
+ }
+ psBridge->rtn = 1;
+
+ EMGD_DEBUG("dev_id %lu, buf_id %lu, buf_tag %lu, phyaddr 0x%lx, virtadd 0x%lx\n",
+ psBridge->dev_id,
+ psBridge->buf_id,
+ psBridge->buf_tag,
+ psBridge->phyaddr,
+ psBridge->virtaddr);
+
+ devinfo = (BC_DEVINFO *)GetAnchorPtr(psBridge->dev_id);
+
+ if (NULL == devinfo
+ || (NULL != devinfo && psBridge->dev_id != devinfo->sBufferInfo.ui32BufferDeviceID)) {
+ EMGD_ERROR("input device id is invalid");
+ return err;
+ }
+ /* To Set Buffer Class Device State */
+ if (0xFF == psBridge->buf_id && BUFCLASS_BUFFER_MAX < psBridge->buf_id) {
+ /* 0xFF - Indicates Buffer Class Device is ready. 0xF0 - not ready */
+ if (BC_DEV_READY == psBridge->buf_tag && 0 < devinfo->sBufferInfo.ui32BufferCount) {
+ emgd_bc_ts_set_state(devinfo, 1);
+ EMGD_DEBUG("dev_id %lu Enable to be Ready!\n", psBridge->dev_id);
+ goto SUCCESS_OK;
+ }
+ if (BC_DEV_NOT_READY == psBridge->buf_tag) {
+ emgd_bc_ts_set_state(devinfo, 0);
+ EMGD_DEBUG("dev_id %lu Disabled!\n", psBridge->dev_id);
+ goto SUCCESS_OK;
+ }
+ }
+
+ if (psBridge->buf_id >= devinfo->sBufferInfo.ui32BufferCount) {
+ EMGD_ERROR("Invalid buf_id");
+ return err;
+ }
+
+ bcBuf = &(devinfo->psSystemBuffer[psBridge->buf_id]);
+
+ if (NULL == bcBuf) {
+ EMGD_ERROR("Invalid buffer: buf_id - %lu!", psBridge->buf_id);
+ return err;
+ }
+ bcBuf->tag = psBridge->buf_tag;
+
+ bcBuf->sCPUVAddr = (IMG_CPU_VIRTADDR)psBridge->virtaddr;
+
+ if (IMG_FALSE == bcBuf->is_conti_addr) {
+ EMGD_ERROR("Only support conti. memory!");
+ } else {
+ if(!psBridge->mapped){
+
+ if(!psBridge->virtaddr) {
+ EMGD_ERROR("Invalid bridge address");
+ return err;
+ }
+ /*The CPU device will be registerd into PVR later*/
+ virt=((struct emgd_ci_meminfo_t *)(psBridge->virtaddr))->virt;
+ if(!virt) {
+ EMGD_ERROR("Invalid CPU address");
+ return err;
+ }
+ bcBuf->sCPUVAddr = virt;
+ bcBuf->psSysAddr[0].uiAddr = virt_to_phys(virt);
+
+ }else{
+ bcBuf->psSysAddr[0].uiAddr = psBridge->phyaddr;
+ }
+ }
+ bcBuf->mapped = psBridge->mapped;
+SUCCESS_OK:
+ psBridge->rtn = 0;
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+static __inline int emgd_bc_ts_bridge_get_buffers_count(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+ emgd_drm_bc_ts_t *psBridge = (emgd_drm_bc_ts_t *)arg;
+ BC_DEVINFO *psDevInfo = NULL;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == psBridge) {
+ EMGD_ERROR("Invalid input parameter!\n");
+ return err;
+ }
+
+ psBridge->rtn = 1;
+
+ psDevInfo = (BC_DEVINFO *)GetAnchorPtr(psBridge->dev_id);
+
+ if (NULL == psDevInfo
+ || (NULL != psDevInfo && psBridge->dev_id != psDevInfo->sBufferInfo.ui32BufferDeviceID)) {
+ EMGD_ERROR("input device id is invalid");
+ return err;
+ }
+
+ if (NULL != psDevInfo) {
+ psBridge->num_buf = psDevInfo->sBufferInfo.ui32BufferCount;
+ psBridge->rtn = 0;
+ err = 0;
+ }
+ EMGD_TRACE_EXIT;
+
+ return err;
+}
+
+static __inline int emgd_bc_ts_bridge_get_buffer_index(struct drm_device *drv, void* arg, struct drm_file *file_priv)
+{
+ EMGD_DEBUG("Not supported\n");
+ return 0;
+}
+
+/* For Buffer Class of Texture Stream */
+int emgd_bc_ts_cmd_init(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_init(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+int emgd_bc_ts_cmd_uninit(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_uninit(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+int emgd_bc_ts_cmd_request_buffers(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_request_buffers(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+
+}
+int emgd_bc_ts_cmd_release_buffers(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_release_buffers(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+
+}
+int emgd_bc_ts_set_buffer_info(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_set_buffer_info(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+int emgd_bc_ts_get_buffers_count(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_get_buffers_count(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+int emgd_bc_ts_get_buffer_index(struct drm_device *dev, void *arg, struct drm_file *file_priv)
+{
+ emgd_drm_bc_ts_t *drm_data = (emgd_drm_bc_ts_t *)arg;
+
+ EMGD_TRACE_ENTER;
+
+ if (NULL == dev || NULL == arg || NULL == file_priv) {
+ return 0;
+ }
+
+ drm_data->rtn = emgd_bc_ts_bridge_get_buffer_index(dev, drm_data, file_priv);
+
+ EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+ EMGD_DEBUG("Returning 0");
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+void emgd_bc_ts_set_state(BC_DEVINFO *psDevInfo, const IMG_CHAR state)
+{
+ if (NULL != psDevInfo) {
+ psDevInfo->sBufferInfo.szDeviceName[TSBUFFERCLASS_DEVSTATUS_OFFSET] = state;
+ }
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
new file mode 100644
index 0000000..3204ce6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
@@ -0,0 +1,2815 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+#define MODULE_NAME hal.pvr3dd
+
+#include <linux/spinlock.h>
+
+#include "drm_emgd_private.h"
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "emgd_dc.h"
+#include "emgd_drm.h"
+
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+
+/* Function to get the PVR services jump table */
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *jtable);
+
+#ifdef SUPPORT_FB_EVENTS
+static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo);
+static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo);
+#endif /* SUPPORT_FB_EVENTS */
+static void flush_flip_queue(emgddc_swapchain_t *swap_chain);
+static PVRSRV_ERROR do_mode_change(igd_context_t *context,
+ emgddc_devinfo_t *devinfo,
+ drm_emgd_priv_t *priv,
+ DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib);
+
+
+/* Special value used to register with the PVR services command queue: */
+#define EMGDDC_COMMAND_COUNT 1
+
+
+/**
+ * This is a pointer to the global emgddc_devinfo_t structure, used in various
+ * parts of this file.
+ */
+static emgddc_devinfo_t *global_devinfo[] = {NULL, NULL};
+
+
+/**
+ * Pairs of equivalent pixel formats, in EMGD and PVR formats:
+ */
+emgddc_pixelformat_translator_t known_pfs[] = {
+ /* 1 Byte-per-pixel [A]RGB Pixel Formats: */
+ {IGD_PF_ARGB8_INDEXED, PVRSRV_PIXEL_FORMAT_PAL8}, /* IMG numbered */
+ {IGD_PF_ARGB4_INDEXED, PVRSRV_PIXEL_FORMAT_PAL4}, /* IMG numbered */
+
+ /* 2 Byte-per-pixel [A]RGB Pixel Formats: */
+ {IGD_PF_ARGB16_4444, PVRSRV_PIXEL_FORMAT_ARGB4444}, /* IMG# & PVR2D-known */
+ {IGD_PF_ARGB16_1555, PVRSRV_PIXEL_FORMAT_ARGB1555}, /* IMG# & PVR2D-known */
+ {IGD_PF_RGB16_565, PVRSRV_PIXEL_FORMAT_RGB565}, /* IMG# & PVR2D-known */
+ {IGD_PF_xRGB16_555, PVRSRV_PIXEL_FORMAT_RGB555}, /* IMG numbered */
+
+ /* 3 Byte-per-pixel [A]RGB Pixel Formats: */
+ {IGD_PF_RGB24, PVRSRV_PIXEL_FORMAT_RGB888}, /* IMG numbered */
+
+ /* 4 Byte-per-pixel [A]RGB Pixel Formats: */
+ {IGD_PF_xRGB32_8888, PVRSRV_PIXEL_FORMAT_XRGB8888}, /* IMG numbered */
+ /* a.k.a. IGD_PF_ARGB32_8888 */
+ {IGD_PF_ARGB32, PVRSRV_PIXEL_FORMAT_ARGB8888}, /* IMG# & PVR2D-known */
+ {IGD_PF_xBGR32_8888, PVRSRV_PIXEL_FORMAT_XBGR8888}, /* IMG numbered */
+ {IGD_PF_ABGR32_8888, PVRSRV_PIXEL_FORMAT_ABGR8888}, /* IMG numbered */
+
+ /* YUV Packed Pixel Formats: */
+ {IGD_PF_YUV422_PACKED_YUY2, PVRSRV_PIXEL_FORMAT_YUY2},
+ {IGD_PF_YUV422_PACKED_YVYU, PVRSRV_PIXEL_FORMAT_YVYU},
+ {IGD_PF_YUV422_PACKED_UYVY, PVRSRV_PIXEL_FORMAT_UYVY},
+ {IGD_PF_YUV422_PACKED_VYUY, PVRSRV_PIXEL_FORMAT_VYUY},
+ /* UNKNOWN to IMG
+ {IGD_PF_YUV411_PACKED_Y41P, PVRSRV_PIXEL_FORMAT_UNKNOWN},
+ */
+
+ /* YUV Planar Pixel Formats: */
+ /* a.k.a. IGD_PF_YUV420_PLANAR_IYUV */
+ {IGD_PF_YUV420_PLANAR_I420, PVRSRV_PIXEL_FORMAT_I420},/* IMG numbered */
+ {IGD_PF_YUV420_PLANAR_YV12, PVRSRV_PIXEL_FORMAT_YV12},/* IMG numbered */
+ /* UNKNOWN to IMG
+ {IGD_PF_YUV410_PLANAR_YVU9, PVRSRV_PIXEL_FORMAT_UNKNOWN},
+ */
+ {IGD_PF_YUV420_PLANAR_NV12, PVRSRV_PIXEL_FORMAT_NV12},
+};
+unsigned int num_known_pfs =
+ sizeof(known_pfs) / sizeof(emgddc_pixelformat_translator_t);
+
+
+/**
+ * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
+ *
+ * @param emgd_pf (IN) EMGD-specific pixel format.
+ * @return Translated PVR-specific pixel format.
+ */
+static unsigned long pvr2emgd_pf(PVRSRV_PIXEL_FORMAT pvr_pf)
+{
+ int i;
+ for (i = 0 ; i < num_known_pfs ; i++) {
+ if (known_pfs[i].pvr_pf == pvr_pf) {
+ return known_pfs[i].emgd_pf;
+ }
+ }
+
+ /* If we get to here, we didn't find a known PVR pixel format: */
+ return IGD_PF_UNKNOWN;
+}
+
+
+/**
+ * Translate EMGD-specific pixel formats into PVR-specific pixel formats.
+ *
+ * @param emgd_pf (IN) EMGD-specific pixel format.
+ * @return Translated PVR-specific pixel format.
+ */
+static PVRSRV_PIXEL_FORMAT emgd2pvr_pf(unsigned long emgd_pf)
+{
+ int i;
+ for (i = 0 ; i < num_known_pfs ; i++) {
+ if (known_pfs[i].emgd_pf == emgd_pf) {
+ return known_pfs[i].pvr_pf;
+ }
+ }
+
+ /* If we get to here, we didn't find a known PVR pixel format: */
+ return IGD_PF_UNKNOWN;
+}
+
+
+/**
+ * Determines if the user-space-provided pointer (to a devinfo) is valid.
+ *
+ * @param devinfo (IN) The user-space-provided pointer to a devinfo.
+ */
+static int is_valid_devinfo(emgddc_devinfo_t *devinfo)
+{
+ if ((devinfo == global_devinfo[0]) || (devinfo == global_devinfo[1])) {
+ return 1;
+ } else {
+ return 0;
+ }
+} /* is_valid_devinfo() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnOpenDCDevice()
+ * function. This function is called when a client wants to use PVR services
+ * with the specified device.
+ *
+ * @param device_id (IN) The device_id associated with this device (i.e.
+ * obtained when emgddc_init() called
+ * PVRSRV_DC_DISP2SRV_KMJTABLE.pfnPVRSRVRegisterDCDevice()).
+ * @param device_h (OUT) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param system_buffer_sync_data (IN) Sync data for this device's system
+ * buffer.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 device_id,
+ IMG_HANDLE *device_h,
+ PVRSRV_SYNC_DATA* system_buffer_sync_data)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+
+
+ UNREFERENCED_PARAMETER(device_id);
+
+ /* Look up the device (for DIH/Extended mode): */
+ if (device_id == global_devinfo[0]->device_id) {
+ devinfo = global_devinfo[0];
+ EMGD_DEBUG("devinfo = global_devinfo[0] = 0x%p", devinfo);
+ } else if (device_id == global_devinfo[1]->device_id) {
+ devinfo = global_devinfo[1];
+ EMGD_DEBUG("devinfo = global_devinfo[1] = 0x%p", devinfo);
+ } else {
+ printk(KERN_ERR "[EMGD] OpenDCDevice() called with unknown device ID "
+ "%lu\n", device_id);
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+ devinfo->system_buffer.sync_data = system_buffer_sync_data;
+ *device_h = (IMG_HANDLE) devinfo;
+
+
+ EMGD_TRACE_EXIT;
+
+ return PVRSRV_OK;
+} /* OpenDCDevice() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCloseDCDevice()
+ * function. This function is called when a client is finished using PVR
+ * services with the specified device.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE device_h)
+{
+ EMGD_TRACE_STUB;
+
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+ if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, device_h);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+} /* CloseDCDevice() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCFormats()
+ * function. This function is called when a client wants to determine the
+ * pixel format currently being used with, and potentially, to determine which
+ * pixel formats can be used with the specified device. The first entry in the
+ * array is the current pixel format.
+ *
+ * Note: this function must be called twice. The first time, the formats
+ * parameter is set to NULL, and the client is trying to determine the number
+ * of pixel formats. The second time, the formats parameter is non-NULL, and
+ * points to enough memory for num_formats-worth of pixel formats. Note: this
+ * creates a small window of time between calls where a mode change could
+ * occur; the probability is considered so small, as to not be a worry.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param num_formats (OUT) The number of pixel formats for this device.
+ * @param format (IN/OUT) An array of the pixel formats for this device (ignore
+ * if NULL).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE device_h,
+ IMG_UINT32 *num_formats,
+ DISPLAY_FORMAT *format)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !num_formats) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *num_formats = devinfo->num_formats;
+
+ if (format) {
+ unsigned long i;
+
+ for (i = 0 ; i < devinfo->num_formats ; i++) {
+ format[i] = devinfo->display_format_list[i];
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* EnumDCFormats() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnEnumDCDims() function.
+ * This function is called when a client wants to determine the current
+ * dimensions (similar to an EMGD mode, but just the dimensions) of, and
+ * potentially, to determine the possible dimensions that can be used with this
+ * device. The first entry in the array is the current dimension.
+ *
+ * Note: this function must be called twice. The first time, the dims
+ * parameter is set to NULL, and the client is trying to determine the number
+ * of dimensions. The second time, the dims parameter is non-NULL, and points
+ * to enough memory for num_dims-worth of dimensions. Note: this
+ * creates a small window of time between calls where a mode change could
+ * occur; the probability is considered so small, as to not be a worry.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param format (IN) A pointer to a pixel format (unused).
+ * @param num_dims (OUT) The number of dimensions for this device.
+ * @param dims (IN/OUT) An array of the dimensions for this device (ignore
+ * if NULL).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR EnumDCDims(IMG_HANDLE device_h,
+ DISPLAY_FORMAT *format,
+ IMG_UINT32 *num_dims,
+ DISPLAY_DIMS *dims)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !format || !num_dims) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *num_dims = devinfo->num_dims;
+
+ if (dims) {
+ unsigned long i;
+
+ for (i = 0 ; i < devinfo->num_dims ; i++) {
+ dims[i] = devinfo->display_dim_list[i];
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* EnumDCDims() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCSystemBuffer()
+ * function. This function returns a handle to the system buffer
+ * (a.k.a. "frame buffer" or "front buffer") of the specified device. The
+ * handle is an opaque pointer to the buffer.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param buffer_h (OUT) The handle for this buffer (an opaque pointer to
+ * devinfo->system_buffer).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE device_h, IMG_HANDLE *buffer_h)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !buffer_h) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *buffer_h = (IMG_HANDLE) &devinfo->system_buffer;
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* GetDCSystemBuffer() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCInfo() function.
+ * This function returns a pointer to the DISPLAY_INFO structure associated
+ * with this device, which contains the driver's name, and information about
+ * swap chains that can be created (i.e. all static information).
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param dc_info (OUT) The DISPLAY_INFO structure associated with this device.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE device_h, DISPLAY_INFO *dc_info)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !dc_info) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *dc_info = devinfo->display_info;
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* GetDCInfo() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBufferAddr()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param buffer_h (IN) The handle of a buffer (an opaque pointer to an
+ * emgddc_buffer_t) to return information of.
+ * @param phys_addr (OUT) A pointer to an array pointer of page addresses of
+ * the buffer. For many devices, this would be a pointer to the physical
+ * address of a contiguous set of memory associated with the buffer, but since
+ * EMGD doesn't use contiguous memory for a buffer, it returns the array of
+ * addresses.
+ * @param fb_size (OUT) The size (in bytes) of the buffer.
+ * @param virt_addr (OUT) A pointer to the virtual address (in kernel space) of
+ * the buffer.
+ * @param os_map_info_h (OUT) Ununsed by PVR services.
+ * @param is_contiguous (OUT) A pointer to a boolean that is set to IMG_FALSE,
+ * because EMGD uses non-contiguous pages of memory for buffers.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE device_h,
+ IMG_HANDLE buffer_h,
+ IMG_SYS_PHYADDR **phys_addr,
+ IMG_UINT32 *fb_size,
+ IMG_VOID **virt_addr,
+ IMG_HANDLE *os_map_info_h,
+ IMG_BOOL *is_contiguous)
+{
+ emgddc_devinfo_t *devinfo;
+ igd_context_t *context;
+ emgddc_buffer_t *system_buffer;
+ unsigned long page_count = 0;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h) {
+ printk(KERN_ERR "[EMGD] %s() Null device handle.\n", __FUNCTION__);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ context = devinfo->priv->context;
+ if (!context || (context->dispatch.gmm_get_page_list == NULL)) {
+ printk(KERN_ERR "[EMGD] %s() HAL not configured.\n", __FUNCTION__);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (!buffer_h) {
+ printk(KERN_ERR "[EMGD] %s() Null buffer handle.\n", __FUNCTION__);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ system_buffer = (emgddc_buffer_t *) buffer_h;
+
+ if (!phys_addr) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
+ EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
+
+ if ((ret = context->dispatch.gmm_get_page_list(system_buffer->offset,
+ (unsigned long **) phys_addr, &page_count)) != 0) {
+ printk(KERN_ERR"Cannot get the page addresses for the buffer at offset "
+ "0x%08lx\n", system_buffer->offset);
+ EMGD_TRACE_EXIT;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ EMGD_DEBUG(" phys_addr = 0x%p", phys_addr);
+ EMGD_DEBUG(" *phys_addr = 0x%p", (*phys_addr));
+ EMGD_DEBUG(" (*phys_addr)->uiAddr = 0x%lx", (*phys_addr)->uiAddr);
+
+ if (!fb_size) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (fb_size) {
+ *fb_size = (IMG_UINT32) system_buffer->size;
+ EMGD_DEBUG(" fb_size = 0x%lx", *fb_size);
+ }
+
+ if (virt_addr) {
+ *virt_addr = system_buffer->virt_addr;
+ EMGD_DEBUG(" virt_addr = 0x%p", *virt_addr);
+ }
+
+ /* Note: this value is ignored by the PVR services code: */
+ if (os_map_info_h) {
+ *os_map_info_h = (IMG_HANDLE)system_buffer->offset;
+ EMGD_DEBUG(" os_map_info_h = 0x%p", *os_map_info_h);
+ }
+
+ /*
+ * Other than cursor, memory allocations are not contiguous pages
+ */
+ if (is_contiguous) {
+ if(system_buffer->is_contiguous == IMG_TRUE)
+ { *is_contiguous = IMG_TRUE;
+
+ }
+ else{
+ *is_contiguous = IMG_FALSE;
+
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* GetDCBufferAddr() */
+
+
+/**
+ * Determines if the user-space-provided pointers (to a devinfo and swap chain)
+ * are valid.
+ *
+ * @param devinfo (IN) The user-space-provided pointer to a devinfo.
+ * @param swap_chain (IN) The swap chain to add to the list.
+ * @param must_be_flipable (IN) Non-zero if swap_chain must be flip-able.
+ * @return non-zero if valid, zero if not.
+ */
+static int is_valid_swap_chain(emgddc_devinfo_t *devinfo,
+ emgddc_swapchain_t *swap_chain, int must_be_flipable)
+{
+ if (!is_valid_devinfo(devinfo)) {
+ return 0;
+ } else {
+ /* Search both lists for this swap chain: */
+ emgddc_swapchain_t *swap = devinfo->flipable_swapchains;
+ while (swap) {
+ if (swap == swap_chain) {
+ return 1;
+ }
+ swap = swap->next;
+ }
+ if (!must_be_flipable) {
+ swap = devinfo->pixmap_swapchains;
+ while (swap) {
+ if (swap == swap_chain) {
+ return 1;
+ }
+ swap = swap->next;
+ }
+ }
+ }
+ /* We didn't find this swap chain pointer, so it's not valid: */
+ return 0;
+} /* is_valid_swap_chain() */
+
+
+/**
+ * Called by CreateDCSwapChain() to add a new swap chain to one of the lists of
+ * swap chains.
+ *
+ * @param list (IN) A pointer to a list of swap chains.
+ * @param swap_chain (IN) The swap chain to add to the list.
+ */
+static void add_swap_chain_to_list(emgddc_swapchain_t **list,
+ emgddc_swapchain_t *swap_chain)
+{
+ /* It's simplest to add to the front of the list: */
+ if (*list == NULL) {
+ *list = swap_chain;
+ } else {
+ swap_chain->next = *list;
+ *list = swap_chain;
+ }
+} /* add_swap_chain_to_list() */
+
+
+/**
+ * Called by DestroyDCSwapChain() to remove an about-to-be-deleted swap chain
+ * from one of the lists of swap chains.
+ *
+ * @param list (IN) A pointer to a list of swap chains.
+ * @param swap_chain (IN) The swap chain to remove from the list.
+ */
+static void remove_swap_chain_from_list(emgddc_swapchain_t **list,
+ emgddc_swapchain_t *swap_chain)
+{
+ emgddc_swapchain_t *swap, *prev;
+
+ swap = *list;
+ prev = *list;
+ while (swap) {
+ if (swap == swap_chain) {
+ /* Found match */
+ if (swap == *list) {
+ *list = swap->next;
+ } else {
+ prev->next = swap->next;
+ }
+ break;
+ }
+ prev = swap;
+ swap = swap->next;
+ }
+} /* remove_swap_chain_from_list() */
+
+
+/**
+ * Called by either CreateDCSwapChain() or DestroyDCSwapChain() to free all GMM
+ * and kernel space memory memory of the specified swap chain.
+ *
+ * @param swap_chain (IN) The swap chain to free.
+ * @param context (IN) The EMGD context to use to call gmm_free().
+ */
+static void free_swap_chain(emgddc_swapchain_t *swap_chain,
+ igd_context_t *context)
+{
+ emgddc_buffer_t *buffers;
+ int i=0;
+
+ /*
+ * Free and unmap the buffers. Must ensure that the HAL is running before
+ * calling it, and ensure that we don't free/unmap the first buffer if is
+ * actually the frame buffer.
+ */
+ if (swap_chain->devinfo->priv->hal_running) {
+ buffers = swap_chain->buffers;
+
+ for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+ if(!buffers[i].is_contiguous){
+ if (!buffers[i].is_fb) {
+ if (buffers[i].virt_addr) {
+ context->dispatch.gmm_unmap(buffers[i].virt_addr);
+ }
+ if (buffers[i].offset) {
+ context->dispatch.gmm_free(buffers[i].offset);
+ }
+ }
+ }
+ else{
+ context->dispatch.gmm_unmap_ci((unsigned long)buffers[i].virt_addr);
+ }
+
+ }
+ }
+
+ if (swap_chain->flip_queue) {
+ OS_FREE(swap_chain->flip_queue);
+ }
+ OS_FREE(swap_chain->buffers);
+ OS_FREE(swap_chain);
+
+ EMGD_TRACE_EXIT;
+} /* free_swap_chain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCreateDCSwapChain()
+ * function. This function was originally designed to create a flip-able swap
+ * chain on the specified device, but has also been augmented to allow the X
+ * driver to create pixmaps or other buffers in GTT memory. A flip-able swap
+ * chain consists of a front buffer (the "system buffer, a.k.a. the "frame
+ * buffer") and one or more back buffers (therefore, the number of buffers
+ * includes the frame buffer).
+ *
+ * Note: Only full-screen flipping is supported (the hardware is pointed at one
+ * complete buffer at a time). There is no support for the
+ * SetDC{Src|Dst}Rect() functions to define a smaller region of the display for
+ * the buffers/flipping.
+ *
+ * Note: The DDK documentation says that the mode should be changed if the
+ * dimensions and pixel format do not match the current dimensions and pixel
+ * format. However, this can only be supported if the X server isn't running
+ * (which is in charge of changing modes when it is running). If the X server
+ * is running, an error is returned unless the current dimensions and pixel
+ * format are specified.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param flags (IN) Unused.
+ * @param dst_surf_attrib (IN) While not described in the DDK documentation,
+ * this presumably specifies the desired dimensions and pixel format of the
+ * front buffer.
+ * @param src_surf_attrib (IN) Specifies the desired dimensions and pixel
+ * format of the back buffers.
+ * @param buffer_count (IN) Number of buffers required in this swap chain.
+ * @param sync_data (IN) While not described in the DDK documentation,
+ * this is an array of sync data for each buffer.
+ * @param oem_flags (IN) Unused.
+ * @param swap_chain_h (OUT) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param swap_chain_id (OUT) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE device_h,
+ IMG_UINT32 flags,
+ DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib,
+ DISPLAY_SURF_ATTRIBUTES *src_surf_attrib,
+ IMG_UINT32 buffer_count,
+ PVRSRV_SYNC_DATA **sync_data,
+ IMG_UINT32 oem_flags,
+ IMG_HANDLE *swap_chain_h,
+ IMG_UINT32 *swap_chain_id)
+{
+ emgddc_devinfo_t *devinfo;
+ emgddc_swapchain_t *swap_chain;
+ emgddc_buffer_t *buffers;
+ IMG_UINT32 i;
+ emgddc_flip_queue_item_t *flip_queue = NULL;
+ unsigned long lock_flags;
+
+ struct drm_device* drm_dev;
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ igd_dispatch_t *dispatch;
+ int flipable;
+
+ IMG_UINT32 ci_offset=0;
+
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p, buffer_count = %lu", device_h, buffer_count);
+ EMGD_DEBUG("flags = 0x%08lx, oem_flags = 0x%08lx", flags, oem_flags);
+
+ if(flags & PVR2D_CREATE_FLIPCHAIN_CI)
+ {
+ ci_offset = src_surf_attrib->ui32Reseved;
+
+ }
+
+ /*
+ * Check the parameters and dependencies:
+ */
+ if (!device_h || !dst_surf_attrib || !src_surf_attrib || !sync_data ||
+ !swap_chain_h) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /*
+ * The oem_flags will determine what type of swapchain this is. The
+ * following types are for a non-flip-able swap chain (e.g. for a pixmap):
+ *
+ * PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY - General purpose displayable
+ * PVR2D_CREATE_FLIPCHAIN_OEMGENERAL - General purpose non-displayable
+ * PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY - Overlay
+ *
+ * Currently, if none of these flags are set, assume this is going
+ * to create a set of back buffers, or a "flip-able" swap chain:
+ *
+ * PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN - Flip-able buffers
+ */
+ /* Is this is an OEM call (I.E. allocating a buffer)? */
+ if ((oem_flags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
+ PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
+ PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY |
+ PVR2D_CREATE_FLIPCHAIN_CI))) {
+ flipable = 0;
+
+ } else {
+ /*
+ * If this is suppose to be an actual flip-able swap chain, then
+ * make sure there are at least 2 buffers.
+ */
+ if (buffer_count < 2) {
+ return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+ }
+ flipable = 1;
+
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ if (!is_valid_devinfo(devinfo)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, devinfo);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ drm_dev = devinfo->drm_device;
+ priv = drm_dev->dev_private;
+ context = priv->context;
+ dispatch = &(context->dispatch);
+
+
+ if (buffer_count > devinfo->display_info.ui32MaxSwapChainBuffers) {
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ /* Ensure the source & destination attributes match each other: */
+ if ((dst_surf_attrib->pixelformat != src_surf_attrib->pixelformat) ||
+ (dst_surf_attrib->sDims.ui32ByteStride !=
+ src_surf_attrib->sDims.ui32ByteStride) ||
+ (dst_surf_attrib->sDims.ui32Width != src_surf_attrib->sDims.ui32Width)||
+ (dst_surf_attrib->sDims.ui32Height !=
+ src_surf_attrib->sDims.ui32Height)) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (flipable) {
+ PVRSRV_ERROR err =
+ do_mode_change(context, devinfo, priv, dst_surf_attrib);
+ if (err != PVRSRV_OK) {
+ EMGD_DEBUG("Exiting early because of an error in do_mode_change()");
+ EMGD_TRACE_EXIT;
+ return err;
+ }
+ }
+
+ /*
+ * Allocate data structures:
+ */
+ swap_chain = (emgddc_swapchain_t *) OS_ALLOC(sizeof(emgddc_swapchain_t));
+ if (!swap_chain) {
+ EMGD_ERROR_EXIT("Can not allocate memory for a swap chain");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OS_MEMSET(swap_chain, 0, sizeof(emgddc_swapchain_t));
+
+ buffers = (emgddc_buffer_t *) OS_ALLOC(sizeof(emgddc_buffer_t) *
+ buffer_count);
+ if (!buffers) {
+ OS_FREE(swap_chain);
+ EMGD_ERROR_EXIT("Can not allocate memory for swap chain buffers");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OS_MEMSET(buffers, 0, sizeof(emgddc_buffer_t) * buffer_count);
+
+ if (flipable) {
+ flip_queue = (emgddc_flip_queue_item_t *)
+ OS_ALLOC(sizeof(emgddc_flip_queue_item_t) * buffer_count);
+ if (!flip_queue) {
+ OS_FREE(buffers);
+ OS_FREE(swap_chain);
+ EMGD_ERROR_EXIT("Can not allocate memory for flip queue");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OS_MEMSET(flip_queue, 0,
+ sizeof(emgddc_flip_queue_item_t) * buffer_count);
+ }
+
+ /*
+ * Initialize data structures:
+ */
+ swap_chain->devinfo = devinfo;
+ swap_chain->valid = EMGD_TRUE;
+ swap_chain->buffer_count = (unsigned long) buffer_count;
+ swap_chain->buffers = buffers;
+ swap_chain->flags = flags;
+ swap_chain->next = NULL;
+ if (flipable) {
+ swap_chain->flip_queue = flip_queue;
+ swap_chain->insert_index = 0;
+ swap_chain->remove_index = 0;
+ }
+ swap_chain->pvr_jtable = &devinfo->pvr_jtable;
+
+ /* Link the buffers of the swap chain: */
+ for (i = 0 ; i < buffer_count-1 ; i++) {
+ buffers[i].next = &buffers[i+1];
+ }
+ buffers[i].next = &buffers[0];
+
+ i = 0;
+ if (flipable) {
+ /* The first buffer is the frame buffer (a.k.a. the front buffer). */
+ buffers[i].priv = priv;
+ buffers[i].offset = devinfo->system_buffer.offset;
+ buffers[i].pixel_format = devinfo->system_buffer.pixel_format;
+ buffers[i].width = devinfo->system_buffer.width;
+ buffers[i].height = devinfo->system_buffer.height;
+ buffers[i].pitch = devinfo->system_buffer.pitch;
+ buffers[i].size = devinfo->system_buffer.size;
+ buffers[i].virt_addr = devinfo->system_buffer.virt_addr;
+ buffers[i].sync_data = sync_data[0];
+ buffers[i].is_fb = 1;
+ swap_chain->flags |= PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN;
+ i++;
+ }
+
+ /*
+ * Allocate memory for the buffers
+ */
+ for (; i < buffer_count ; i++) {
+ unsigned long offset;
+ unsigned long virt_addr;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ unsigned int pitch = 0;
+ unsigned long size = 0;
+ unsigned long pf;
+ unsigned long flags = IGD_SURFACE_RENDER;
+ int ret;
+ unsigned int map_method=1; /*1: gtt map by va driver*/
+
+ if (!(oem_flags & PVR2D_CREATE_FLIPCHAIN_OEMGENERAL)) {
+ flags |= IGD_SURFACE_DISPLAY;
+ }
+
+ buffers[i].priv = priv;
+
+ /*
+ * What should be used for the surface attributes, the source
+ * surface attributes or the destination surface attributes?
+ * Can we assume that source is the surface requested?
+ */
+ pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
+ width = dst_surf_attrib->sDims.ui32Width;
+ height = dst_surf_attrib->sDims.ui32Height;
+ pitch = dst_surf_attrib->sDims.ui32ByteStride;
+ flags |= IGD_MIN_PITCH;
+
+ if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
+ if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI_V4L2_MAP)
+ map_method = 0;
+
+
+ size=height*pitch;
+ ret = dispatch->gmm_map_ci(&offset,
+ ci_offset,
+ &virt_addr,
+ map_method,
+ size);
+
+
+ if (0 != ret) {
+ free_swap_chain(swap_chain, context);
+ EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ buffers[i].is_contiguous = IMG_TRUE;
+
+ }
+ else{
+
+ ret = dispatch->gmm_alloc_surface(&offset,
+ pf,
+ &width, &height,
+ &pitch, &size,
+ IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
+ if (0 != ret) {
+ free_swap_chain(swap_chain, context);
+ EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ buffers[i].is_contiguous = IMG_FALSE;
+ }
+
+ dst_surf_attrib->sDims.ui32ByteStride = pitch;
+ src_surf_attrib->sDims.ui32ByteStride = pitch;
+
+ buffers[i].pixel_format = pf;
+ buffers[i].width = width;
+ buffers[i].height = height;
+ buffers[i].pitch = pitch;
+ buffers[i].size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+ buffers[i].offset = offset;
+
+ if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
+
+ buffers[i].virt_addr = (IMG_CPU_VIRTADDR)virt_addr;
+ }
+ else
+ buffers[i].virt_addr = dispatch->gmm_map(offset);
+ buffers[i].sync_data = sync_data[i];
+ buffers[i].is_fb = 0;
+ } /* for */
+
+
+ if (flipable) {
+ /* Initialize what's needed for flip-able swap chains: */
+ int must_enable;
+
+ for (i = 0 ; i < buffer_count ; i++) {
+ flip_queue[i].valid = EMGD_FALSE;
+ flip_queue[i].flipped = EMGD_FALSE;
+ flip_queue[i].cmd_completed = EMGD_FALSE;
+ }
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ must_enable = (devinfo->flipable_swapchains == NULL) ? 1 : 0;
+
+ /* Add this swap chain to the list of flip-able swap chains: */
+ add_swap_chain_to_list(&devinfo->flipable_swapchains, swap_chain);
+
+ /* Unlock here (before enabling interrupts), to prevent deadlock: */
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+ if (!devinfo->flush_commands) {
+ if (must_enable) {
+ /* Enable interrupts for vblanks: */
+ if (!devinfo->interrupt_h || dispatch->
+ enable_vblank_callback(devinfo->interrupt_h)) {
+ /* For some reason (rare), interrupts weren't enabled: */
+ EMGD_ERROR_EXIT("Can not enable VBlank interrupts! "
+ "Therefore, cannot do buffer flipping!");
+ /* Properly clean up: */
+ remove_swap_chain_from_list(&devinfo->flipable_swapchains,
+ swap_chain);
+ free_swap_chain(swap_chain, context);
+ return PVRSRV_ERROR_BAD_MAPPING;
+ } else {
+ devinfo->flipping_disabled = EMGD_FALSE;
+ }
+ }
+ }
+
+#ifdef SUPPORT_FB_EVENTS
+ if (must_enable) {
+ /* Enable fb events: */
+ if (enable_event_notification(devinfo)!= EMGD_OK) {
+ EMGD_ERROR_EXIT("Can not enable framebuffer event "
+ "notification");
+ /* Properly clean up: */
+ if (devinfo->interrupt_h) {
+ dispatch->disable_vblank_callback(
+ devinfo->interrupt_h);
+ }
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+ remove_swap_chain_from_list(&devinfo->flipable_swapchains,
+ swap_chain);
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+ free_swap_chain(swap_chain, context);
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+#endif /* SUPPORT_FB_EVENTS */
+ } else {
+ /* Add this swap chain to the list of pixmap swap chains: */
+ add_swap_chain_to_list(&devinfo->pixmap_swapchains, swap_chain);
+ }
+
+
+ *swap_chain_id = ++devinfo->swap_chain_id_counter;
+ *swap_chain_h = (IMG_HANDLE) swap_chain;
+ EMGD_DEBUG("swap_chain_h = 0x%p, *swap_chain_id = %lu",
+ swap_chain_h, *swap_chain_id);
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* CreateDCSwapChain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnDestroyDCSwapChain()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h)
+{
+ emgddc_devinfo_t *devinfo;
+ drm_emgd_priv_t *priv;
+ igd_context_t *context;
+ igd_dispatch_t *dispatch;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long lock_flags;
+#ifdef SUPPORT_FB_EVENTS
+ emgd_error_t error;
+#endif /* SUPPORT_FB_EVENTS */
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !swap_chain_h) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ priv = devinfo->priv;
+ context = priv->context;
+ dispatch = &(context->dispatch);
+ swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+ if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+ "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Remove swap chain from the appropriate list: */
+ if (swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN) {
+ /* De-initialize what's needed for flip-able swap chains: */
+ int must_disable;
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+ must_disable =
+ ((devinfo->flipable_swapchains == swap_chain) &&
+ (devinfo->flipable_swapchains->next == NULL)) ? 1 : 0;
+
+ /* Remove this swap chain from the list of flip-able swap chains: */
+ remove_swap_chain_from_list(&devinfo->flipable_swapchains, swap_chain);
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+#ifdef SUPPORT_FB_EVENTS
+ if (must_disable) {
+ /* Disable fb events: */
+ error = disable_event_notification(devinfo);
+ if (error != EMGD_OK) {
+ EMGD_ERROR("Could not disable framebuffer event notification");
+ }
+ }
+#endif /* SUPPORT_FB_EVENTS */
+
+ /* Disable interrupts for vblanks: */
+ if (must_disable) {
+ if (devinfo->interrupt_h) {
+ dispatch->disable_vblank_callback(devinfo->interrupt_h);
+ }
+ }
+
+ /* Flush any pending flips: */
+ flush_flip_queue(swap_chain);
+
+ /* Flip back to the system buffer: */
+ emgddc_flip(swap_chain, &devinfo->system_buffer);
+ } else {
+ /* Remove this swap chain from the list of pixmap swap chains: */
+ remove_swap_chain_from_list(&devinfo->pixmap_swapchains, swap_chain);
+ }
+
+ /* Free all GMM and kernel space memory for this swap chain: */
+ free_swap_chain(swap_chain, context);
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* DestroyDCSwapChain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstRect()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h,
+ IMG_RECT *rect)
+{
+ UNREFERENCED_PARAMETER(device_h);
+ UNREFERENCED_PARAMETER(swap_chain_h);
+ UNREFERENCED_PARAMETER(rect);
+
+ EMGD_TRACE_STUB;
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcRect()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h,
+ IMG_RECT *rect)
+{
+ UNREFERENCED_PARAMETER(device_h);
+ UNREFERENCED_PARAMETER(swap_chain_h);
+ UNREFERENCED_PARAMETER(rect);
+
+ EMGD_TRACE_STUB;
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstColourKey()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param color (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h,
+ IMG_UINT32 color)
+{
+ UNREFERENCED_PARAMETER(device_h);
+ UNREFERENCED_PARAMETER(swap_chain_h);
+ UNREFERENCED_PARAMETER(color);
+
+ EMGD_TRACE_STUB;
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcColourKey()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param color (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h,
+ IMG_UINT32 color)
+{
+ UNREFERENCED_PARAMETER(device_h);
+ UNREFERENCED_PARAMETER(swap_chain_h);
+ UNREFERENCED_PARAMETER(color);
+
+ EMGD_TRACE_STUB;
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBuffers()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param buffer_count (OUT) The number of buffers in the specified swap chain.
+ * @param buffer_h (IN/OUT) An array of buffer handles (an opaque pointer to a
+ * emgddc_buffer_t) in the specified swap chain (memory must be allocated by
+ * the caller).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h,
+ IMG_UINT32 *buffer_count,
+ IMG_HANDLE *buffer_h)
+{
+ emgddc_devinfo_t *devinfo;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long i;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !swap_chain_h || !buffer_count || !buffer_h) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+ if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+ "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *buffer_count = (IMG_UINT32) swap_chain->buffer_count;
+
+ for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+ buffer_h[i] = (IMG_HANDLE) &swap_chain->buffers[i];
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* GetDCBuffers() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCBuffer()
+ * function. This function is supposed to cause a flip to the specified
+ * buffer. However, it is no longer called by PVR services!
+ *
+ * NOTE: As can be seen, this function was never completely implemented
+ * (i.e. in the DDK used to create this version). This is because the PVR code
+ * doesn't call this function. Instead, it calls emgddc_process_flip().
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param buffer_h (IN) The handle for this buffer (an opaque pointer to a
+ * emgddc_buffer_t).
+ * @param swap_interval (IN) Unused.
+ * @param private_tag_h (IN) Unused.
+ * @param clip_rect_count (IN) Largely unused.
+ * @param clip_rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE device_h,
+ IMG_HANDLE buffer_h,
+ IMG_UINT32 swap_interval,
+ IMG_HANDLE private_tag_h,
+ IMG_UINT32 clip_rect_count,
+ IMG_RECT *clip_rect)
+{
+ /* This function is never called by PVR services, and so it is stubbed: */
+ UNREFERENCED_PARAMETER(device_h);
+ UNREFERENCED_PARAMETER(buffer_h);
+ UNREFERENCED_PARAMETER(swap_interval);
+ UNREFERENCED_PARAMETER(private_tag_h);
+ UNREFERENCED_PARAMETER(clip_rect_count);
+ UNREFERENCED_PARAMETER(clip_rect);
+
+ EMGD_TRACE_STUB;
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+
+} /* SwapToDCBuffer() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCSystem()
+ * function. This function causes a flip to the "system buffer" (a.k.a. frame
+ * buffer).
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE device_h,
+ IMG_HANDLE swap_chain_h)
+{
+ emgddc_devinfo_t *devinfo;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long lock_flags;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!device_h || !swap_chain_h) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ devinfo = (emgddc_devinfo_t *) device_h;
+ swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+ if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+ "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ /* This must be a flip-able swap chain, or we can't cause a flip for it: */
+ if (!(swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN)) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ flush_flip_queue(swap_chain);
+ emgddc_flip(swap_chain, &devinfo->system_buffer);
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+
+ EMGD_TRACE_EXIT;
+ return PVRSRV_OK;
+
+} /* SwapToDCSystem() */
+
+
+/**
+ * Drains the circular queue of buffers to flip for a specified swap chain.
+ * The queue is processed in order. For every item in the queue, processing is
+ * as follows:
+ *
+ * - An item that has been "completed" (i.e. PVR services has been told that
+ * the flip occured), but hasn't reached the end of its swap interval, is
+ * immediately ended and cleared.
+ *
+ * - An item that has been flipped, but hasn't been "completed" with PVR
+ * services, is "completed," ended, and cleared.
+ *
+ * - An item that has been queued, but hasn't been flipped, is immediately
+ * flipped (i.e. given the Poulsbo hardware, this really means that the
+ * hardware is told to flip them at the start of the next vertical blanking
+ * period), "completed," ended, and cleared.
+ *
+ * Note: This function assumes that the calling function has already obtained
+ * the spin lock.
+ *
+ * @param swap_chain (IN) The swap chain to flush the queue for.
+ */
+static void flush_flip_queue(emgddc_swapchain_t *swap_chain)
+{
+ emgddc_flip_queue_item_t *flip_item;
+ unsigned long max_index;
+ unsigned long i;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Get the first item to drain in the circular queue: */
+ flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+ max_index = swap_chain->buffer_count - 1;
+
+ for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+ if (flip_item->valid == EMGD_FALSE) {
+ continue;
+ }
+
+ EMGD_DEBUG("Flushing buffer offset=0x%lx", flip_item->buffer->offset);
+
+ if ((swap_chain->devinfo->flipping_disabled == EMGD_FALSE) &&
+ (flip_item->flipped == EMGD_FALSE) &&
+ (swap_chain->valid == EMGD_TRUE)) {
+ EMGD_DEBUG("Flipping to buffer offset=0x%lx",
+ flip_item->buffer->offset);
+ emgddc_flip(swap_chain, flip_item->buffer);
+ }
+
+ if (flip_item->cmd_completed == EMGD_FALSE) {
+ PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
+
+ EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
+ flip_item->buffer->offset);
+ pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete, IMG_TRUE);
+ }
+
+ /* We're done with this item in the queue. Prepare for processing the
+ * next item:
+ */
+ flip_item->flipped = EMGD_FALSE;
+ flip_item->cmd_completed = EMGD_FALSE;
+ flip_item->valid = EMGD_FALSE;
+
+ /* Point to the next item in the circular queue: */
+ swap_chain->remove_index++;
+ if (swap_chain->remove_index > max_index) {
+ swap_chain->remove_index = 0;
+ }
+
+ /* Get the next item in the circular queue: */
+ flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+ }
+
+ /* Reset the circular queue to the start: */
+ swap_chain->insert_index = 0;
+ swap_chain->remove_index = 0;
+
+
+ EMGD_TRACE_EXIT;
+
+} /* flush_flip_queue() */
+
+
+static void set_flush_state_internal_nolock(emgddc_devinfo_t* devinfo,
+ emgd_bool flush_state)
+{
+ emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (flush_state) {
+ if (devinfo->set_flush_state_ref_count == 0) {
+ /* Don't actually disable interrupts. Just set a flag so that
+ * buffer flips won't be queued, then flush the circular buffer of
+ * all pending flips, for all swap chains:
+ */
+ devinfo->flush_commands = EMGD_TRUE;
+ while (swap_chain != NULL) {
+ flush_flip_queue(swap_chain);
+ swap_chain = swap_chain->next;
+ }
+ }
+ devinfo->set_flush_state_ref_count++;
+ } else {
+ if (devinfo->set_flush_state_ref_count != 0) {
+ devinfo->set_flush_state_ref_count--;
+ if (devinfo->set_flush_state_ref_count == 0) {
+ /* Don't actually enable interrupts. Just set a flag so that
+ * buffer flips will be queued:
+ */
+ devinfo->flush_commands = EMGD_FALSE;
+ }
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+}
+
+
+static void set_flush_state_external(emgddc_devinfo_t* devinfo,
+ emgd_bool flush_state)
+{
+ unsigned long lock_flags;
+
+ EMGD_TRACE_ENTER;
+
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ if (devinfo->flush_commands != flush_state) {
+ devinfo->flush_commands = flush_state;
+ set_flush_state_internal_nolock(devinfo, flush_state);
+ }
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCState() function.
+ * This function is supposed to set some state flags in the driver, affecting
+ * interrupt-driven buffer flips.
+ *
+ * Note: The following function used to never be called, but now is called when
+ * X11 is rotated 90 degrees (it is called as a result of an interrupt handler
+ * dealing with an SGX hardware reset). As such, the code that this calls
+ * cannot enable/disable interrupts (which may cause an interrupt handler to be
+ * registered/unregistered).
+ *
+ * Note: The code that this calls seems overly complicated. If we never enable
+ * SUPPORT_FB_EVENTS, it can be simplified (e.g. no use of
+ * set_flush_state_ref_count).
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param state (IN) Either DC_STATE_FLUSH_COMMANDS or
+ * DC_STATE_NO_FLUSH_COMMANDS.
+ */
+static IMG_VOID SetDCState(IMG_HANDLE device_h, IMG_UINT32 state)
+{
+ emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) device_h;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+ if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+ __FUNCTION__, device_h);
+ return;
+ }
+
+ switch (state) {
+ case DC_STATE_FLUSH_COMMANDS:
+ set_flush_state_external(devinfo, EMGD_TRUE);
+ break;
+ case DC_STATE_NO_FLUSH_COMMANDS:
+ set_flush_state_external(devinfo, EMGD_FALSE);
+ break;
+ default:
+ break;
+ }
+
+
+ EMGD_TRACE_EXIT;
+} /* SetDCState() */
+
+
+#ifdef SUPPORT_FB_EVENTS
+/* NOTE -- The following code is probably not correct. It was inherited from
+ * an early IMG/UMG DDK, and has never been used. If we ever decide to use
+ * this code, we should look at the latest DDK and UMG code, to glean what may
+ * be really needed. At a minimum, the following code needs to affect all swap
+ * chains.
+ */
+
+static int emgddc_fb_events(struct notifier_block *notif,
+ unsigned long event, void *data)
+{
+ emgddc_devinfo_t *devinfo;
+ emgddc_swapchain_t *swap_chain;
+ struct fb_event *fb_event = (struct fb_event *) data;
+ emgd_bool blanked;
+ unsigned long lock_flags;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (event != FB_EVENT_BLANK) {
+ return 0;
+ }
+
+ /* Look up the device (for DIH/Extended mode): */
+ if (notif == &(global_devinfo[0]->lin_notif_block)) {
+ devinfo = global_devinfo[0];
+ } else if (notif == &(global_devinfo[1]->lin_notif_block)) {
+ devinfo = global_devinfo[1];
+ } else {
+ printk(KERN_ERR "[EMGD] emgddc_fb_events() cannot find its device\n");
+ return -ENODEV;
+ }
+ swap_chain = devinfo->flipable_swapchains;
+
+ blanked = (*(IMG_INT *) fb_event->data != 0) ? EMGD_TRUE : EMGD_FALSE;
+
+ if (blanked != swap_chain->blanked) {
+ swap_chain->blanked = blanked;
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ if (blanked) {
+ set_flush_state_internal_nolock(devinfo, EMGD_TRUE);
+ } else {
+ set_flush_state_internal_nolock(devinfo, EMGD_FALSE);
+ }
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+
+static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo)
+{
+ int res;
+ emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
+
+ EMGD_TRACE_ENTER;
+
+
+ memset(&devinfo->lin_notif_block, 0, sizeof(devinfo->lin_notif_block));
+
+ devinfo->lin_notif_block.notifier_call = emgddc_fb_events;
+ swap_chain->blanked = EMGD_FALSE;
+ res = fb_register_client(&devinfo->lin_notif_block);
+ if (res != 0) {
+ EMGD_ERROR_EXIT("fb_register_client() failed (%d)", res);
+ return EMGD_ERROR_GENERIC;
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return EMGD_OK;
+}
+
+
+static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo)
+{
+ int res;
+
+
+ EMGD_TRACE_ENTER;
+
+
+ res = fb_unregister_client(&devinfo->lin_notif_block);
+ if (res != 0) {
+ EMGD_ERROR_EXIT("fb_unregister_client() failed (%d)", res);
+ return EMGD_ERROR_GENERIC;
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return EMGD_OK;
+}
+#endif /* SUPPORT_FB_EVENTS */
+
+
+/**
+ * This function does per-vblank processing of the circular queue of buffers to
+ * flip. It is called for each flip-able swap chain, during a VBlank
+ * interrupt. The first item in the queue is processed, and if it is cleared
+ * (see below), the next item is processed, etc. Items are processed as
+ * follows:
+ *
+ * - An item that hasn't been flipped, is flipped. In this case, processing
+ * stops. It is assumed that the swap interval for this item is at least
+ * one, and therefore, another vblank is needed for this flip.
+ *
+ * - An item that has been flipped, but hasn't been "completed" (i.e. PVR
+ * services has been told that the flip occured), is "completed" and has its
+ * swap interval decremented by 1. If the swap interval is now 0, the item
+ * is cleared, allowing processing of the next item to start.
+ *
+ * - An item that has been "completed," but hasn't reached the end of its swap
+ * interval, has its swap interval decremented by 1. If the swap interval is
+ * now 0, the item is cleared, allowing processing of the next item to start.
+ *
+ * @param swap_chain (IN) The swap chain to process the queue for.
+ */
+emgd_bool emgddc_process_flip_queue_for_vblank(emgddc_swapchain_t *swap_chain)
+{
+ PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable = swap_chain->pvr_jtable;
+ IMG_BOOL status = IMG_TRUE;
+ emgddc_flip_queue_item_t *flip_item;
+ unsigned long max_index;
+
+ EMGD_TRACE_ENTER;
+
+
+ if (swap_chain->devinfo->flush_commands) {
+ EMGD_TRACE_EXIT;
+ return status;
+ }
+
+ /* Get the first item to process in the circular queue: */
+ flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+ max_index = swap_chain->buffer_count - 1;
+
+ while (flip_item->valid) {
+ if (flip_item->flipped) {
+ if (!flip_item->cmd_completed) {
+ EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer "
+ "offset=0x%lx", flip_item->buffer->offset);
+ pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete,
+ IMG_TRUE);
+ flip_item->cmd_completed = EMGD_TRUE;
+ }
+
+ flip_item->swap_interval--;
+ EMGD_DEBUG("Swap interval is %lu for buffer offset=0x%lx",
+ flip_item->swap_interval, flip_item->buffer->offset);
+
+ if (flip_item->swap_interval == 0) {
+ /* We're done with this item in the queue. Prepare for
+ * processing the next item:
+ */
+ flip_item->cmd_completed = EMGD_FALSE;
+ flip_item->flipped = EMGD_FALSE;
+ flip_item->valid = EMGD_FALSE;
+
+ /* Point to the next item in the circular queue: */
+ swap_chain->remove_index++;
+ if (swap_chain->remove_index > max_index) {
+ swap_chain->remove_index = 0;
+ }
+ } else {
+ /* Wait for more vblanks before doing more queue processing: */
+ break;
+ }
+ } else {
+ EMGD_DEBUG("Flipping to buffer offset=0x%lx",
+ flip_item->buffer->offset);
+ emgddc_flip(swap_chain, flip_item->buffer);
+ flip_item->flipped = EMGD_TRUE;
+ /* Wait for more vblanks before doing more queue processing: */
+ break;
+ }
+
+ /* Get the next item in the circular queue: */
+ flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+ }
+
+
+ EMGD_TRACE_EXIT;
+
+ return status;
+
+} /* emgddc_process_flip_queue_for_vblank() */
+
+
+/**
+ * This is called by a HAL-implemented, Linux interrupt handler. It is called
+ * when a VBlank interrupt occurs. All device-specific functionality was
+ * implemented by the HAL, and only 3DD-specific functionality needs to be
+ * provided by this function.
+ *
+ * @param pdevinfo (IN) Pointer to the devinfo that had a VBlank interrupt.
+ * @return Non-zero for success, zeron for failure.
+ */
+static int emgddc_process_vblank(void* pdevinfo)
+{
+ emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) pdevinfo;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long lock_flags;
+
+ EMGD_TRACE_ENTER;
+
+
+ if ((devinfo != global_devinfo[0]) && (devinfo != global_devinfo[1])) {
+ return 0;
+ }
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ swap_chain = devinfo->flipable_swapchains;
+ while (swap_chain != NULL) {
+ (void) emgddc_process_flip_queue_for_vblank(swap_chain);
+ swap_chain = swap_chain->next;
+ }
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+ return 1;
+
+} /* emgddc_process_vblank() */
+
+
+/**
+ * Called by PVR services to flip a buffer. When interrupts are supported, the
+ * flip may be queued (in a circular buffer) to happen later. When interrupts
+ * are not supported, the flip always happens immediately
+ *
+ * @param cmd_cookie_h (IN) An opaque pointer to a PVR service data structure
+ * that must be handed back when the flip is "completed" (i.e. PVR services
+ * is told that the flip occured).
+ * @param data_size (IN) Size of the flip command and all clipping rectangles
+ * (which isn't supported). This is only used for consistency-checking.
+ * @param data (IN) A pointer to information about what to flip.
+ */
+static IMG_BOOL emgddc_process_flip(IMG_HANDLE cmd_cookie_h,
+ IMG_UINT32 data_size,
+ IMG_VOID *data)
+{
+ DISPLAYCLASS_FLIP_COMMAND *flip_cmd;
+ emgddc_devinfo_t *devinfo;
+ emgddc_buffer_t *buffers;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long max_index;
+ emgddc_flip_queue_item_t* flip_item;
+ unsigned long lock_flags;
+ int must_flip = 0;
+ int must_complete = 0;
+ igd_context_t *context;
+
+ EMGD_TRACE_ENTER;
+
+
+ /*
+ * Unpack the flip command and look for errors:
+ */
+
+ if (!cmd_cookie_h || !data) {
+ EMGD_ERROR_EXIT("NULL parameter(s)");
+ return IMG_FALSE;
+ }
+
+ flip_cmd = (DISPLAYCLASS_FLIP_COMMAND *) data;
+
+ /* Note: the data_size actually accounts for both the flip command and
+ * all of the clipping rectangles. As such, the only error is if
+ * data_size is smaller than the sizeof the flip command:
+ */
+ if (flip_cmd == IMG_NULL ||
+ (sizeof(DISPLAYCLASS_FLIP_COMMAND) > data_size)) {
+ EMGD_ERROR_EXIT("Invalid flip_cmd (0x%p)", flip_cmd);
+ return IMG_FALSE;
+ }
+
+ devinfo = (emgddc_devinfo_t *) flip_cmd->hExtDevice;
+ buffers = (emgddc_buffer_t *) flip_cmd->hExtBuffer;
+ swap_chain = (emgddc_swapchain_t *) flip_cmd->hExtSwapChain;
+
+ if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
+ /* Note: Hardware video decode creates pixmap swap chains,
+ * and when they are being destroyed (at
+ * the end of video playback), something tries to flip these
+ * non-flipable swap chains. The only way to avoid a hang is to
+ * "complete" the flip command.
+ */
+ printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+ "swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+ swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+ EMGD_TRACE_EXIT;
+ return IMG_TRUE;
+ }
+
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+ if ((devinfo->flipping_disabled == EMGD_TRUE) ||
+ (swap_chain->valid != EMGD_TRUE)) {
+ /* We won't flip, but must tell PVR services that the flip occured: */
+ EMGD_DEBUG("Something (e.g. a mode change) has invalidated\n"
+ "this swap chain. As such buffer flips are not allowed.\n"
+ "If a mode change caused this problem, this swap chain\n"
+ "needs to be destroyed, and a new one created.");
+ swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+ EMGD_TRACE_EXIT;
+ return IMG_TRUE;
+ }
+
+ context = devinfo->priv->context;
+ if (context->device_context.power_state != IGD_POWERSTATE_D0) {
+ /* If device is in a suspended state, but PVR services asks the driver
+ * to perform a buffer flip, basically ignore it except for telling PVR
+ * services that we did the flip:
+ */
+ EMGD_DEBUG("Device in suspended state--completing command");
+ swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+ EMGD_TRACE_EXIT;
+ return IMG_TRUE;
+ }
+
+ /* Get the first item to add to the circular queue: */
+ flip_item = &swap_chain->flip_queue[swap_chain->insert_index];
+ max_index = swap_chain->buffer_count - 1;
+
+
+ /*
+ * Decide what needs to be done:
+ */
+ if ((flip_cmd->ui32SwapInterval == 0) ||
+ (devinfo->flush_commands == EMGD_TRUE)) {
+ /* Perform and complete the flip now: */
+ must_flip = 1;
+ must_complete = 1;
+ } else {
+ /* PVR services only calls emgddc_process_flip() when the 3DD completes
+ * the previous flip. Thus, the circular flip_item queue should never
+ * overflow. However, just in case, check whether the flip_item
+ * already contains a valid/queued flip (i.e. we've overflowed the
+ * circular queue).
+ */
+ if (flip_item->valid == EMGD_FALSE) {
+ if (swap_chain->insert_index == swap_chain->remove_index) {
+ /* Perform the flip now, but queue it for completion: */
+ must_flip = 1;
+ }
+ /* else - queue the flip for later: */
+ } else {
+ /* Just in case we overflow the circular queue, generate an error */
+ swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+ EMGD_ERROR_EXIT("Overflowed the circular flip_item queue");
+ return IMG_FALSE;
+ }
+ }
+
+
+ /*
+ * Do what needs to be done:
+ */
+ if (must_flip) {
+ /* Perform the flip now: */
+ EMGD_DEBUG("Flipping to buffer offset=0x%lx", buffers->offset);
+ emgddc_flip(swap_chain, buffers);
+ }
+ if (must_complete) {
+ /* Tell the PVR services that the flip occured: */
+ EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
+ buffers->offset);
+ swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
+ } else {
+ /* Queue the flip for later completion: */
+ EMGD_DEBUG("Queueing buffer offset=0x%lx", buffers->offset);
+ if (must_flip) {
+ flip_item->flipped = EMGD_TRUE;
+ }
+ flip_item->cmd_complete = cmd_cookie_h;
+ flip_item->swap_interval = (unsigned long) flip_cmd->ui32SwapInterval;
+ flip_item->valid = EMGD_TRUE;
+ flip_item->buffer = buffers;
+
+ swap_chain->insert_index++;
+ if (swap_chain->insert_index > max_index) {
+ swap_chain->insert_index = 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+ EMGD_TRACE_EXIT;
+ return IMG_TRUE;
+} /* emgddc_process_flip() */
+
+
+/**
+ * For a given devinfo, unmap's the frame buffer, and frees the devinfo and
+ * it's surfaces.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ */
+void emgddc_free_a_devinfo(emgddc_devinfo_t *devinfo)
+{
+ igd_context_t *context = devinfo->priv->context;
+
+ EMGD_TRACE_ENTER;
+
+ if (devinfo->priv->hal_running) {
+ /* Un-register (if needed) the interrupt connection with the HAL: */
+ if (devinfo->interrupt_h) {
+ context->dispatch.unregister_vblank_callback(devinfo->interrupt_h);
+ devinfo->interrupt_h = NULL;
+ }
+
+ if (devinfo->system_buffer.virt_addr) {
+ context->dispatch.gmm_unmap(devinfo->system_buffer.virt_addr);
+ }
+ }
+ OS_FREE(devinfo);
+
+ EMGD_TRACE_EXIT;
+} /* emgddc_free_a_devinfo() */
+
+
+/**
+ * Frees all devinfo structures and their surfaces. This is called during
+ * de-init time, or when init fails.
+ */
+void emgddc_free_all_devinfos(void)
+{
+ emgddc_devinfo_t *devinfo;
+
+ EMGD_TRACE_ENTER;
+
+ /* Free the primary display's structures: */
+ devinfo = global_devinfo[0];
+ emgddc_free_a_devinfo(devinfo);
+ global_devinfo[0] = NULL;
+
+ /* Free the secondary display's structures, if applicable: */
+ if (NULL == (devinfo = global_devinfo[1])) {
+ emgddc_free_a_devinfo(devinfo);
+ global_devinfo[1] = NULL;
+ }
+
+ EMGD_TRACE_EXIT;
+} /* emgddc_free_all_devinfos() */
+
+
+/**
+ * Initialize the "static" (i.e. doesn't vary with alter_display) portion of
+ * a devinfo structure.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ * @param devinfo (IN/OUT) The devinfo to initialize.
+ * @param port_number (IN) Which devinfo (0 for primary, 1 for secondary/DIH).
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static emgd_error_t emgddc_init_devinfo(struct drm_device *dev,
+ emgddc_devinfo_t *devinfo, int which_devinfo)
+{
+ drm_emgd_priv_t *priv = dev->dev_private;
+ PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable;
+ PFN_CMD_PROC cmd_proc_list[EMGDDC_COMMAND_COUNT];
+ IMG_UINT32 sync_count_list[EMGDDC_COMMAND_COUNT][2];
+
+ EMGD_TRACE_ENTER;
+
+
+ /*
+ * Initialize the static/display-independent devinfo values:
+ */
+ devinfo->which_devinfo = which_devinfo;
+ devinfo->priv = priv;
+ devinfo->drm_device = dev;
+ devinfo->flipable_swapchains = NULL;
+ devinfo->swap_chain_id_counter = 0;
+ devinfo->display_info.ui32MaxSwapChainBuffers = 5;
+ devinfo->display_info.ui32MaxSwapChains = 1024 * 1024;
+ /* Note: change from zero if we support interrupts and see the need: */
+ devinfo->display_info.ui32MaxSwapInterval = 2;
+ devinfo->display_info.ui32MinSwapInterval = 0;
+ EMGD_DEBUG("Maximum number of swap chains: %lu",
+ devinfo->display_info.ui32MaxSwapChains);
+ EMGD_DEBUG("Maximum number of swap chain buffers: %lu",
+ devinfo->display_info.ui32MaxSwapChainBuffers);
+ strncpy(devinfo->display_info.szDisplayName, DISPLAY_DEVICE_NAME,
+ MAX_DISPLAY_NAME_SIZE);
+ devinfo->flush_commands = EMGD_FALSE;
+ spin_lock_init(&devinfo->swap_chain_lock);
+
+
+ /*
+ * Get the PVR services jump table, which this 3rd-party display driver can
+ * use to call PVR services:
+ */
+ if (!PVRGetDisplayClassJTable(&devinfo->pvr_jtable)) {
+ EMGD_ERROR_EXIT("Can not get PVR services jump table");
+ return EMGD_ERROR_INIT_FAILURE;
+ }
+ pvr_jtable = &devinfo->pvr_jtable;
+
+
+ /*
+ * Setup the jump table that PVR services uses to call this 3rd-party
+ * display driver:
+ */
+ devinfo->dc_jtable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+ devinfo->dc_jtable.pfnOpenDCDevice = OpenDCDevice;
+ devinfo->dc_jtable.pfnCloseDCDevice = CloseDCDevice;
+ devinfo->dc_jtable.pfnEnumDCFormats = EnumDCFormats;
+ devinfo->dc_jtable.pfnEnumDCDims = EnumDCDims;
+ devinfo->dc_jtable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+ devinfo->dc_jtable.pfnGetDCInfo = GetDCInfo;
+ devinfo->dc_jtable.pfnGetBufferAddr = GetDCBufferAddr;
+ devinfo->dc_jtable.pfnCreateDCSwapChain = CreateDCSwapChain;
+ devinfo->dc_jtable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+ devinfo->dc_jtable.pfnSetDCDstRect = SetDCDstRect;
+ devinfo->dc_jtable.pfnSetDCSrcRect = SetDCSrcRect;
+ devinfo->dc_jtable.pfnSetDCDstColourKey = SetDCDstColourKey;
+ devinfo->dc_jtable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+ devinfo->dc_jtable.pfnGetDCBuffers = GetDCBuffers;
+ devinfo->dc_jtable.pfnSwapToDCBuffer = SwapToDCBuffer;
+ devinfo->dc_jtable.pfnSwapToDCSystem = SwapToDCSystem;
+ devinfo->dc_jtable.pfnSetDCState = SetDCState;
+
+
+ /*
+ * Register this device with PVR services:
+ */
+ if (pvr_jtable->pfnPVRSRVRegisterDCDevice(&devinfo->dc_jtable,
+ &devinfo->device_id ) != PVRSRV_OK) {
+ EMGD_ERROR_EXIT("Device registration failed");
+ return EMGD_ERROR_DEVICE_REGISTER_FAILED;
+ }
+
+ EMGD_DEBUG("Device ID: %d", (int)devinfo->device_id);
+
+
+ /*
+ * Tell PVR services about the function to process swap-chain buffer
+ * flips:
+ */
+ cmd_proc_list[DC_FLIP_COMMAND] = emgddc_process_flip;
+
+ /* FIXME: Not sure what these are for: */
+ sync_count_list[DC_FLIP_COMMAND][0] = 0;
+ sync_count_list[DC_FLIP_COMMAND][1] = 2;
+
+ if (pvr_jtable->pfnPVRSRVRegisterCmdProcList(devinfo->device_id,
+ &cmd_proc_list[0],
+ sync_count_list,
+ EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
+ EMGD_ERROR_EXIT("Can't register callback\n");
+ return EMGD_ERROR_CANT_REGISTER_CALLBACK;
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return EMGD_OK;
+
+} /* emgddc_init_devinfo() */
+
+
+/**
+ * Initializes the display/device-specific values of the devinfo structure for
+ * a specified display (primary or secondary). This function is called during
+ * initialization time, and whenever the EMGD driver does a potential mode
+ * change, via alter_displays().
+ *
+ * @param devinfo (IN/OUT) The devinfo to initialize for the display.
+ * @param display (IN) The specified display (primary or secondary).
+ * @param port_number (IN) The port number of the specified display.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static emgd_error_t init_display(emgddc_devinfo_t *devinfo,
+ igd_display_h display,
+ unsigned short port_number)
+{
+ drm_emgd_priv_t *priv = devinfo->priv;
+ igd_context_t *context = priv->context;
+ unsigned long dc = priv->dc;
+ igd_framebuffer_info_t fb_info;
+ DISPLAY_FORMAT *display_format_list;
+ igd_display_info_t pt_info;
+ unsigned long *fb_list_pfs;
+ DISPLAY_DIMS *display_dim_list;
+ igd_display_info_t *mode_list = NULL;
+ igd_display_info_t *mode;
+ int mode_flags = IGD_QUERY_LIVE_MODES;
+ emgddc_buffer_t *buffer = &(devinfo->system_buffer);
+ int i = 1, j, ret;
+
+ EMGD_TRACE_ENTER;
+
+ EMGD_DEBUG("Parameters:");
+ EMGD_DEBUG(" devinfo=0x%p", devinfo);
+ EMGD_DEBUG(" devinfo->which_devinfo=%d", devinfo->which_devinfo);
+ EMGD_DEBUG(" display=0x%p", display);
+ EMGD_DEBUG(" port_number=%u", port_number);
+
+ /* Clear the following lists, in case we are re-initializing: */
+ OS_MEMSET(devinfo->display_format_list, 0,
+ sizeof(devinfo->display_format_list));
+ OS_MEMSET(devinfo->display_dim_list, 0,
+ sizeof(devinfo->display_dim_list));
+ display_format_list = devinfo->display_format_list;
+ display_dim_list = devinfo->display_dim_list;
+
+
+ /* Call get_display() to get some of the following info: */
+ ret = context->dispatch.get_display(display, port_number,
+ &fb_info, &pt_info, 0);
+ if (0 != ret) {
+ EMGD_ERROR_EXIT("get_display() returned %d", ret);
+ return EMGD_ERROR_GENERIC;
+ }
+
+
+ /*
+ * Obtain the following addresses:
+ *
+ * - buffer->offset = Framebuffer GTT address
+ * - virt_addr = gmm_map(framebuffer offset);
+ */
+ buffer->offset = fb_info.fb_base_offset;
+ if(NULL == buffer->virt_addr){
+ buffer->virt_addr = context->dispatch.gmm_map(fb_info.fb_base_offset);
+ }
+ EMGD_DEBUG("buffer->virt_addr = 0x%p", buffer->virt_addr);
+ /* This is the offset of the allocated framebuffer (e.g. the
+ * 1024x768 surface of gmm-managed memory):
+ */
+ EMGD_DEBUG("fb_info->fb_base_offset = 0x%lx", fb_info.fb_base_offset);
+
+
+ /* Register (if we haven't) with the HAL to be able to use interrupts: */
+ if (!devinfo->interrupt_h) {
+ devinfo->interrupt_h =
+ context->dispatch.register_vblank_callback(emgddc_process_vblank,
+ devinfo, port_number);
+ if (!devinfo->interrupt_h) {
+ /* This should not happen, but just in case, provide an error: */
+ printk(KERN_ERR "Cannot establish the ability to perform VBlank "
+ "interrupts for port number %u.", port_number);
+ }
+ }
+
+
+ /*
+ * Obtain and translate pixel formats:
+ */
+ /* Note: We always care about the current pixel format: */
+ devinfo->emgd_pf = fb_info.pixel_format;
+ devinfo->pvr_pf = emgd2pvr_pf(fb_info.pixel_format);
+ display_format_list[0].pixelformat = emgd2pvr_pf(fb_info.pixel_format);
+ EMGD_DEBUG("FB's native EMGD pixel format = 0x%08lx", devinfo->emgd_pf);
+ EMGD_DEBUG("FB's PVR pixel format = %u",display_format_list[0].pixelformat);
+ if (!priv->xserver_running) {
+ /* In addition, provide an entire list of pixel formats: */
+ ret = context->dispatch.get_pixelformats(display, &fb_list_pfs, NULL,
+ NULL, NULL, NULL);
+ if (0 != ret) {
+ EMGD_ERROR_EXIT("get_pixelformats() returned %d", ret);
+ return EMGD_ERROR_GENERIC;
+ }
+ while (*fb_list_pfs) {
+ if ((devinfo->pvr_pf != emgd2pvr_pf(*fb_list_pfs)) &&
+ (PVRSRV_PIXEL_FORMAT_UNKNOWN != emgd2pvr_pf(*fb_list_pfs))) {
+ display_format_list[i].pixelformat = emgd2pvr_pf(*fb_list_pfs);
+ EMGD_DEBUG(" Add'l (%d) PVR pixel format = "
+ "%u", i, emgd2pvr_pf(*fb_list_pfs));
+ }
+ fb_list_pfs++;
+ if (++i >= EMGDDC_MAXFORMATS) {
+ /* Don't write past the end of the array */
+ EMGD_ERROR("Reached end of display_format_list! Consider "
+ "increasing EMGDDC_MAXFORMATS.");
+ break;
+ }
+ }
+ }
+ devinfo->num_formats = i;
+ EMGD_DEBUG("Total number of translated pixel formats = %d", i);
+
+
+ /*
+ * Obtain the possible dimensions, from the EMGD modes:
+ */
+ /* Note: we always care about the current dimensions: */
+ devinfo->width = fb_info.width;
+ devinfo->height = fb_info.height;
+ devinfo->byte_stride = fb_info.screen_pitch;
+ EMGD_DEBUG("FB's width = %ld, height = %ld, stride = %ld",
+ devinfo->width, devinfo->height, devinfo->byte_stride);
+ display_dim_list[0].ui32Width = fb_info.width;
+ display_dim_list[0].ui32Height = fb_info.height;
+ display_dim_list[0].ui32ByteStride = fb_info.screen_pitch;
+ i = 1;
+ if (!priv->xserver_running) {
+ /* In addition, provide an entire list of dimensions: */
+ ret = context->dispatch.query_mode_list((igd_driver_h) context, dc,
+ &mode_list, mode_flags);
+ if (0 != ret) {
+ EMGD_ERROR_EXIT("query_mode_list() returned %d", ret);
+ return EMGD_ERROR_GENERIC;
+ }
+ mode = mode_list;
+ while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+ int seen = 0;
+ for (j = i - 1 ; j >= 0 ; j--) {
+ if ((display_dim_list[j].ui32Width == mode->width) &&
+ (display_dim_list[j].ui32Height == mode->height)) {
+ seen = 1;
+ }
+ }
+ if (!seen) {
+ display_dim_list[i].ui32Width = mode->width;
+ display_dim_list[i].ui32Height = mode->height;
+ display_dim_list[i].ui32ByteStride =
+ (mode->width * IGD_PF_BPP(devinfo->emgd_pf) + 7) >>3;
+ EMGD_DEBUG(" Add'l width = %d, height = %d, stride = %ld",
+ mode->width, mode->height,
+ display_dim_list[i].ui32ByteStride);
+ if (++i >= EMGDDC_MAXDIMS) {
+ /* Don't write past the end of the array */
+ EMGD_ERROR("Reached end of display_dim_list! Consider "
+ "increasing EMGDDC_MAXDIMS.");
+ break;
+ }
+ }
+ mode++;
+ }
+ }
+ devinfo->num_dims = i;
+ EMGD_DEBUG("Total number of dimensions = %d", i);
+
+
+ /*
+ * Obtain the size of the frame buffer, which will also be the size of any
+ * swap chain buffers:
+ */
+ devinfo->fb_size = devinfo->height * devinfo->byte_stride;
+ EMGD_DEBUG("Frame buffer size = %lu = %luMB = 0x%lx", devinfo->fb_size,
+ devinfo->fb_size / (1024 * 1024), devinfo->fb_size);
+
+
+ /*
+ * Initialize the igd_surface_t structure for the frame buffer, in order
+ * allow the buffer flipping code to flip back to the frame buffer:
+ */
+ buffer->priv = priv;
+ buffer->offset = fb_info.fb_base_offset;
+ buffer->pitch = devinfo->byte_stride;
+ buffer->width = devinfo->width;
+ buffer->height = devinfo->height;
+ buffer->pixel_format = fb_info.pixel_format;
+ buffer->size = devinfo->fb_size;
+
+
+ EMGD_TRACE_EXIT;
+ return EMGD_OK;
+
+} /* init_display() */
+
+/**
+ * Loops through the avaiable displays, invalidating the associated flip-chains
+ * This function is called from igd_alter_displays so as to resolve any race
+ * conditions that may occur due to performing a flip during a mode-set.
+ *
+ * @param display (IN) The display whose flipchains are to be invalidated.
+ */
+static int emgddc_invalidate_flip_chains(int display) {
+
+ emgddc_devinfo_t * devinfo;
+ emgddc_swapchain_t *swap_chain;
+ unsigned long lock_flags;
+ igd_surface_t surf;
+ igd_display_h display_handle;
+ igd_context_t *context;
+ int i;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters:");
+ EMGD_DEBUG("display=0x%1x",display);
+
+ for (i = 0; i < MAX_DISPLAYS; i++) {
+ if (display & (1 << i)) {
+ devinfo = global_devinfo[i];
+
+ if (devinfo == NULL) {
+ EMGD_DEBUG("Skipping NULL display at index %d", i);
+ continue;
+ }
+
+
+ /* Mode changes invalidate flip-able swap chains. We can't destroy
+ * them behind the back of PVR services, but we can and should
+ * ignore all pending and future buffer flips for existing swap
+ * chains.
+ * Note: new swap chains will be valid, and be able to perform flips.
+ */
+ /* Obtain the lock, to hold-off future interrupt handling for a bit */
+ spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+ swap_chain = devinfo->flipable_swapchains;
+ while (swap_chain != NULL) {
+ swap_chain->valid = EMGD_FALSE;
+
+ flush_flip_queue(swap_chain);
+ swap_chain = swap_chain->next;
+ }
+ /* Now that we've invalidated pending flips, release the lock */
+ spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+ /* Reset the frame-buffer information to point to the system
+ * buffer */
+ context = devinfo->priv->context;
+ display_handle = (devinfo->which_devinfo == 1)?
+ devinfo->priv->secondary:devinfo->priv->primary;
+
+ surf.offset = devinfo->system_buffer.offset;
+ surf.pitch = devinfo->system_buffer.pitch;
+ surf.width = devinfo->system_buffer.width;
+ surf.height = devinfo->system_buffer.height;
+ surf.pixel_format = devinfo->system_buffer.pixel_format;
+ surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
+
+ ret = context->dispatch.set_surface(display_handle,
+ IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+
+ if (ret) {
+ EMGD_ERROR("set_surface() returned %d for display at index %d",
+ ret, i);
+ }
+ }
+ }
+
+ EMGD_TRACE_EXIT;
+
+ return 0;
+}
+
+
+/**
+ * [Re-]Initializes the 3DD's display/device-specific values for both devinfo
+ * structures. This function is called during initializatio time, and whenever
+ * the EMGD driver does a potential mode change, via alter_displays().
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static int emgddc_reinit_3dd(struct drm_device *dev)
+{
+ emgddc_devinfo_t *devinfo;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+ if (0 == priv->dc) {
+ EMGD_DEBUG("not ready to re-init, because no dc has been set");
+ if (!priv->hal_running) {
+ /* Ensure that devinfo->interrupt_h is NULL: */
+ if (NULL != (devinfo = global_devinfo[0])) {
+ devinfo->interrupt_h = NULL;
+ }
+ if (NULL != (devinfo = global_devinfo[1])) {
+ devinfo->interrupt_h = NULL;
+ }
+ }
+ return EMGD_OK;
+ }
+
+ EMGD_DEBUG("The DC is 0x%08lx", priv->dc);
+ EMGD_DEBUG("IGD_DC_CLONE(priv->dc) is %d", IGD_DC_CLONE(priv->dc));
+ EMGD_DEBUG("IGD_DC_EXTENDED(priv->dc) is %d", IGD_DC_EXTENDED(priv->dc));
+
+ /* Always initialize the primary devinfo: */
+ ret = init_display(global_devinfo[0], priv->primary,
+ priv->primary_port_number);
+ if (ret != EMGD_OK) {
+ return ret;
+ }
+
+ /* Initialize the secondary devinfo if we're in DIH/extended mode: */
+ if (IGD_DC_EXTENDED(priv->dc)) {
+ EMGD_DEBUG("Detected that we're in DIH/EXTENDED mode");
+
+ /* Allocate the devinfo if it hasn't already been allocated: */
+ if (NULL == (devinfo = global_devinfo[1])) {
+ EMGD_DEBUG("Allocating devinfo structure for DIH/EXTENDED mode");
+ devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
+ if (!devinfo) {
+ EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
+ return EMGD_ERROR_OUT_OF_MEMORY;
+ }
+ OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
+
+ /* Perform static/display-independent initialization: */
+ ret = emgddc_init_devinfo(dev, devinfo, 1);
+ if (ret != EMGD_OK) {
+ EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
+ emgddc_free_a_devinfo(devinfo);
+ return ret;
+ }
+ }
+
+ /* Perform dynamic/display-dependent initialization: */
+ ret = init_display(devinfo, priv->secondary,
+ priv->secondary_port_number);
+ if (ret != EMGD_OK) {
+ EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
+ emgddc_free_a_devinfo(devinfo);
+ global_devinfo[1] = NULL;
+ return ret;
+ }
+
+ /* Remember the devinfo, for other functions that aren't passed it: */
+ global_devinfo[1] = devinfo;
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return EMGD_OK;
+
+} /* emgddc_reinit_3dd() */
+
+
+/**
+ * Master initialization function. This is called when the EMGD DRM module
+ * tells PVR services to start, which calls this function.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+emgd_error_t emgddc_init(struct drm_device *dev)
+{
+ emgddc_devinfo_t *devinfo;
+ drm_emgd_priv_t *priv = dev->dev_private;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+
+
+ /* Exit early if trying to initialize again: */
+ devinfo = global_devinfo[0];
+ if (devinfo != NULL) {
+ EMGD_TRACE_EXIT;
+ return EMGD_OK;
+ }
+
+ /* Always allocate the primary display's devinfo structure: */
+ devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
+ if (!devinfo) {
+ EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
+ return EMGD_ERROR_OUT_OF_MEMORY;
+ }
+ OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
+ global_devinfo[0] = devinfo;
+
+ /* Perform static/display-independent initialization: */
+ ret = emgddc_init_devinfo(dev, devinfo, 0);
+ if (ret != EMGD_OK) {
+ emgddc_free_all_devinfos();
+ return ret;
+ }
+
+ /* Perform dynamic/display-dependent initialization (if we're in
+ * DIH/Extended mode, the secondary devinfo will also be allocated and
+ * initialized):
+ */
+ priv->reinit_3dd = emgddc_reinit_3dd;
+
+ /* Used inside igd_alter_displays */
+ priv->invalidate_flip_chains = emgddc_invalidate_flip_chains;
+
+ ret = emgddc_reinit_3dd(dev);
+ if (ret != EMGD_OK) {
+ emgddc_free_all_devinfos();
+ return ret;
+ }
+
+ /* Remember the devinfo, for other functions that aren't passed it: */
+ global_devinfo[0] = devinfo;
+
+
+ EMGD_TRACE_EXIT;
+ return EMGD_OK;
+
+} /* emgddc_init() */
+
+
+/**
+ * Master de-initialization function. This is called when the EMGD DRM module
+ * is being unloaded (it tells PVR services to exit, which calls this
+ * function).
+ *
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+emgd_error_t emgddc_deinit(void)
+{
+ emgddc_devinfo_t *devinfo;
+ int i;
+ emgd_error_t ret = EMGD_OK;
+
+ EMGD_TRACE_ENTER;
+
+
+ for (i = 0 ; i < 2 ; i++) {
+ devinfo = global_devinfo[i];
+ if (devinfo == NULL) {
+ continue;
+ }
+
+
+ /* Unhook and unregister from PVR services: */
+ if (devinfo->pvr_jtable.pfnPVRSRVRemoveCmdProcList(devinfo->device_id,
+ EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
+ ret = EMGD_ERROR_GENERIC;
+ }
+ if (devinfo->pvr_jtable.pfnPVRSRVRemoveDCDevice(devinfo->device_id) !=
+ PVRSRV_OK) {
+ ret = EMGD_ERROR_GENERIC;
+ }
+
+
+ /* Delete any/all swap chains now: */
+ /* Note: If we ever support interrupts, there may be a race condition
+ * of pending flips. This was placed here, after the PVR services
+ * thinks the driver has gone away, so that no flips should come by
+ * this time.
+ */
+ while (devinfo->flipable_swapchains) {
+ if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
+ devinfo->flipable_swapchains)) {
+ ret = EMGD_ERROR_GENERIC;
+ }
+ }
+ while (devinfo->pixmap_swapchains) {
+ if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
+ devinfo->pixmap_swapchains)) {
+ ret = EMGD_ERROR_GENERIC;
+ }
+ }
+
+
+ emgddc_free_a_devinfo(devinfo);
+ global_devinfo[i] = NULL;
+ }
+
+
+ EMGD_TRACE_EXIT;
+ return ret;
+
+} /* emgddc_deinit() */
+
+
+/*
+ * Potentially perform a mode change.
+ *
+ * If the X server is running, PVR services (including this function) can't
+ * do mode changes. To avoid having to switch modes, ensure that the
+ * current pixel format and dimension is specified:
+ *
+ * If the X server is NOT running, PVR services (including this function)
+ * can do mode changes. In this case, if the pixel format and/or
+ * dimensions don't match the current mode, perform a mode change (as long
+ * as valid values are provided):
+ */
+static PVRSRV_ERROR do_mode_change(igd_context_t *context,
+ emgddc_devinfo_t *devinfo,
+ drm_emgd_priv_t *priv,
+ DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib)
+{
+ struct drm_device* drm_dev;
+ int err = PVRSRV_OK;
+
+ drm_dev = devinfo->drm_device;
+
+ if (priv->xserver_running) {
+ if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
+ (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride) ||
+ (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
+ (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ } else if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
+ (dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride)||
+ (dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
+ (dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
+ unsigned long emgd_pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
+ igd_display_info_t *mode_list = NULL;
+ igd_display_info_t *mode = NULL;
+ igd_display_info_t *desired_mode = NULL;
+ int mode_flags = IGD_QUERY_LIVE_MODES;
+ unsigned long byte_stride;
+ igd_framebuffer_info_t primary_fb_info;
+ igd_framebuffer_info_t secondary_fb_info;
+ igd_display_h primary;
+ igd_display_h secondary;
+
+ printk("[EMGD] A mode change is requested. The following new values\n"
+ "[EMGD] will be checked, and if good, take effect:\n");
+ printk("[EMGD] pixel format = %u (PVR) = 0x%08lx (EMGD)\n",
+ dst_surf_attrib->pixelformat, emgd_pf);
+ printk("[EMGD] width = %lu, height = %lu\n",
+ dst_surf_attrib->sDims.ui32Width,
+ dst_surf_attrib->sDims.ui32Height);
+ printk("[EMGD] stride = %lu\n",dst_surf_attrib->sDims.ui32ByteStride);
+
+
+ /* Check the pixel format: */
+ if (IGD_PF_UNKNOWN == emgd_pf) {
+ printk(KERN_ERR "Unknown pixel format %u\n",
+ dst_surf_attrib->pixelformat);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ /* Check the width, height, and stride: */
+ EMGD_DEBUG("Calling query_mode_list()");
+ err = context->dispatch.query_mode_list(context, priv->dc,
+ &mode_list, mode_flags);
+ if (err) {
+ printk(KERN_ERR "The query_mode_list() function returned %d.", err);
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ EMGD_DEBUG("Comparing the mode list with the desired width, height, "
+ "and stride...");
+ mode = mode_list;
+ while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+ byte_stride = IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
+ EMGD_DEBUG(" ... Found a mode with width=%d, height=%d, "
+ "refresh=%d;", mode->width, mode->height, mode->refresh);
+ if ((mode->width == dst_surf_attrib->sDims.ui32Width) &&
+ (mode->height == dst_surf_attrib->sDims.ui32Height) &&
+ (byte_stride == dst_surf_attrib->sDims.ui32ByteStride)) {
+ EMGD_DEBUG(" ... This mode is a match!");
+ desired_mode = mode;
+ break;
+ }
+ mode++;
+ }
+ if (NULL == desired_mode) {
+ printk(KERN_ERR "No mode matching the desired width (%lu), height "
+ "(%lu), and stride (%lu) was found.",
+ dst_surf_attrib->sDims.ui32Width,
+ dst_surf_attrib->sDims.ui32Height,
+ dst_surf_attrib->sDims.ui32ByteStride);
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ } else {
+ /* Must set this in order to get the timings setup: */
+ desired_mode->flags |= IGD_DISPLAY_ENABLE;
+ }
+
+
+ /* Make the mode change by calling alter_displays(): */
+ primary_fb_info.width = desired_mode->width;
+ primary_fb_info.height = desired_mode->height;
+ primary_fb_info.pixel_format = emgd_pf;
+ primary_fb_info.flags = 0;
+ primary_fb_info.allocated = 0;
+ memcpy(&secondary_fb_info, &primary_fb_info,
+ sizeof(igd_framebuffer_info_t));
+
+ EMGD_DEBUG("Calling alter_displays()");
+ err = context->dispatch.alter_displays(context,
+ &primary, desired_mode, &primary_fb_info,
+ &secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
+ if (err) {
+ printk(KERN_ERR "The alter_displays() function returned %d.", err);
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+
+
+ /* Update the private copy, like emgd_alter_displays() would do: */
+ priv->primary = primary;
+ priv->secondary = secondary;
+ priv->primary_port_number = (priv->dc & 0xf0) >> 4;
+ priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
+
+
+ /* Re-initialize the display values: */
+ err = priv->reinit_3dd(drm_dev);
+ if (err != EMGD_OK) {
+ printk(KERN_ERR "The reinit_3dd() function returned %d.", err);
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ } /* end of mode-change code */
+
+ return err;
+} /* do_mode_change() */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
new file mode 100644
index 0000000..8ea6d33
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
@@ -0,0 +1,342 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef EMGD_DC_H
+#define EMGD_DC_H
+
+#include <drm/drmP.h>
+#include "memory.h"
+#include "io.h"
+#include "emgd_shared.h"
+
+
+#define EMGDDC_MAXFORMATS 20
+#define EMGDDC_MAXDIMS 20
+
+
+#define DISPLAY_DEVICE_NAME "Intel EMGD Display Driver"
+#define DRVNAME "emgd_dc"
+#define DEVNAME DRVNAME
+#define DRIVER_PREFIX DRVNAME
+
+
+#define EMGD_TRACE_STUB \
+ EMGD_DEBUG("Inside the stubbed %s() function", __FUNCTION__)
+
+
+typedef struct _emgddc_devinfo emgddc_devinfo_t;
+
+
+typedef enum tag_emgd_bool
+{
+ EMGD_FALSE = 0,
+ EMGD_TRUE = 1,
+} emgd_bool;
+
+
+/**
+ * A pair of equivalent pixel formats, one in the EMGD format, one in the PVR
+ * format. This structure is used to translate between the two formats.
+ */
+typedef struct _emgddc_pixelformat_translator
+{
+ /** An EMGD-formatted pixel format. */
+ unsigned long emgd_pf;
+
+ /** A PVR-formatted pixel format. */
+ PVRSRV_PIXEL_FORMAT pvr_pf;
+} emgddc_pixelformat_translator_t;
+
+
+/** Information about a given swap chain buffer. */
+typedef struct _emgddc_buffer
+{
+ /** A copy of the drm_emgd_private associated with this buffer. */
+ drm_emgd_priv_t *priv;
+
+ /** The GMM offset of this buffer's memory. */
+ unsigned long offset;
+
+ /** This buffer's EMGD-formatted pixel format. */
+ unsigned long pixel_format;
+
+ /** This buffer's width. */
+ unsigned long width;
+
+ /** This buffer's height. */
+ unsigned long height;
+
+ /**
+ * This buffer's stride (i.e. number of bytes between the same point on
+ * successive scanlines).
+ */
+ unsigned long pitch;
+
+ /** This buffer's size. */
+ unsigned long size;
+
+ /** Is this buffer the framebuffer (a.k.a. system buffer). */
+ int is_fb;
+
+ /**
+ * The memory-mapped virtual address of the buffer (obtained from
+ * gmm_map())
+ */
+ IMG_CPU_VIRTADDR virt_addr;
+
+ /** The PVR sync data for this buffer */
+ PVRSRV_SYNC_DATA *sync_data;
+
+ unsigned long is_contiguous;
+
+ /**
+ * The PVR next buffer in the swap chain (the last buffer points to the
+ * first buffer
+ */
+ struct _emgddc_buffer *next;
+} emgddc_buffer_t;
+
+
+/** Information for queueing a flip for a given swap chain buffer. */
+typedef struct _emgddc_flip_queue_item
+{
+ /**
+ * A handle to a PVR services data structure that must be passed to
+ * PVRSRVCmdComplete(), in order to "complete" a flip (i.e. when PVR
+ * services knows that the 3DD has caused the flip to occur, and as such,
+ * when its queue-processing code can call emgddc_process_flip() to
+ * start/queue another flip). "Completing" a flip does not mean that the
+ * flip has reached the end of its swap_interval and been "cleared."
+ */
+ IMG_HANDLE cmd_complete;
+
+ /**
+ * The number of VBlanks after a flip occurs, before the next flip can
+ * start.
+ */
+ unsigned long swap_interval;
+
+ /** Whether the corresponding buffer has a flip in progress. */
+ emgd_bool valid;
+
+ /**
+ * Whether the corresponding buffer completed a flip. This can only be
+ * EMGD_TRUE if valid is also EMGD_TRUE.
+ */
+ emgd_bool flipped;
+
+ /**
+ * Whether the corresponding buffer told PVR services that it completed a
+ * flip. This can only be EMGD_TRUE if flipped is also EMGD_TRUE.
+ */
+ emgd_bool cmd_completed;
+
+ /** Which buffer is associated with this flip_item. */
+ emgddc_buffer_t *buffer;
+
+} emgddc_flip_queue_item_t;
+
+
+/** Information about a given swap chain. */
+typedef struct _emgddc_swapchain
+{
+ /**
+ * Pointer to the parent devinfo, so that emgddc_flip() can lookup which
+ * device (and therefore, which igd_display_t) to use.
+ */
+ emgddc_devinfo_t *devinfo;
+
+ /** Whether this swap chain is valid for buffer flipping. */
+ emgd_bool valid;
+
+ /** Number of buffers in this swap chain. */
+ unsigned long buffer_count;
+
+ /** An array of the buffers in this swap chain. */
+ emgddc_buffer_t *buffers;
+
+ /** An array of the structures that keep track of queued flips. Each flip
+ * item corresponds to the identically-numbered buffer in this swap chain.
+ */
+ emgddc_flip_queue_item_t *flip_queue;
+
+ /** Index into both the buffers and flip_queue arrays. Used when queueing
+ * (or inserting) flips. Is incremented until it gets too large, and then
+ * is zero'd-out.
+ */
+ unsigned long insert_index;
+
+ /** Index into both the buffers and flip_queue arrays. Used when flushing
+ * (or removing from) the flip queue. Is incremented until it gets too
+ * large, and then is zero'd-out.
+ */
+ unsigned long remove_index;
+
+#ifdef SUPPORT_FB_EVENTS
+ emgd_bool blanked;
+#endif /* SUPPORT_FB_EVENTS */
+
+ /** Type of swap chain */
+ unsigned long flags;
+
+ /** A copy of emgddc_devinfo_t.pvr_jtable. */
+ PVRSRV_DC_DISP2SRV_KMJTABLE *pvr_jtable;
+
+ /** Next swap chain in the list */
+ struct _emgddc_swapchain *next;
+} emgddc_swapchain_t;
+
+
+/** Information about the device. */
+struct _emgddc_devinfo
+{
+ /*
+ * The following values are display-dependent, and are dynamically
+ * re-initialized after an EMGD alter_displays() call:
+ */
+
+ /** The size (in bytes) of the framebuffer and future swap chain buffers. */
+ unsigned long fb_size;
+
+ /** The width (in pixels) of the framebuffer. */
+ unsigned long width;
+
+ /** The height (in pixels) of the framebuffer. */
+ unsigned long height;
+
+ /** The stride (in bytes) from one row of the framebuffer to another. */
+ unsigned long byte_stride;
+
+ /* The number of dimensions for the primary display: */
+ unsigned long num_dims;
+
+ /* The supported dimensions for the primary display: */
+ DISPLAY_DIMS display_dim_list[EMGDDC_MAXDIMS];
+
+ /** The one EMGD-formatted pixel format (before translation) being used. */
+ unsigned long emgd_pf;
+
+ /** The one PVR-formatted pixel format (after translation) being used. */
+ PVRSRV_PIXEL_FORMAT pvr_pf;
+
+ /** The number of pixel formats for the primary display. */
+ unsigned long num_formats;
+
+ /** The supported PVR pixel formats for the primary display. */
+ DISPLAY_FORMAT display_format_list[EMGDDC_MAXFORMATS];
+
+ /** The frame buffer (a.k.a. "system buffer" or "front buffer"). */
+ emgddc_buffer_t system_buffer;
+
+
+ /*
+ * The following values are display-independent, are statically
+ * initialized at start-up time, and some may be altered during run time:
+ */
+
+ /** 0 for the primary devinfo, 1 for the secondary/DIH mode devinfo */
+ int which_devinfo;
+
+ /** A copy of the drm_emgd_private associated with this devinfo. */
+ drm_emgd_priv_t *priv;
+
+ /** Private copy of the drm_device associated with this devinfo. */
+ struct drm_device *drm_device;
+
+ /**
+ * The first of potentially multiple swap chains that support full-screen
+ * buffer flipping.
+ */
+ emgddc_swapchain_t *flipable_swapchains;
+
+ /** The first of potentially many swap chains that support pixmaps. */
+ emgddc_swapchain_t *pixmap_swapchains;
+
+ /** Counter to provide unique IDs to each swap chain. */
+ unsigned long swap_chain_id_counter;
+
+ /** Static information about swap chains, plus the driver's string name. */
+ DISPLAY_INFO display_info;
+
+ /** HAL handle associated with this devinfo for dealing with interrupts. */
+ emgd_vblank_callback_h interrupt_h;
+
+ /** Handle very rare case of not being able to [re-]enable interrupts. */
+ emgd_bool flipping_disabled;
+
+ /** If EMGD_TRUE, don't queue buffer flips, but flip/complete right away. */
+ emgd_bool flush_commands;
+
+ /**
+ * A counter so that the state of flush_commands must be set to EMGD_TRUE
+ * and EMGD_FALSE an equal number of times before the state actually
+ * changes.
+ */
+ unsigned long set_flush_state_ref_count;
+
+ /**
+ * A spinlock to prevent contention between regular code and
+ * interrupt-handling code.
+ */
+ spinlock_t swap_chain_lock;
+
+#ifdef SUPPORT_FB_EVENTS
+ struct notifier_block lin_notif_block;
+#endif /* SUPPORT_FB_EVENTS */
+
+ /** PVR services functions. */
+ PVRSRV_DC_DISP2SRV_KMJTABLE pvr_jtable;
+
+ /** Functions we provide to PVR services. */
+ PVRSRV_DC_SRV2DISP_KMJTABLE dc_jtable;
+
+ /** This device's numeric ID, obtained when registering with PVR services */
+ unsigned long device_id;
+
+};
+
+
+typedef enum _emgd_error
+{
+ EMGD_OK = 0,
+ EMGD_ERROR_GENERIC = 1,
+ EMGD_ERROR_OUT_OF_MEMORY = 2,
+ EMGD_ERROR_TOO_FEW_BUFFERS = 3,
+ EMGD_ERROR_INVALID_PARAMS = 4,
+ EMGD_ERROR_INIT_FAILURE = 5,
+ EMGD_ERROR_CANT_REGISTER_CALLBACK = 6,
+ EMGD_ERROR_INVALID_DEVICE = 7,
+ EMGD_ERROR_DEVICE_REGISTER_FAILED = 8
+} emgd_error_t;
+
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+
+emgd_error_t emgddc_init(struct drm_device * dev);
+emgd_error_t emgddc_deinit(void);
+
+void emgddc_flip(emgddc_swapchain_t *swap_chain, emgddc_buffer_t *buffer);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
new file mode 100644
index 0000000..c8d8cdf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
@@ -0,0 +1,153 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+#define MODULE_NAME hal.pvr3dd
+
+#include "drm_emgd_private.h"
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "emgd_dc.h"
+
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+
+/* The following macros exist to help the PVR services code name/find and call
+ * the Init and Cleanup functions below. The DISPLAY_CONTROLLER macro must be
+ * set in the build, so that the PVR service code can use the same magic to
+ * discover the name of the Init and Cleanup functions for this driver.
+ */
+#if !defined(DISPLAY_CONTROLLER)
+#define DISPLAY_CONTROLLER emgd_dc
+#endif
+#define MAKENAME_HELPER(x, y) x ## y
+#define MAKENAME2(x, y) MAKENAME_HELPER(x, y)
+#define MAKENAME(x) MAKENAME2(DISPLAY_CONTROLLER, x)
+
+
+/* The following tells GCC to not warn about ununsed functions: */
+#define unref__ __attribute__ ((unused))
+
+
+/**
+ * Function that initializes and starts this 3rd-party display driver. This is
+ * called by the PVR services when it starts.
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ */
+int MAKENAME(_Init)(struct drm_device unref__ *dev)
+{
+ EMGD_TRACE_ENTER;
+
+ if (emgddc_init(dev) != EMGD_OK) {
+ EMGD_ERROR_EXIT(DRVNAME " init failed (" DISPLAY_DEVICE_NAME ")\n");
+ return -ENODEV;
+ }
+
+ EMGD_TRACE_EXIT;
+ return 0;
+}
+
+
+/**
+ * Function that shuts-down and de-initializes this 3rd-party display driver.
+ * This is called by the PVR services when it ends.
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ */
+void MAKENAME(_Cleanup)(struct drm_device unref__ *dev)
+{
+ EMGD_TRACE_ENTER;
+
+ if (emgddc_deinit() != EMGD_OK) {
+ EMGD_ERROR_EXIT(DRVNAME " de-init failed (" DISPLAY_DEVICE_NAME ")\n");
+ }
+
+ EMGD_TRACE_EXIT;
+}
+
+
+/**
+ * Set the display to the surface specified by buffer.
+ *
+ * @param swap_chain (IN) Pointer to the swap chain associated with buffer.
+ * @param buffer (IN) Pointer to the buffer to display.
+ */
+void emgddc_flip(emgddc_swapchain_t *swap_chain, emgddc_buffer_t *buffer)
+{
+ drm_emgd_priv_t *priv = buffer->priv;
+ igd_context_t *context = priv->context;
+ igd_surface_t surf;
+ int ret;
+
+ EMGD_TRACE_ENTER;
+ EMGD_DEBUG("Parameters: swap_chain=0x%p", swap_chain);
+ EMGD_DEBUG(" buffer=0x%p, *buffer->offset=0x%08lx",
+ buffer, buffer->offset);
+
+ if (EMGD_FALSE == swap_chain->valid) {
+ EMGD_DEBUG("Not flipping--swap chain invalidated by a mode change.");
+ EMGD_TRACE_EXIT;
+ return;
+ }
+
+ surf.offset = buffer->offset;
+ surf.pitch = buffer->pitch;
+ surf.width = buffer->width;
+ surf.height = buffer->height;
+ surf.pixel_format = buffer->pixel_format;
+ surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
+
+ /* Flip the primary surface. Select a different EMGD display depending on
+ * the DC & devinfo:
+ */
+ if (IGD_DC_EXTENDED(priv->dc) &&
+ (swap_chain->devinfo->which_devinfo == 1)) {
+ ret = context->dispatch.set_surface(priv->secondary,
+ IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+ if (ret != 0) {
+ printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+ }
+ } else {
+ ret = context->dispatch.set_surface(priv->primary,
+ IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+ if (ret != 0) {
+ printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+ }
+ }
+
+ /* Flip the secondary surface: */
+ if (IGD_DC_CLONE(priv->dc)) {
+ /* If in clone mode, flip the other pipe too: */
+ ret = context->dispatch.set_surface(priv->secondary,
+ IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+ if (ret != 0) {
+ printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+ }
+ }
+
+
+ EMGD_TRACE_EXIT;
+} /* emgddc_flip() */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h b/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
new file mode 100644
index 0000000..7f0f445
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
@@ -0,0 +1,59 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_CMD DRM_PVR_RESERVED1
+#define PVR_DRM_DISP_CMD DRM_PVR_RESERVED2
+#define PVR_DRM_BC_CMD DRM_PVR_RESERVED3
+#define PVR_DRM_IS_MASTER_CMD DRM_PVR_RESERVED4
+#define PVR_DRM_UNPRIV_CMD DRM_PVR_RESERVED5
+#define PVR_DRM_DBGDRV_CMD DRM_PVR_RESERVED6
+#else
+#define PVR_DRM_SRVKM_CMD 0
+#define PVR_DRM_DISP_CMD 1
+#define PVR_DRM_BC_CMD 2
+#define PVR_DRM_IS_MASTER_CMD 3
+#define PVR_DRM_UNPRIV_CMD 4
+#define PVR_DRM_DBGDRV_CMD 5
+#endif
+
+#define PVR_DRM_UNPRIV_INIT_SUCCESFUL 0
+#define PVR_DRM_UNPRIV_BUSID_TYPE 1
+#define PVR_DRM_UNPRIV_BUSID_FIELD 2
+
+#define PVR_DRM_BUS_TYPE_PCI 0
+
+#define PVR_DRM_PCI_DOMAIN 0
+#define PVR_DRM_PCI_BUS 1
+#define PVR_DRM_PCI_DEV 2
+#define PVR_DRM_PCI_FUNC 3
+
+#endif
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h b/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
new file mode 100644
index 0000000..4bf59b1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_BC_DEVICE pfnOpenBCDevice;
+ PFN_CLOSE_BC_DEVICE pfnCloseBCDevice;
+ PFN_GET_BC_INFO pfnGetBCInfo;
+ PFN_GET_BC_BUFFER pfnGetBCBuffer;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ PFN_GET_BUFFER_ID_FROM_TAG pfnGetBufferIdFromTag;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_BC_REGISTER_BUFFER_DEV pfnPVRSRVRegisterBCDevice;
+ PFN_BC_REMOVE_BUFFER_DEV pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h b/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
new file mode 100644
index 0000000..b14c131
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
@@ -0,0 +1,152 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+ DISPLAY_FORMAT*,
+ IMG_UINT32*,
+ DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_UINT32,
+ DISPLAY_SURF_ATTRIBUTES*,
+ DISPLAY_SURF_ATTRIBUTES*,
+ IMG_UINT32,
+ PVRSRV_SYNC_DATA**,
+ IMG_UINT32,
+ IMG_HANDLE*,
+ IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32*,
+ IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_DC_DEVICE pfnOpenDCDevice;
+ PFN_CLOSE_DC_DEVICE pfnCloseDCDevice;
+ PFN_ENUM_DC_FORMATS pfnEnumDCFormats;
+ PFN_ENUM_DC_DIMS pfnEnumDCDims;
+ PFN_GET_DC_SYSTEMBUFFER pfnGetDCSystemBuffer;
+ PFN_GET_DC_INFO pfnGetDCInfo;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ PFN_CREATE_DC_SWAPCHAIN pfnCreateDCSwapChain;
+ PFN_DESTROY_DC_SWAPCHAIN pfnDestroyDCSwapChain;
+ PFN_SET_DC_DSTRECT pfnSetDCDstRect;
+ PFN_SET_DC_SRCRECT pfnSetDCSrcRect;
+ PFN_SET_DC_DSTCK pfnSetDCDstColourKey;
+ PFN_SET_DC_SRCCK pfnSetDCSrcColourKey;
+ PFN_GET_DC_BUFFERS pfnGetDCBuffers;
+ PFN_SWAP_TO_DC_BUFFER pfnSwapToDCBuffer;
+ PFN_SWAP_TO_DC_SYSTEM pfnSwapToDCSystem;
+ PFN_SET_DC_STATE pfnSetDCState;
+ PFN_QUERY_SWAP_COMMAND_ID pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+ PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+ IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_DC_REGISTER_DISPLAY_DEV pfnPVRSRVRegisterDCDevice;
+ PFN_DC_REMOVE_DISPLAY_DEV pfnPVRSRVRemoveDCDevice;
+ PFN_DC_OEM_FUNCTION pfnPVRSRVOEMFunction;
+ PFN_DC_REGISTER_COMMANDPROCLIST pfnPVRSRVRegisterCmdProcList;
+ PFN_DC_REMOVE_COMMANDPROCLIST pfnPVRSRVRemoveCmdProcList;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVCmdComplete;
+ PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler;
+ PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket;
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+
+ IMG_HANDLE hExtDevice;
+
+
+ IMG_HANDLE hExtSwapChain;
+
+
+ IMG_HANDLE hExtBuffer;
+
+
+ IMG_HANDLE hPrivateTag;
+
+
+ IMG_UINT32 ui32ClipRectCount;
+
+
+ IMG_RECT *psClipRect;
+
+
+ IMG_UINT32 ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+#define DC_FLIP_COMMAND 0
+
+#define DC_STATE_NO_FLUSH_COMMANDS 0
+#define DC_STATE_FLUSH_COMMANDS 1
+
+
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
new file mode 100644
index 0000000..9e6004e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
@@ -0,0 +1,1380 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+#ifdef __linux__
+
+ #include <linux/ioctl.h>
+
+ #define PVRSRV_IOC_GID 'g'
+ #define PVRSRV_IO(INDEX) _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOW(INDEX) _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOR(INDEX) _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOWR(INDEX) _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else
+
+ #error Unknown platform: Cannot define ioctls
+
+ #define PVRSRV_IO(INDEX) (PVRSRV_IOC_GID + INDEX)
+ #define PVRSRV_IOW(INDEX) (PVRSRV_IOC_GID + INDEX)
+ #define PVRSRV_IOR(INDEX) (PVRSRV_IOC_GID + INDEX)
+ #define PVRSRV_IOWR(INDEX) (PVRSRV_IOC_GID + INDEX)
+
+ #define PVRSRV_BRIDGE_BASE PVRSRV_IOC_GID
+#endif
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0UL
+#define PVRSRV_BRIDGE_ENUM_DEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_CONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST (PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SIM_CMD_LAST (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST (PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST (PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST (PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_FB_STATS PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_STATS_CMD_LAST (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST (PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MISC_CMD_LAST (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#endif
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_REG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_REGPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_COMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_PDUMP_PDREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST (PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_OEM_CMD_LAST (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST (PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST (PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST (PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST (PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+4)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST (PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST (PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST (PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST (PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST (PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST (PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+#define PVRSRV_KERNEL_MODE_CLIENT 1
+
+typedef struct PVRSRV_BRIDGE_RETURN_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvData;
+
+}PVRSRV_BRIDGE_RETURN;
+
+
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+ IMG_UINT32 ui32BridgeID;
+ IMG_UINT32 ui32Size;
+ IMG_VOID *pvParamIn;
+ IMG_UINT32 ui32InBufferSize;
+ IMG_VOID *pvParamOut;
+ IMG_UINT32 ui32OutBufferSize;
+
+ IMG_HANDLE hKernelServices;
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 uiDevIndex;
+ PVRSRV_DEVICE_TYPE eDeviceType;
+
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS sDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS DeviceClass;
+ IMG_VOID* pvDevInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 ui32Attribs;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_PVOID pvLinAddr;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_SIZE_T ui32QueueSize;
+
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hMHandle;
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hMHandle;
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR *psDevVAddr;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hKernelServices;
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hDstDevMemHeap;
+
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psDstKernelSyncInfo;
+ PVRSRV_CLIENT_MEM_INFO sDstClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sDstClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceClassBuffer;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_BOOL bIsRead;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvLinAddr;
+ IMG_PVOID pvAltLinAddr;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvAltLinAddr;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Mask;
+ IMG_UINT32 ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_DEV_PHYADDR *pPages;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_VIRTADDR sDevAddr;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Length;
+ IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Frame;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32StrideInBytes;
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+ IMG_UINT32 ui32Size;
+ PDUMP_PIXEL_FORMAT ePixelFormat;
+ PDUMP_MEM_FORMAT eMemFormat;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Address;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+
+typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32RegOffset;
+ IMG_BOOL bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ IMG_UINT32 ui32DevID[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hDevCookie;
+
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceKM;
+
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+ IMG_VOID *pvLinAddr;
+ IMG_SIZE_T ui32ByteSize;
+ IMG_SIZE_T ui32PageOffset;
+ IMG_BOOL bPhysContig;
+ IMG_UINT32 ui32NumPageTableEntries;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS 10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS 10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS 4
+#define PVRSRV_MAX_DC_CLIP_RECTS 32
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_FORMAT asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ DISPLAY_FORMAT sFormat;
+
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_DIMS asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ DISPLAY_INFO sDisplayInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBuffer;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_UINT32 ui32Flags;
+ DISPLAY_SURF_ATTRIBUTES sDstSurfAttrib;
+ DISPLAY_SURF_ATTRIBUTES sSrcSurfAttrib;
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32OEMFlags;
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSwapChain;
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+ IMG_RECT sRect;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+ IMG_UINT32 ui32CKColour;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BufferCount;
+ IMG_HANDLE ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hBuffer;
+ IMG_UINT32 ui32SwapInterval;
+ IMG_HANDLE hPrivateTag;
+ IMG_UINT32 ui32ClipRectCount;
+ IMG_RECT sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceKM;
+
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ BUFFER_INFO sBufferInfo;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_UINT32 ui32BufferIndex;
+
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBuffer;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemContext;
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemHeap;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+ IMG_UINT64 ui64Stamp;
+#endif
+
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_PVOID pvLinAddr;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Free;
+ IMG_SIZE_T ui32LargestBlock;
+
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+#include "pvrmmap.h"
+typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+
+ IMG_UINT32 ui32ByteOffset;
+
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bMUnmap;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+ IMG_UINT32 ui32RealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_BOOL bIsCapturing;
+
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Available;
+
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_SYS_PHYADDR sSysPhysAddr;
+ IMG_UINT32 uiSizeInBytes;
+
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_PVOID pvUserAddr;
+ IMG_UINT32 uiActualSize;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvUserAddr;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+ IMG_PVOID *ppvTbl;
+ IMG_UINT32 uiTblSize;
+
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_SYS_PHYADDR sRegsPhysBase;
+ IMG_VOID *pvRegsBase;
+ IMG_PVOID pvProcess;
+ IMG_UINT32 ulNoOfEntries;
+ IMG_PVOID pvTblLinAddr;
+
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+ IMG_VOID *pvRegsBase;
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32StatusAndMask;
+ PVRSRV_ERROR eError;
+
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+
+typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+ IMG_SIZE_T ui32Size;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR_TAG
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+ IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32WriteOpsPending;
+
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
new file mode 100644
index 0000000..063ffb5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
@@ -0,0 +1,292 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32 uiDevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbShared
+ );
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+ ", " #alignment "," #memInfo "): " logStr " (size = 0x%;x)", size)),\
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo))
+#else
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferIdFromTagKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE pidx);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+
+PVRSRV_ERROR PVRSRVGetFBStatsKM(IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Available);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVGetPageListKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo, struct page ***pvPageList,
+ unsigned long *numpages,
+ unsigned long *offset);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
new file mode 100644
index 0000000..54f1121
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+
+
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
new file mode 100755
index 0000000..7c8ed47
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
@@ -0,0 +1,189 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+ switch (eError)
+ {
+ case PVRSRV_OK: return "No Errors";
+ case PVRSRV_ERROR_GENERIC: return "Generic error - fix";
+ case PVRSRV_ERROR_OUT_OF_MEMORY: return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+ case PVRSRV_ERROR_TOO_FEW_BUFFERS: return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+ case PVRSRV_ERROR_INVALID_PARAMS: return "PVRSRV_ERROR_INVALID_PARAMS";
+ case PVRSRV_ERROR_INIT_FAILURE: return "PVRSRV_ERROR_INIT_FAILURE";
+ case PVRSRV_ERROR_CANT_REGISTER_CALLBACK: return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+ case PVRSRV_ERROR_INVALID_DEVICE: return "PVRSRV_ERROR_INVALID_DEVICE";
+ case PVRSRV_ERROR_NOT_OWNER: return "PVRSRV_ERROR_NOT_OWNER";
+ case PVRSRV_ERROR_BAD_MAPPING: return "PVRSRV_ERROR_BAD_MAPPING";
+ case PVRSRV_ERROR_TIMEOUT: return "PVRSRV_ERROR_TIMEOUT";
+ case PVRSRV_ERROR_FLIP_CHAIN_EXISTS: return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+ case PVRSRV_ERROR_SCENE_INVALID: return "PVRSRV_ERROR_SCENE_INVALID";
+ case PVRSRV_ERROR_STREAM_ERROR: return "PVRSRV_ERROR_STREAM_ERROR";
+ case PVRSRV_ERROR_FAILED_DEPENDENCIES: return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+ case PVRSRV_ERROR_CMD_NOT_PROCESSED: return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+ case PVRSRV_ERROR_CMD_TOO_BIG: return "PVRSRV_ERROR_CMD_TOO_BIG";
+ case PVRSRV_ERROR_DEVICE_REGISTER_FAILED: return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+ case PVRSRV_ERROR_TOOMANYBUFFERS: return "PVRSRV_ERROR_TOOMANYBUFFERS";
+ case PVRSRV_ERROR_NOT_SUPPORTED: return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+ case PVRSRV_ERROR_PROCESSING_BLOCKED: return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+ case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE: return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+ case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE: return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+ case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS: return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+ case PVRSRV_ERROR_RETRY: return "PVRSRV_ERROR_RETRY";
+
+ case PVRSRV_ERROR_DDK_VERSION_MISMATCH: return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+ case PVRSRV_ERROR_BUILD_MISMATCH: return "PVRSRV_ERROR_BUILD_MISMATCH";
+
+ case PVRSRV_ERROR_INVALID_FLAGS: return "PVRSRV_ERROR_INVALID_FLAGS";
+ case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS: return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY: return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+ case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR: return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+ case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED: return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+ case PVRSRV_ERROR_BRIDGE_CALL_FAILED: return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+
+ case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND: return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+ case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_PCI_CALL_FAILED: return "PVRSRV_ERROR_PCI_CALL_FAILED";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM: return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC: return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+ case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR: return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES: return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_FREE_PAGES: return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_COPY_PAGES: return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+ case PVRSRV_ERROR_STILL_MAPPED: return "PVRSRV_ERROR_STILL_MAPPED";
+ case PVRSRV_ERROR_MAPPING_NOT_FOUND: return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+ case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT: return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+
+ case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK: return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+ case PVRSRV_ERROR_INVALID_SGXDEVDATA: return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+ case PVRSRV_ERROR_INVALID_DEVINFO: return "PVRSRV_ERROR_INVALID_DEVINFO";
+ case PVRSRV_ERROR_INVALID_MEMINFO: return "PVRSRV_ERROR_INVALID_MEMINFO";
+ case PVRSRV_ERROR_UNKNOWN_IOCTL: return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+ case PVRSRV_ERROR_INVALID_KERNELINFO: return "PVRSRV_ERROR_INVALID_KERNELINFO";
+ case PVRSRV_ERROR_UNKNOWN_POWER_STATE: return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+ case PVRSRV_ERROR_INVALID_HANDLE_TYPE: return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+ case PVRSRV_ERROR_INVALID_WRAP_TYPE: return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+ case PVRSRV_ERROR_INVALID_PHYS_ADDR: return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+ case PVRSRV_ERROR_INVALID_HEAPINFO: return "PVRSRV_ERROR_INVALID_HEAPINFO";
+ case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO: return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+ case PVRSRV_ERROR_INVALID_MAP_REQUEST: return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+ case PVRSRV_ERROR_INVALID_UNMAP_REQUEST: return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+
+ case PVRSRV_ERROR_EXCEEDED_HW_LIMITS: return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+ case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED: return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+ case PVRSRV_ERROR_THREAD_READ_ERROR: return "PVRSRV_ERROR_THREAD_READ_ERROR";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+ case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+ case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+ case PVRSRV_ERROR_ISR_ALREADY_INSTALLED: return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+ case PVRSRV_ERROR_ISR_NOT_INSTALLED: return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+ case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+ case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO: return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+ case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT: return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES : return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE: return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+ case PVRSRV_ERROR_INVALID_LOCK_ID: return "PVRSRV_ERROR_INVALID_LOCK_ID";
+ case PVRSRV_ERROR_RESOURCE_NOT_LOCKED: return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+ case PVRSRV_ERROR_FLIP_FAILED: return "PVRSRV_ERROR_FLIP_FAILED";
+ case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED: return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+ case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE: return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+ case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED: return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+ case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG: return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+ case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID: return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+ case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE: return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+ case PVRSRV_ERROR_PDUMP_BUFFER_FULL: return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+ case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW: return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+ case PVRSRV_ERROR_PDUMP_NOT_ACTIVE: return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+ case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+ case PVRSRV_ERROR_MUTEX_DESTROY_FAILED: return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+ case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR: return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+ case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE: return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+
+ case PVRSRV_ERROR_PROCESS_NOT_INITIALISED: return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+ case PVRSRV_ERROR_PROCESS_NOT_FOUND: return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+ case PVRSRV_ERROR_SRV_CONNECT_FAILED: return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+ case PVRSRV_ERROR_SRV_DISCONNECT_FAILED: return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+ case PVRSRV_ERROR_DEINT_PHASE_FAILED: return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+ case PVRSRV_ERROR_INIT2_PHASE_FAILED: return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+ case PVRSRV_ERROR_NO_DC_DEVICES_FOUND: return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+ case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE: return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+ case PVRSRV_ERROR_NO_DEVICEDATA_FOUND: return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+
+ case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT: return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+
+ case PVRSRV_ERROR_UNABLE_TO_INIT_TASK: return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK: return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_KILL_TASK: return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+ case PVRSRV_ERROR_FORCE_I32: return "PVRSRV_ERROR_FORCE_I32";
+
+ default:
+ return "Unknown PVRSRV error number";
+ }
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h b/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
new file mode 100644
index 0000000..4ef3939
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
@@ -0,0 +1,272 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT (500)
+
+#define DRIVERNAME_MAXLENGTH (100)
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+ PVRSRV_MEMTYPE_UNKNOWN = 0,
+ PVRSRV_MEMTYPE_DEVICE = 1,
+ PVRSRV_MEMTYPE_DEVICECLASS = 2,
+ PVRSRV_MEMTYPE_WRAPPED = 3,
+ PVRSRV_MEMTYPE_MAPPED = 4,
+}
+PVRSRV_MEMTYPE;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SIZE_T ui32AllocSize;
+
+
+ PVRSRV_MEMBLK sMemBlk;
+
+
+ IMG_PVOID pvSysBackupBuffer;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bPendingFree;
+
+
+ #if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+ #endif
+
+
+ struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
+
+ PVRSRV_MEMTYPE memType;
+
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM;
+
+
+ IMG_HANDLE hResItem;
+
+
+
+ IMG_UINT32 ui32RefCount;
+
+} PVRSRV_KERNEL_SYNC_INFO;
+
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+
+ IMG_UINT32 ui32ReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ IMG_UINT32 ui32WriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOpsPending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+typedef struct _PVRSRV_COMMAND
+{
+ IMG_SIZE_T ui32CmdSize;
+ IMG_UINT32 ui32DevIndex;
+ IMG_UINT32 CommandType;
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_SIZE_T ui32DataSize;
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvData;
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+ IMG_VOID *pvLinQueueKM;
+ IMG_VOID *pvLinQueueUM;
+ volatile IMG_SIZE_T ui32ReadOffset;
+ volatile IMG_SIZE_T ui32WriteOffset;
+ IMG_UINT32 *pui32KickerAddrKM;
+ IMG_UINT32 *pui32KickerAddrUM;
+ IMG_SIZE_T ui32QueueSize;
+
+ IMG_UINT32 ui32ProcessID;
+
+ IMG_HANDLE hMemBlock[2];
+
+ struct _PVRSRV_QUEUE_INFO_ *psNextKM;
+}PVRSRV_QUEUE_INFO;
+
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+ PVRSRV_COMMAND**,
+ IMG_UINT32,
+ IMG_UINT16,
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hExtDevice;
+ IMG_HANDLE hExtBuffer;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hServices;
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32WriteOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ else
+ {
+
+
+
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ return ui32WriteOpsPending;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32ReadOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+ else
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ return ui32ReadOpsPending;
+}
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+ PVRSRV_COMMAND *psCommand);
+
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVGetMMUContextPDDevPAddr(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *sPDDevPAddr);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelMemInfo,
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
new file mode 100644
index 0000000..61a147c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
@@ -0,0 +1,473 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#define PVRSRV_BRIDGE_SGX_GETMMUPDADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+10)
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2 PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#if defined(SUPPORT_SGX_HWPERF)
+#define PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+29)
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+#endif
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#endif
+
+
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_PHYADDR DevPAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR_TAG
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+ SGX_INTERNAL_DEVINFO sSGXInternalDevInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+ SGX_CLIENT_INFO sClientInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_CLIENT_INFO sClientInfo;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_CCB_KICK sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_TRANSFER_SGX_KICK sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_2D_SGX_KICK sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_MISC_INFO *psMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+ PVRSRV_ERROR eError;
+ SGX_BRIDGE_INFO_FOR_SRVINIT sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_BRIDGE_INIT_INFO sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+
+typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hKernSyncInfo;
+ IMG_BOOL bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_BOOL bLockOnFailure;
+ IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hSharedPBDesc;
+ IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+ IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+ IMG_HANDLE hBlockKernelMemInfoHandle;
+ IMG_HANDLE hHWBlockKernelMemInfoHandle;
+ IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hSharedPBDescKernelMemInfo;
+ IMG_HANDLE hHWPBDescKernelMemInfo;
+ IMG_HANDLE hBlockKernelMemInfo;
+ IMG_HANDLE hHWBlockKernelMemInfo;
+ IMG_UINT32 ui32TotalPBSize;
+ IMG_HANDLE *phKernelMemInfoHandles;
+ IMG_UINT32 ui32KernelMemInfoHandlesCount;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef PDUMP
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+ IMG_UINT32 ui32BufferArrayLength;
+ IMG_BOOL bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_UINT32 ui32TAKickCount;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define SGX2D_MAX_BLT_CMD_SIZ 256
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32Reg;
+ IMG_BOOL bNew;
+ IMG_UINT32 ui32New;
+ IMG_UINT32 ui32NewReset;
+ IMG_UINT32 ui32CountersReg;
+ IMG_UINT32 ui32Reg2;
+} PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Old;
+ IMG_BOOL bActive;
+ PVRSRV_SGXDEV_DIFF_INFO sDiffs;
+} PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS;
+
+
+#if defined(SUPPORT_SGX_HWPERF)
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32ArraySize;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData;
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DataCount;
+ IMG_UINT32 ui32ClockSpeed;
+ IMG_UINT32 ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
new file mode 100644
index 0000000..7a59274
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
@@ -0,0 +1,339 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if defined(SGX_FEATURE_MP)
+ #define SGX_REG_BANK_SHIFT (12)
+ #define SGX_REG_BANK_SIZE (0x4000)
+ #if defined(SGX541)
+ #define SGX_REG_BANK_BASE_INDEX (1)
+ #define SGX_REG_BANK_MASTER_INDEX (SGX_REG_BANK_BASE_INDEX + SGX_FEATURE_MP_CORE_COUNT)
+ #else
+ #define SGX_REG_BANK_BASE_INDEX (2)
+ #define SGX_REG_BANK_MASTER_INDEX (1)
+ #endif
+ #define SGX_MP_CORE_SELECT(x,i) (x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+ #define SGX_MP_MASTER_SELECT(x) (x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+ #define SGX_MP_CORE_SELECT(x,i) (x)
+#endif
+
+
+typedef struct _SGXMKIF_COMMAND_
+{
+ IMG_UINT32 ui32ServiceAddress;
+ IMG_UINT32 ui32CacheControl;
+ IMG_UINT32 ui32Data[2];
+} SGXMKIF_COMMAND;
+
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+ SGXMKIF_COMMAND asCommands[256];
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+ IMG_UINT32 ui32WriteOffset;
+ IMG_UINT32 ui32ReadOffset;
+} PVRSRV_SGX_CCB_CTL;
+
+
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+ IMG_UINT32 ui32BreakpointDisable;
+ IMG_UINT32 ui32Continue;
+#endif
+
+ volatile IMG_UINT32 ui32InitStatus;
+ volatile IMG_UINT32 ui32PowerStatus;
+ volatile IMG_UINT32 ui32CleanupStatus;
+#if defined(FIX_HW_BRN_28889)
+ volatile IMG_UINT32 ui32InvalStatus;
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+ IMG_UINT32 ui32uKernelDetectedLockups;
+ IMG_UINT32 ui32HostDetectedLockups;
+ IMG_UINT32 ui32HWRecoverySampleRate;
+#endif
+ IMG_UINT32 ui32uKernelTimerClock;
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ IMG_UINT32 ui32InterruptFlags;
+ IMG_UINT32 ui32InterruptClearFlags;
+
+
+ IMG_UINT32 ui32NumActivePowerEvents;
+
+#if defined(SUPPORT_SGX_HWPERF)
+ IMG_UINT32 ui32HWPerfFlags;
+#endif
+
+
+ IMG_UINT32 ui32TimeWraps;
+} SGXMKIF_HOST_CTL;
+
+#define SGXMKIF_CMDTA_CTRLFLAGS_READY 0x00000001
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+ IMG_UINT32 ui32CtrlFlags;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+
+ IMG_UINT32 ui32TATQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TATQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DTQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DTQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTADstSyncs[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
+
+ CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+ CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+#define SGXTQ_MAX_STATUS SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE 0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING 0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC 0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC 0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH 0x00000010
+#endif
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER 0x00000020
+
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+
+
+ IMG_UINT32 ui32SrcReadOpPendingVal;
+ IMG_DEV_VIRTADDR sSrcReadOpsCompleteDevAddr;
+
+ IMG_UINT32 ui32SrcWriteOpPendingVal;
+ IMG_DEV_VIRTADDR sSrcWriteOpsCompleteDevAddr;
+
+
+
+ IMG_UINT32 ui32DstReadOpPendingVal;
+ IMG_DEV_VIRTADDR sDstReadOpsCompleteDevAddr;
+
+ IMG_UINT32 ui32DstWriteOpPendingVal;
+ IMG_DEV_VIRTADDR sDstWriteOpsCompleteDevAddr;
+
+
+ IMG_UINT32 ui32TASyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TASyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncReadOpsCompleteDevVAddr;
+
+ IMG_UINT32 ui32NumStatusVals;
+ CTL_STATUS sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+
+ IMG_UINT32 ui32NumSrcSync;
+ PVRSRV_DEVICE_SYNC_OBJECT sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sDstSyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTASyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT s3DSyncData;
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+ IMG_DEV_VIRTADDR sAccessDevAddr;
+ IMG_UINT32 ui32NumSyncObjects;
+
+ PVRSRV_DEVICE_SYNC_OBJECT asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+#define PVRSRV_USSE_EDM_INIT_COMPLETE (1UL << 0)
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
+
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE (1UL << 0)
+
+#if defined(FIX_HW_BRN_28889)
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE (1UL << 0)1UL
+#endif
+
+#define PVRSRV_USSE_MISCINFO_READY 0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES 0x2UL
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD 0x4UL
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL 0x1UL << 31
+#endif
+#endif
+
+
+#define PVRSRV_CLEANUPCMD_RT 0x1
+#define PVRSRV_CLEANUPCMD_RC 0x2
+#define PVRSRV_CLEANUPCMD_TC 0x3
+#define PVRSRV_CLEANUPCMD_2DC 0x4
+#define PVRSRV_CLEANUPCMD_PB 0x5
+
+#define PVRSRV_POWERCMD_POWEROFF 0x1
+#define PVRSRV_POWERCMD_IDLE 0x2
+#define PVRSRV_POWERCMD_RESUME 0x3
+
+
+#if defined(SGX_FEATURE_BIF_NUM_DIRLISTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM (SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM (0)
+#endif
+
+#define SGXMKIF_CC_INVAL_BIF_PT 0x1
+#define SGXMKIF_CC_INVAL_BIF_PD 0x2
+#define SGXMKIF_CC_INVAL_BIF_SL 0x4
+#define SGXMKIF_CC_INVAL_DATA 0x8
+
+
+
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+ IMG_UINT32 ui32Sizeof_2DCMD;
+ IMG_UINT32 ui32Sizeof_2DCMD_SHARED;
+#endif
+ IMG_UINT32 ui32Sizeof_CMDTA;
+ IMG_UINT32 ui32Sizeof_CMDTA_SHARED;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD_SHARED;
+ IMG_UINT32 ui32Sizeof_3DREGISTERS;
+ IMG_UINT32 ui32Sizeof_HWPBDESC;
+ IMG_UINT32 ui32Sizeof_HWRENDERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HWRENDERDETAILS;
+ IMG_UINT32 ui32Sizeof_HWRTDATA;
+ IMG_UINT32 ui32Sizeof_HWRTDATASET;
+ IMG_UINT32 ui32Sizeof_HWTRANSFERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HOST_CTL;
+ IMG_UINT32 ui32Sizeof_COMMAND;
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+typedef struct _PVRSRV_SGX_MISCINFO_MEMREAD
+{
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+} PVRSRV_SGX_MISCINFO_MEMREAD;
+#endif
+
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+ IMG_UINT32 ui32MiscInfoFlags;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVRSRV_SGX_MISCINFO_MEMREAD sSGXMemReadData;
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif
+
+#define SGXMKIF_HWPERF_CB_SIZE 0x100
+
+#if defined(SUPPORT_SGX_HWPERF)
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32TimeWraps;
+ IMG_UINT32 ui32Time;
+ IMG_UINT32 ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+ IMG_UINT32 ui32Woff;
+ IMG_UINT32 ui32Roff;
+ IMG_UINT32 ui32OrdinalGRAPHICS;
+ IMG_UINT32 ui32OrdinalMK_EXECUTION;
+ SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
new file mode 100644
index 0000000..2e85b61
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
@@ -0,0 +1,288 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA 24
+#define SGX_MAX_INIT_MEM_HANDLES 16
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+ SGXMKIF_CMD_TA = 0,
+ SGXMKIF_CMD_TRANSFER = 1,
+ SGXMKIF_CMD_2D = 2,
+ SGXMKIF_CMD_POWER = 3,
+ SGXMKIF_CMD_CLEANUP = 4,
+ SGXMKIF_CMD_GETMISCINFO = 5,
+ SGXMKIF_CMD_PROCESS_QUEUES = 6,
+ SGXMKIF_CMD_MAX = 7,
+
+ SGXMKIF_CMD_FORCE_I32 = -1,
+
+} SGXMKIF_CMD_TYPE;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_
+{
+ IMG_HANDLE hKernelCCBMemInfo;
+ IMG_HANDLE hKernelCCBCtlMemInfo;
+ IMG_HANDLE hKernelCCBEventKickerMemInfo;
+ IMG_HANDLE hKernelSGXHostCtlMemInfo;
+ IMG_HANDLE hKernelSGXTA3DCtlMemInfo;
+ IMG_HANDLE hKernelSGXMiscMemInfo;
+
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+ SGX_INIT_SCRIPTS sScripts;
+
+ IMG_UINT32 ui32ClientBuildOptions;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ IMG_HANDLE hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ IMG_HANDLE hKernelHWPerfCBMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ IMG_HANDLE hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ IMG_HANDLE hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ IMG_HANDLE hKernelTmpDPMStateMemInfo;
+#endif
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+#endif
+
+ IMG_UINT32 ui32CacheControl;
+
+ IMG_UINT32 asInitDevData[SGX_MAX_DEV_DATA];
+ IMG_HANDLE asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+ PSGXMKIF_HWDEVICE_SYNC_LIST psHWDeviceSyncList;
+
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+ PVRSRV_CLIENT_MEM_INFO *psHWDeviceSyncListClientMemInfo;
+ PVRSRV_CLIENT_MEM_INFO *psAccessResourceClientMemInfo;
+
+ volatile IMG_UINT32 *pui32Lock;
+
+ struct _SGX_DEVICE_SYNC_LIST_ *psNext;
+
+
+ IMG_UINT32 ui32NumSyncObjects;
+ IMG_HANDLE ahSyncHandles[1];
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+ CTL_STATUS sCtlStatus;
+ IMG_HANDLE hKernelMemInfo;
+
+ IMG_UINT32 ui32LastStatusUpdateDumpVal;
+} SGX_INTERNEL_STATUS_UPDATE;
+
+
+typedef struct _SGX_CCB_KICK_
+{
+ SGXMKIF_COMMAND sCommand;
+ IMG_HANDLE hCCBKernelMemInfo;
+
+ IMG_UINT32 ui32NumDstSyncObjects;
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+
+
+ IMG_HANDLE *pahDstSyncHandles;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ SGX_INTERNEL_STATUS_UPDATE asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+ SGX_INTERNEL_STATUS_UPDATE as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+ IMG_HANDLE ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ IMG_HANDLE ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+ IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ IMG_BOOL bTerminateOrAbort;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ IMG_BOOL bKickRender;
+#endif
+
+
+ IMG_UINT32 ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ IMG_HANDLE ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+ IMG_BOOL bTADependency;
+ IMG_HANDLE hTA3DSyncInfo;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+ IMG_UINT32 ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK;
+
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX 15
+
+
+typedef struct _SGX_CLIENT_INFO_
+{
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvProcess;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+ IMG_UINT32 asDevData[SGX_MAX_DEV_DATA];
+
+} SGX_CLIENT_INFO;
+
+typedef struct _SGX_INTERNAL_DEVINFO_
+{
+ IMG_UINT32 ui32Flags;
+ IMG_HANDLE hHostCtlKernelMemInfoHandle;
+ IMG_BOOL bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32NumDstSync;
+ IMG_HANDLE ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32Flags;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+
+ IMG_HANDLE display;
+ IMG_UINT32 headline;
+ IMG_UINT32 footline;
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ IMG_HANDLE hDstSyncInfo;
+
+
+ IMG_HANDLE hTASyncInfo;
+
+
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif
+#endif
+
+#define PVRSRV_SGX_DIFF_NUM_COUNTERS 9
+
+typedef struct _PVRSRV_SGXDEV_DIFF_INFO_
+{
+ IMG_UINT32 aui32Counters[PVRSRV_SGX_DIFF_NUM_COUNTERS];
+ IMG_UINT32 ui32Time[3];
+ IMG_UINT32 ui32Marker[2];
+} PVRSRV_SGXDEV_DIFF_INFO, *PPVRSRV_SGXDEV_DIFF_INFO;
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
new file mode 100644
index 0000000..efabffe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
@@ -0,0 +1,3447 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "sysconfig.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+#include "srvkm.h"
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+ return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+ return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ psEnumDeviceOUT->eError =
+ PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+ psEnumDeviceOUT->asDeviceIdentifier);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+ PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+ psAcquireDevInfoIN->eDeviceType,
+ &hDevCookieInt);
+ if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAcquireDevInfoOUT->hDevCookie,
+ hDevCookieInt,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+ IMG_BOOL bCreated;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1);
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psCreateDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+ psPerProc,
+ &hDevMemContextInt,
+ &psCreateDevMemContextOUT->ui32ClientHeapCount,
+ &psCreateDevMemContextOUT->sHeapInfo[0],
+ &bCreated,
+ pbSharedDeviceMemHeap);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if(bCreated)
+ {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else
+ {
+
+ if(bCreated)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDevMemContextOUT->hDevMemContext);
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+ }
+#endif
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_BOOL bDestroyed;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psDestroyDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(bDestroyed)
+ {
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetDevMemHeapInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetDevMemHeapInfoIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+ hDevMemContextInt,
+ &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+ &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+ pbSharedDeviceMemHeap);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else
+ {
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemHeapInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2);
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psAllocDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+ psAllocDeviceMemIN->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVAllocDeviceMemKM(hDevCookieInt,
+ psPerProc,
+ hDevMemHeapInt,
+ psAllocDeviceMemIN->ui32Attribs,
+ psAllocDeviceMemIN->ui32Size,
+ psAllocDeviceMemIN->ui32Alignment,
+ &psMemInfo,
+ "" );
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+ psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+ psAllocDeviceMemOUT->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+ psAllocDeviceMemOUT->psKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+
+ psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psAllocDeviceMemOUT->sClientSyncInfo;
+
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#endif
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvKernelMemInfo;
+
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psFreeDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EXPORT_DEVICEMEM);
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psExportDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo,
+ psExportDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+ return 0;
+ }
+
+
+ psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo = IMG_NULL;
+ IMG_HANDLE hDstDevMemHeap = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEV_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2);
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_VOID**)&psSrcKernelMemInfo,
+ psMapDevMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDstDevMemHeap,
+ psMapDevMemIN->hDstDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+ psSrcKernelMemInfo,
+ hDstDevMemHeap,
+ &psDstKernelMemInfo);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientMemInfo));
+ OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+ psDstKernelMemInfo->pvLinAddrKM;
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+ psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+ psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+ psMapDevMemOUT->sDstClientMemInfo.ui32AllocSize = psDstKernelMemInfo->ui32AllocSize;
+ psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+ psDstKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+ psMapDevMemOUT->psDstKernelSyncInfo = IMG_NULL;
+
+
+ if(psDstKernelMemInfo->psKernelSyncInfo)
+ {
+ psMapDevMemOUT->psDstKernelSyncInfo = psDstKernelMemInfo->psKernelSyncInfo;
+
+ psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+ psDstKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelMemInfo,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hOSMapInfo;
+ IMG_HANDLE hDeviceClassBufferInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2);
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase, &hDeviceClassBufferInt,
+ &eHandleType,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psMapDevClassMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+ case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapDevClassMemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVMapDeviceClassMemoryKM(psPerProc,
+ hDevMemContextInt,
+ hDeviceClassBufferInt,
+ &psMemInfo,
+ &hOSMapInfo);
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientMemInfo));
+ OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psMapDevClassMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+ psMapDevClassMemOUT->sClientMemInfo.hOSMapInfo = hOSMapInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+ psMapDevClassMemOUT->psKernelSyncInfo = IMG_NULL;
+
+
+ if(psMemInfo->psKernelSyncInfo)
+ {
+ psMapDevClassMemOUT->psKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+
+ psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_UINT32 ui32PageTableSize = 0;
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2);
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psWrapExtMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psWrapExtMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+ * sizeof(IMG_SYS_PHYADDR);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID **)&psSysPAddr, 0,
+ "Page Table"));
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSysPAddr,
+ psWrapExtMemIN->psSysPAddr,
+ ui32PageTableSize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+
+ return -EFAULT;
+ }
+ }
+
+ psWrapExtMemOUT->eError =
+ PVRSRVWrapExtMemoryKM(hDevCookieInt,
+ psPerProc,
+ hDevMemContextInt,
+ psWrapExtMemIN->ui32ByteSize,
+ psWrapExtMemIN->ui32PageOffset,
+ psWrapExtMemIN->bPhysContig,
+ psSysPAddr,
+ psWrapExtMemIN->pvLinAddr,
+ psWrapExtMemIN->ui32Flags,
+ &psMemInfo);
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID *)psSysPAddr, 0);
+
+ }
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psWrapExtMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psGetFreeDeviceMemOUT->eError =
+ PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+ &psGetFreeDeviceMemOUT->ui32Total,
+ &psGetFreeDeviceMemOUT->ui32Free,
+ &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+ return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapOSMemHandleToMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->ui32MMapOffset,
+ &psMMapDataOUT->ui32ByteOffset,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapReleaseMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->bMUnmap,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+ psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+ psPDumpCommentIN->ui32Flags);
+ return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError =
+ PDumpRegWithFlagsKM(psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpRegDumpIN->sHWReg.ui32RegVal,
+ psPDumpRegDumpIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError =
+ PDumpRegPolWithFlagsKM(psPDumpRegPolIN->sHWReg.ui32RegAddr,
+ psPDumpRegPolIN->sHWReg.ui32RegVal,
+ psPDumpRegPolIN->ui32Mask,
+ psPDumpRegPolIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemPolIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+ psPDumpMemPolIN->ui32Offset,
+ psPDumpMemPolIN->ui32Value,
+ psPDumpMemPolIN->ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ psPDumpMemPolIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemDumpIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpMemDumpIN->pvAltLinAddr,
+ psPDumpMemDumpIN->pvLinAddr,
+ pvMemInfo,
+ psPDumpMemDumpIN->ui32Offset,
+ psPDumpMemDumpIN->ui32Bytes,
+ psPDumpMemDumpIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psRetOUT->eError =
+ PDumpBitmapKM(&psPDumpBitmapIN->szFileName[0],
+ psPDumpBitmapIN->ui32FileOffset,
+ psPDumpBitmapIN->ui32Width,
+ psPDumpBitmapIN->ui32Height,
+ psPDumpBitmapIN->ui32StrideInBytes,
+ psPDumpBitmapIN->sDevBaseAddr,
+ psPDumpBitmapIN->ui32Size,
+ psPDumpBitmapIN->ePixelFormat,
+ psPDumpBitmapIN->eMemFormat,
+ psPDumpBitmapIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError =
+ PDumpReadRegKM(&psPDumpReadRegIN->szFileName[0],
+ psPDumpReadRegIN->ui32FileOffset,
+ psPDumpReadRegIN->ui32Address,
+ psPDumpReadRegIN->ui32Size,
+ psPDumpReadRegIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32PDumpFlags;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ ui32PDumpFlags = 0;
+ if(psPDumpDriverInfoIN->bContinuous)
+ {
+ ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+ }
+ psRetOUT->eError =
+ PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+ ui32PDumpFlags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+ IMG_VOID *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncDumpIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpSyncDumpIN->pvAltLinAddr,
+ IMG_NULL,
+ ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ psPDumpSyncDumpIN->ui32Offset,
+ ui32Bytes,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Offset;
+ IMG_VOID *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncPolIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psPDumpSyncPolIN->bIsRead)
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ }
+ else
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ ui32Offset,
+ psPDumpSyncPolIN->ui32Value,
+ psPDumpSyncPolIN->ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpPDRegBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG *psPDumpPDRegDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PDREG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PDumpPDReg(psPDumpPDRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpPDRegDumpIN->sHWReg.ui32RegVal,
+ PDUMP_PD_UNIQUETAG);
+
+ psRetOUT->eError = PVRSRV_OK;
+ return 0;
+}
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PDumpCycleCountRegRead(psPDumpCycleCountRegReadIN->ui32RegOffset,
+ psPDumpCycleCountRegReadIN->bLastFrame);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+ psPDumpPDDevPAddrIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+ psPDumpPDDevPAddrIN->ui32Offset,
+ psPDumpPDDevPAddrIN->sPDDevPAddr,
+ MAKEUNIQUETAG(pvMemInfo),
+ PDUMP_PD_UNIQUETAG);
+ return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStartInitPhaseKM();
+
+ return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStopInitPhaseKM();
+
+ return 0;
+}
+
+#endif
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+ &psGetMiscInfoIN->sMiscInfo,
+ sizeof(PVRSRV_MISC_INFO));
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0))
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0))
+ {
+
+ ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+ "Output string buffer"));
+
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = IMG_NULL;
+
+
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+ if(eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+ return -EFAULT;
+ }
+ }
+ else
+ {
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+ }
+
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+ {
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+ psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+ psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+ psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+ psConnectServicesOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+ PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+ psEnumDispClassOUT->eError =
+ PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+ &psEnumDispClassOUT->ui32NumDevices,
+ &psEnumDispClassOUT->ui32DevID[0]);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1);
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenDispClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVOpenDCDeviceKM(psPerProc,
+ psOpenDispClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hDispClassInfoInt);
+
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenDispClassDeviceOUT->hDeviceKM,
+ hDispClassInfoInt,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassFormatsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+ &psEnumDispClassFormatsOUT->ui32Count,
+ psEnumDispClassFormatsOUT->asFormat);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassDimsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+ &psEnumDispClassDimsIN->sFormat,
+ &psEnumDispClassDimsOUT->ui32Count,
+ psEnumDispClassDimsOUT->asDim);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hBufferInt;
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1);
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psGetDispClassSysBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+ &hBufferInt);
+
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetDispClassSysBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassSysBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVGetDCInfoKM(pvDispClassInfo,
+ &psGetDispClassInfoOUT->sDisplayInfo);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_HANDLE hSwapChainInt;
+ IMG_UINT32 ui32SwapChainID;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1);
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psCreateDispClassSwapChainIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+ psCreateDispClassSwapChainIN->ui32Flags,
+ &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+ &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+ psCreateDispClassSwapChainIN->ui32BufferCount,
+ psCreateDispClassSwapChainIN->ui32OEMFlags,
+ &hSwapChainInt,
+ &ui32SwapChainID);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psCreateDispClassSwapChainOUT->hSwapChain,
+ hSwapChainInt,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDispClassSwapChainIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassDstRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassDstRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassDstRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassSrcRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassSrcRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassSrcRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassBuffersIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psGetDispClassBuffersIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVGetDCBuffersKM(pvDispClassInfo,
+ pvSwapChain,
+ &psGetDispClassBuffersOUT->ui32BufferCount,
+ psGetDispClassBuffersOUT->ahBuffer);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+ {
+ IMG_HANDLE hBufferExt;
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hBufferExt,
+ psGetDispClassBuffersOUT->ahBuffer[i],
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassBuffersIN->hSwapChain);
+
+ psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChainBuf;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChainBuf,
+ psSwapDispClassBufferIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+ pvSwapChainBuf,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->hPrivateTag,
+ psSwapDispClassBufferIN->ui32ClipRectCount,
+ psSwapDispClassBufferIN->sClipRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassSystemIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassSystemIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassSystemIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ psRetOUT->eError =
+ PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+ pvSwapChain);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1);
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenBufferClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVOpenBCDeviceKM(psPerProc,
+ psOpenBufferClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hBufClassInfo);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenBufferClassDeviceOUT->hDeviceKM,
+ hBufClassInfo,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVGetBCInfoKM(pvBufClassInfo,
+ &psGetBufferClassInfoOUT->sBufferInfo);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+ IMG_HANDLE hBufferInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVGetBCBufferKM(pvBufClassInfo,
+ psGetBufferClassBufferIN->ui32BufferIndex,
+ &hBufferInt);
+
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetBufferClassBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetBufferClassBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetBCBufferIdFromTagBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo = IMG_NULL;
+ IMG_HANDLE pidx = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVGetBCBufferIdFromTagKM(pvBufClassInfo,
+ psGetBufferClassBufferIN->ui32BufferIndex,
+ &pidx);
+
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->hBuffer = pidx;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1);
+
+ psAllocSharedSysMemOUT->eError =
+ PVRSRVAllocSharedSysMemoryKM(psPerProc,
+ psAllocSharedSysMemIN->ui32Flags,
+ psAllocSharedSysMemIN->ui32Size,
+ &psKernelMemInfo);
+ if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ IMG_HANDLE hParent;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2);
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+ &eHandleType,
+ psMapMemInfoMemIN->hKernelMemInfo);
+ if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ switch (eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapMemInfoMemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVGetParentHandle(psPerProc->psHandleBase,
+ &hParent,
+ psMapMemInfoMemIN->hKernelMemInfo,
+ eHandleType);
+ if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ if (hParent == IMG_NULL)
+ {
+ hParent = psMapMemInfoMemIN->hKernelMemInfo;
+ }
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+ psKernelMemInfo->sDevVAddr;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ hParent);
+
+ if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psMapMemInfoMemOUT->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+ psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+
+static IMG_INT
+MMU_GetPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrIN,
+ PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevMemContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR);
+
+ psGetMmuPDDevPAddrOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetMmuPDDevPAddrIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psGetMmuPDDevPAddrOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetMmuPDDevPAddrOUT->sPDDevPAddr =
+ BM_GetDeviceNode(hDevMemContextInt)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hDevMemContextInt));
+ if(psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr)
+ {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+ }
+ else
+ {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_GENERIC;
+ }
+ return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu (%s) mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID));
+#endif
+ return -ENOTTY;
+}
+
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName)
+{
+ static IMG_UINT32 ui32PrevIndex = ~0UL;
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+ PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+
+ if(g_BridgeDispatchTable[ui32Index].pfFunction)
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+ __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%lu)",
+ __FUNCTION__, pszIOCName, ui32Index));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+ __FUNCTION__));
+ }
+
+
+ if((ui32PrevIndex != ~0UL) &&
+ ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+ (ui32Index <= ui32PrevIndex)))
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %lu (%s) and %lu (%s)",
+ __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+ ui32Index, pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+ __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+ __FUNCTION__));
+ }
+
+ g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+ g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+ g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+ g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+ ui32PrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+#if defined (__linux__)
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+ psPerProc->bInitProcess = IMG_TRUE;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psPerProc->bInitProcess = IMG_FALSE;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+ psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+ PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL,
+ (((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful)))
+ ? IMG_TRUE : IMG_FALSE);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectWaitIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectWait(hOSEventKM);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+ PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1);
+
+ psEventObjectOpenOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectOpenIN->sEventObject.hOSEventKM,
+ psEventObjectOpenIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEventObjectOpenOUT->eError = OSEventObjectOpen(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ psEventObjectOpenOUT->hOSEvent,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectCloseIN->sEventObject.hOSEventKM,
+ psEventObjectCloseIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectCloseIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectClose(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+ return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+ IMG_UINT32 ui32ReadOpsPendingSnapShot;
+ IMG_UINT32 ui32WriteOpsPendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if (!pvParam)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+ psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+ && (psModSyncOpInfo->ui32ReadOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ {
+ goto OpFlushedComplete;
+ }
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush"));
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush timed out"));
+
+ return PVRSRV_ERROR_TIMEOUT;
+
+OpFlushedComplete:
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+ }
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+
+
+
+ PVRSRVCommandCompleteCallbacks();
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hKernelSyncInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hKernelSyncInfo,
+ psModifySyncOpsIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ psKernelSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hKernelSyncInfo;
+
+ if(psKernelSyncInfo->hResItem != IMG_NULL)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+ return 0;
+ }
+
+ ASSIGN_AND_EXIT_ON_ERROR(psModifySyncOpsOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MODIFY_SYNC_OP_INFO),
+ (IMG_VOID **)&psModSyncOpInfo, 0,
+ "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+
+ psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+ psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+
+
+ psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+ psKernelSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+ psModSyncOpInfo,
+ 0,
+ ModifyCompleteSyncOpsCallBack);
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_RETURN *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelSyncInfo,
+ psModifySyncOpsIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psKernelSyncInfo->hResItem == IMG_NULL)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+
+
+
+
+
+
+
+
+
+ eError = ResManFreeResByPtr(psKernelSyncInfo->hResItem);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: ResManFreeResByPtr failed"));
+ return 0;
+ }
+
+ psKernelSyncInfo->hResItem = IMG_NULL;
+
+ return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES, PVRSRVEnumerateDevicesBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES, PVRSRVDisconnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM , DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PDREG, PDumpPDRegBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
+#endif
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG, PVRSRVGetBCBufferIdFromTagBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR, MMU_GetPDDevPAddrBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT, PVRSRVInitSrvConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, PVRSRVInitSrvDisconnectBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT, PVRSRVEventObjectWaitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN, PVRSRVEventObjectOpenBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, PVRSRVEventObjectCloseBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+
+#if defined (SUPPORT_SGX)
+ SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+ SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+ SetMSVDXDispatchTableEntry();
+#endif
+
+
+
+
+ for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+ {
+ if(!g_BridgeDispatchTable[i].pfFunction)
+ {
+ g_BridgeDispatchTable[i].pfFunction = DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+ g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+ g_BridgeDispatchTable[i].ui32CallCount = 0;
+ g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+ g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+
+ IMG_VOID * psBridgeIn;
+ IMG_VOID * psBridgeOut;
+ BridgeWrapperFunction pfBridgeHandler;
+ IMG_UINT32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+ IMG_INT err = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+ __FUNCTION__,
+ g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+ if(!psPerProc->bInitProcess)
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed. Driver unusable.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ else
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ else
+ {
+
+ switch(ui32BridgeID)
+ {
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ }
+ }
+
+
+
+#if defined(__linux__)
+ {
+
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+ psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+ if(psBridgePackageKM->ui32InBufferSize > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgeIn,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+ }
+ }
+#else
+ psBridgeIn = psBridgePackageKM->pvParamIn;
+ psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+ if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+ __FUNCTION__, ui32BridgeID));
+ goto return_fault;
+ }
+ pfBridgeHandler =
+ (BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
+ err = pfBridgeHandler(ui32BridgeID,
+ psBridgeIn,
+ psBridgeOut,
+ psPerProc);
+ if(err < 0)
+ {
+ goto return_fault;
+ }
+
+
+#if defined(__linux__)
+
+ if(CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgePackageKM->pvParamOut,
+ psBridgeOut,
+ psBridgePackageKM->ui32OutBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+#endif
+
+ err = 0;
+return_fault:
+ ReleaseHandleBatch(psPerProc);
+ return err;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
new file mode 100644
index 0000000..9d03a24
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
@@ -0,0 +1,227 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X) (X - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res) \
+ do \
+ { \
+ (error) = (src); \
+ if ((error) != PVRSRV_OK) \
+ { \
+ return (res); \
+ } \
+ } while (error != PVRSRV_OK)
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src) \
+ ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+ eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+ if (eError == PVRSRV_OK)
+ {
+ psPerProc->bHandlesBatched = IMG_TRUE;
+ }
+
+ return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_ASSERT(psPerProc->bHandlesBatched);
+
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->bHandlesBatched)
+ {
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+ }
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+ BridgeWrapperFunction pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ const IMG_CHAR *pszIOCName;
+ const IMG_CHAR *pszFunctionName;
+ IMG_UINT32 ui32CallCount;
+ IMG_UINT32 ui32CopyFromUserTotalBytes;
+ IMG_UINT32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+ #if defined(SUPPORT_VGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_VGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_MSVDX_CMD
+ #endif
+#else
+ #if defined(SUPPORT_SGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_SGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+ #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName);
+
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+ IMG_UINT32 ui32IOCTLCount;
+ IMG_UINT32 ui32TotalCopyFromUserBytes;
+ IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
new file mode 100644
index 0000000..b82231a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
@@ -0,0 +1,81 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+{
+ IMG_HANDLE hMHandleInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ PVRSRV_ERROR eError;
+
+
+ eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+ &eHandleType,
+ hMHandle);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ {
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SOC_TIMER:
+ {
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+ }
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+#endif
+ default:
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
new file mode 100644
index 0000000..b5c2d15
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
new file mode 100644
index 0000000..de4e697
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
@@ -0,0 +1,2510 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+
+#if defined(SUPPORT_MSVDX)
+ #include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+ psGetClientInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psGetClientInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetClientInfoOUT->eError =
+ SGXGetClientInfoKM(hDevCookieInt,
+ &psGetClientInfoOUT->sClientInfo);
+ return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psReleaseClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+ psDevInfo->ui32ClientRefCount--;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXGetInternalDevInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXGetInternalDevInfoOUT->eError =
+ SGXGetInternalDevInfoKM(hDevCookieInt,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+ IMG_INT ret = 0;
+ IMG_UINT32 ui32NumDstSyncs;
+ IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psDoKickIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTASyncInfo,
+ psDoKickIN->sCCBKick.hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.h3DSyncInfo,
+ psDoKickIN->sCCBKick.h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#else
+
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+ if(ui32NumDstSyncs > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+ " Invalid pasDstSyncHandles pointer", __FUNCTION__));
+ return -EFAULT;
+ }
+
+ psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelSyncInfoHandles,
+ 0,
+ "Array of Synchronization Info Handles");
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelSyncInfoHandles,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+
+ psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+
+ for( i = 0; i < ui32NumDstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXDoKickKM(hDevCookieInt,
+ &psDoKickIN->sCCBKick);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+ if(phKernelSyncInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelSyncInfoHandles,
+ 0);
+
+ }
+ return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psScheduleProcQIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+ return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_TRANSFER_SGX_KICK *psKick;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psKick = &psSubmitTransferIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmitTransferIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahDstSyncInfo[i],
+ psKick->ahDstSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_2D_SGX_KICK *psKick;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmit2DIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psKick = &psSubmit2DIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hDstSyncInfo,
+ psKick->hDstSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXSubmit2DKM(hDevCookieInt, psKick);
+
+ return 0;
+}
+#endif
+#endif
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt = 0;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ SGX_MISC_INFO sMiscInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXGetMiscInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+
+ if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+ {
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ psDeviceNode = hDevCookieInt;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+ if (psDeviceNode == IMG_NULL)
+ {
+ return -EFAULT;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+ psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ &sMiscInfo,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+
+#ifdef SUPPORT_SGX_HWPERF
+ if (sMiscInfo.eRequest == SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB)
+ {
+
+ IMG_VOID * pAllocated;
+ IMG_HANDLE hAllocatedHandle;
+ IMG_VOID * psTmpUserData;
+ IMG_UINT32 allocatedSize;
+
+ allocatedSize = (IMG_UINT32)(sMiscInfo.uData.sRetrieveCB.ui32ArraySize * sizeof(PVRSRV_SGX_HWPERF_CBDATA));
+
+ ASSIGN_AND_EXIT_ON_ERROR(psRetOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ &pAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+
+ psTmpUserData = sMiscInfo.uData.sRetrieveCB.psHWPerfData;
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData = pAllocated;
+
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, 0);
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ pAllocated,
+ hAllocatedHandle);
+
+ return 0;
+ }
+
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psTmpUserData,
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData,
+ allocatedSize);
+
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData = psTmpUserData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ pAllocated,
+ hAllocatedHandle);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ }
+ else
+#endif
+ {
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ &sMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+#if defined(SUPPORT_SGX_HWPERF)
+static IMG_INT
+SGXReadDiffCountersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS);
+
+ psSGXReadDiffCountersOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadDiffCountersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadDiffCountersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXReadDiffCountersOUT->eError = SGXReadDiffCountersKM(hDevCookieInt,
+ psSGXReadDiffCountersIN->ui32Reg,
+ &psSGXReadDiffCountersOUT->ui32Old,
+ psSGXReadDiffCountersIN->bNew,
+ psSGXReadDiffCountersIN->ui32New,
+ psSGXReadDiffCountersIN->ui32NewReset,
+ psSGXReadDiffCountersIN->ui32CountersReg,
+ psSGXReadDiffCountersIN->ui32Reg2,
+ &psSGXReadDiffCountersOUT->bActive,
+ &psSGXReadDiffCountersOUT->sDiffs);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psAllocated;
+ IMG_HANDLE hAllocatedHandle;
+ IMG_UINT32 ui32AllocatedSize;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+ psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+ sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+ ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ (IMG_VOID **)&psAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+ psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+ psSGXReadHWPerfCBIN->ui32ArraySize,
+ psAllocated,
+ &psSGXReadHWPerfCBOUT->ui32DataCount,
+ &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+ &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+ if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+ {
+ psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXReadHWPerfCBIN->psHWPerfCBData,
+ psAllocated,
+ ui32AllocatedSize);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ psAllocated,
+ hAllocatedHandle);
+
+
+ return 0;
+}
+#endif
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bDissociateFailed = IMG_FALSE;
+ IMG_BOOL bLookupFailed = IMG_FALSE;
+ IMG_BOOL bReleaseFailed = IMG_FALSE;
+ IMG_HANDLE hDummy;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXDevInitPart2IN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ {
+ continue;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ hHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+ }
+
+ if (bLookupFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+ #if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (*phHandle == IMG_NULL)
+ continue;
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ phHandle,
+ *phHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+ }
+
+ if (bReleaseFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ continue;
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+ }
+
+
+
+
+ if(bDissociateFailed)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ continue;
+
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ DevInitSGXPart2KM(psPerProc,
+ hDevCookieInt,
+ &psSGXDevInitPart2IN->sInitInfo);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWRenderContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWRenderContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWRenderContextInt =
+ SGXRegisterHWRenderContextKM(hDevCookieInt,
+ &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr,
+ psPerProc);
+
+ if (hHWRenderContextInt == IMG_NULL)
+ {
+ psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWRenderContextOUT->hHWRenderContext,
+ hHWRenderContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWRenderContextInt,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWTransferContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWTransferContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWTransferContextInt =
+ SGXRegisterHWTransferContextKM(hDevCookieInt,
+ &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr,
+ psPerProc);
+
+ if (hHWTransferContextInt == IMG_NULL)
+ {
+ psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWTransferContextOUT->hHWTransferContext,
+ hHWTransferContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWTransferContextInt,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHW2DContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHW2DContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHW2DContextInt =
+ SGXRegisterHW2DContextKM(hDevCookieInt,
+ &psSGXRegHW2DContextIN->sHW2DContextDevVAddr,
+ psPerProc);
+
+ if (hHW2DContextInt == IMG_NULL)
+ {
+ psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHW2DContextOUT->hHW2DContext,
+ hHW2DContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHW2DContextInt,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFlushHWRenderTargetIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvSyncInfo;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ ps2DQueryBltsCompleteIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ ps2DQueryBltsCompleteIN->hKernSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ psRetOUT->eError =
+ SGX2DQueryBlitsCompleteKM(psDevInfo,
+ (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+ ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+ IMG_UINT32 i;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+ psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ psSGXFindSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFindSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ psSGXFindSharedPBDescOUT->eError =
+ SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSGXFindSharedPBDescIN->bLockOnFailure,
+ psSGXFindSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ &psSharedPBDescKernelMemInfo,
+ &psHWPBDescKernelMemInfo,
+ &psBlockKernelMemInfo,
+ &psHWBlockKernelMemInfo,
+ &ppsSharedPBDescSubKernelMemInfos,
+ &ui32SharedPBDescSubKernelMemInfosCount);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+
+ if(hSharedPBDesc == IMG_NULL)
+ {
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+ psSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+ psHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+ psBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+ psHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+ psSGXFindSharedPBDescOUT;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+ ppsSharedPBDescSubKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+ }
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+ if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL);
+ }
+
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ if(hSharedPBDesc != IMG_NULL)
+ {
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+ }
+ }
+ else
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hSharedPBDesc;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hSharedPBDesc,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ IMG_UINT32 ui32KernelMemInfoHandlesCount =
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+ IMG_INT ret = 0;
+ IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+ psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ PVR_ASSERT(ui32KernelMemInfoHandlesCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXAddSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psSharedPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+ " Invalid phKernelMemInfos pointer", __FUNCTION__));
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelMemInfoHandles,
+ 0,
+ "Array of Handles");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelMemInfoHandles,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+ != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID **)&ppsKernelMemInfos,
+ 0,
+ "Array of pointers to Kernel Memory Info");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&ppsKernelMemInfos[i],
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+ }
+
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSharedPBDescKernelMemInfo,
+ psHWPBDescKernelMemInfo,
+ psBlockKernelMemInfo,
+ psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ ppsKernelMemInfos,
+ ui32KernelMemInfoHandlesCount);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+ if(phKernelMemInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelMemInfoHandles,
+ 0);
+ }
+ if(ppsKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID *)ppsKernelMemInfos,
+ 0);
+ }
+
+ if(ret == 0 && eError == PVRSRV_OK)
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+ }
+
+ psSGXAddSharedPBDescOUT->eError = eError;
+
+ return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXInfoForSrvinitIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ SGXGetInfoForSrvinitKM(hDevCookieInt,
+ &psSGXInfoForSrvinitOUT->sInitInfo);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ PVRSRV_HEAP_INFO *psHeapInfo;
+
+ psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+ if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+ if (psHeapInfo->hDevMemHeap != IMG_NULL)
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+ }
+ }
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray,
+ IMG_UINT32 ui32BufferArrayLength,
+ IMG_BOOL bDumpPolls)
+{
+ IMG_UINT32 i;
+
+ for (i=0; i<ui32BufferArrayLength; i++)
+ {
+ PSGX_KICKTA_DUMP_BUFFER psBuffer;
+ PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM;
+ IMG_CHAR * pszName;
+ IMG_HANDLE hUniqueTag;
+ IMG_UINT32 ui32Offset;
+
+ psBuffer = &psBufferArray[i];
+ pszName = psBuffer->pszName;
+ if (!pszName)
+ {
+ pszName = "Nameless buffer";
+ }
+
+ hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+ #if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+ ui32Offset = psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+ #else
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ #endif
+
+ if (psBuffer->ui32Start <= psBuffer->ui32End)
+ {
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32SpaceUsed,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+
+ PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32End - psBuffer->ui32Start,
+ 0,
+ hUniqueTag);
+ }
+ else
+ {
+
+
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ 0,
+ hUniqueTag);
+
+ if (bDumpPolls)
+ {
+ PDUMPMEMPOL(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ psBuffer->ui32End,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ 0,
+ psBuffer->ui32End,
+ 0,
+ hUniqueTag);
+ }
+ }
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 i;
+ SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+ IMG_UINT32 ui32BufferArrayLength =
+ psPDumpBufferArrayIN->ui32BufferArrayLength;
+ IMG_UINT32 ui32BufferArraySize =
+ ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+ PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32BufferArraySize,
+ (IMG_PVOID *)&psKickTADumpBuffer, 0,
+ "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+ {
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psKickTADumpBuffer,
+ psPDumpBufferArrayIN->psBufferArray,
+ ui32BufferArraySize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+ return -EFAULT;
+ }
+
+ for(i = 0; i < ui32BufferArrayLength; i++)
+ {
+ IMG_VOID *pvMemInfo;
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+ }
+
+ if(eError == PVRSRV_OK)
+ {
+ DumpBufferArray(psPerProc,
+ psKickTADumpBuffer,
+ ui32BufferArrayLength,
+ psPDumpBufferArrayIN->bDumpPolls);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+
+ return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL;
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDump3DSignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDump3DSignatureRegisters(psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+ psPDump3DSignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpCounterRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpCounterRegisters(psPDumpCounterRegistersIN->ui32DumpFrameNum,
+ psPDumpCounterRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL;
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDumpTASignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpTASignatureRegisters(psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+ psPDumpTASignatureRegistersIN->ui32TAKickCount,
+ psPDumpTASignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDumpHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PDumpHWPerfCBKM(&psPDumpHWPerfCBIN->szFileName[0],
+ psPDumpHWPerfCBIN->ui32FileOffset,
+ psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+ psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+ psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+ return 0;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return 0;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return -EFAULT;
+#endif
+}
+
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW);
+
+#if defined(TRANSFER_QUEUE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT , SGXGetInfoForSrvinitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+
+#if defined(SUPPORT_SGX_HWPERF)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS, SGXReadDiffCountersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+#endif
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW);
+#endif
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
new file mode 100644
index 0000000..ba2a3c8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
@@ -0,0 +1,38 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
new file mode 100644
index 0000000..ecb5d03
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
@@ -0,0 +1,2069 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+
+#define MIN(a,b) (a > b ? b : a)
+
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+static IMG_BOOL
+AllocMemory (BM_CONTEXT *pBMContext,
+ BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_BUF *pBuf)
+{
+ BM_MAPPING *pMapping;
+ IMG_UINTPTR_T uOffset;
+ RA_ARENA *pArena = IMG_NULL;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory (pBMContext=%08X, uSize=0x%x, uFlags=0x%x, align=0x%x, pBuf=%08X)",
+ pBMContext, uSize, uFlags, uDevVAddrAlignment, pBuf));
+
+
+
+
+ if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+ return IMG_FALSE;
+ }
+
+
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+
+ pArena = psBMHeap->pImportArena;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+ return IMG_FALSE;
+ }
+
+
+ if (!RA_Alloc(pArena,
+ uSize,
+ IMG_NULL,
+ (IMG_VOID*) &pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0,
+ (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+ return IMG_FALSE;
+ }
+
+ uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+ }
+ else
+ {
+ pBuf->CpuVAddr = IMG_NULL;
+ }
+
+ if(uSize == pMapping->uSize)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ uOffset,
+ uSize,
+ psBMHeap->ui32Attribs,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+ else
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+ if (psDevVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+ return IMG_FALSE;
+ }
+
+
+ pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+ uDevVAddrAlignment,
+ psDevVAddr);
+
+
+ pBuf->DevVAddr = *psDevVAddr;
+ }
+ else
+ {
+
+
+
+ pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ &pBuf->DevVAddr);
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_MAPPING_),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED"));
+ return IMG_FALSE;
+ }
+
+
+ pBuf->CpuVAddr = IMG_NULL;
+ pBuf->hOSMemHandle = 0;
+ pBuf->CpuPAddr.uiAddr = 0;
+
+
+ pMapping->CpuVAddr = IMG_NULL;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->DevVAddr = pBuf->DevVAddr;
+ pMapping->psSysAddr = IMG_NULL;
+ pMapping->uSize = uSize;
+ pMapping->hOSMemHandle = 0;
+ }
+
+
+ pMapping->pArena = pArena;
+
+
+ pMapping->pBMHeap = psBMHeap;
+ pBuf->pMapping = pMapping;
+
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pMapping,
+ pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr,
+ pMapping->CpuPAddr.uiAddr,
+ pMapping->uSize));
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pBuf,
+ pBuf->DevVAddr.uiAddr,
+ pBuf->CpuVAddr,
+ pBuf->CpuPAddr.uiAddr,
+ uSize));
+
+
+ PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+ return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T ui32BaseOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 uFlags,
+ BM_BUF *pBuf)
+{
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ BM_MAPPING *pMapping;
+ IMG_BOOL bResult;
+ IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%x, flags=0x%x, pBuf=%08X)",
+ psBMHeap, uSize, ui32BaseOffset, bPhysContig, pvCPUVAddr, uFlags, pBuf));
+
+ PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+ uSize += ui32BaseOffset;
+ uSize = HOST_PAGEALIGN (uSize);
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*pMapping),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Mocked-up mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
+ return IMG_FALSE;
+ }
+
+ OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = psBMHeap;
+
+ if(pvCPUVAddr)
+ {
+ pMapping->CpuVAddr = pvCPUVAddr;
+
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSRegisterMem(pMapping->CpuPAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterMem Phys=0x%08X, CpuVAddr = 0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr, pMapping->CpuVAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterDiscontigMem CpuVAddr = 0x%08X, Size=%d) failed",
+ pMapping->CpuVAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+ else
+ {
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSReservePhys(pMapping->CpuPAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+
+
+ bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+ &DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+ if(!ui32BaseOffset)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ ui32BaseOffset,
+ (pMapping->uSize-ui32BaseOffset),
+ uFlags,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+ goto fail_cleanup;
+ }
+ }
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
+ }
+ pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pMapping, pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pBuf, pBuf->DevVAddr.uiAddr,
+ pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+ pBuf->pMapping = pMapping;
+ return IMG_TRUE;
+
+fail_cleanup:
+ if(ui32BaseOffset && pBuf->hOSMemHandle)
+ {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+ }
+
+ if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+ switch(pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+
+ return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags)
+{
+ IMG_VOID *pvCpuVAddr;
+
+ if(pBuf->CpuVAddr)
+ {
+ OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+ }
+ else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+ || pMapping->eCpuMemoryOrigin == hm_wrapped)
+ {
+ pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ }
+ else
+ {
+ IMG_SIZE_T ui32BytesRemaining = ui32Bytes;
+ IMG_SIZE_T ui32CurrentOffset = 0;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+
+ PVR_ASSERT(pBuf->hOSMemHandle);
+
+ while(ui32BytesRemaining > 0)
+ {
+ IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
+ CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
+
+ if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+ {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining, HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+ }
+
+ pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
+{
+ BM_MAPPING *pMapping;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "FreeBuf: pBuf=%08X: DevVAddr=%08X CpuVAddr=%08X CpuPAddr=%08X",
+ pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+
+ pMapping = pBuf->pMapping;
+
+ if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+ }
+ else
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+ }
+ else
+ {
+
+ if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+ {
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+ }
+ }
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+
+
+ PVR_ASSERT(pBuf->ui32ExportCount == 0);
+ RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ }
+ }
+ else
+ {
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (bFromAllocator)
+ DevMemoryFree (pMapping);
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+
+ }
+ }
+}
+
+PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+ if (!bTestDelete)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE hBMContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVRSRV_ERROR eError;
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_FALSE;
+ }
+
+
+
+ if (pBMContext == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBMContext->ui32RefCount--;
+
+ if (pBMContext->ui32RefCount > 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+
+
+
+ eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, BM_DestroyContext_AnyCb);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+
+
+
+
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+ if(ResManFreeSpecial() != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
+ }
+
+#endif
+ return eError;
+ }
+ else
+ {
+
+ eError = ResManFreeResByPtr(pBMContext->hResItem);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+ return eError;
+ }
+
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_TRUE;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ BM_CONTEXT *pBMContext = pvParam;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+ if(List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+ BM_DestroyContextCallBack_AnyVaCb,
+ psDeviceNode) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ if (pBMContext->psMMUContext)
+ {
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+ }
+
+
+
+ if (pBMContext->pBufferHash)
+ {
+ HASH_Delete(pBMContext->pBufferHash);
+ }
+
+ if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+
+ psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+ }
+ else
+ {
+
+ List_BM_CONTEXT_Remove(pBMContext);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+ PRESMAN_CONTEXT hResManContext;
+ hResManContext = va_arg(va, PRESMAN_CONTEXT);
+ if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+ {
+
+ pBMContext->ui32RefCount++;
+ return pBMContext;
+ }
+ return IMG_NULL;
+}
+
+IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_CONTEXT *pBMContext;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ pBMContext = va_arg(va, BM_CONTEXT*);
+ switch(psBMHeap->sDevArena.DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+ break;
+ }
+ }
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated)
+{
+ BM_CONTEXT *pBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_BOOL bKernelContext;
+ PRESMAN_CONTEXT hResManContext;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+ if (psPerProc == IMG_NULL)
+ {
+ bKernelContext = IMG_TRUE;
+ hResManContext = psDeviceNode->hResManContext;
+ }
+ else
+ {
+ bKernelContext = IMG_FALSE;
+ hResManContext = psPerProc->hResManContext;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_FALSE;
+ }
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ if (bKernelContext == IMG_FALSE)
+ {
+ IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+ BM_CreateContext_IncRefCount_AnyVaCb,
+ hResManContext);
+ if (res)
+ {
+ return res;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_CONTEXT_),
+ (IMG_PVOID *)&pBMContext, IMG_NULL,
+ "Buffer Manager Context") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+ return IMG_NULL;
+ }
+ OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+
+ pBMContext->psDeviceNode = psDeviceNode;
+
+
+
+ pBMContext->pBufferHash = HASH_Create(32);
+ if (pBMContext->pBufferHash==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+ goto cleanup;
+ }
+
+ if(psDeviceNode->pfnMMUInitialise(psDeviceNode,
+ &pBMContext->psMMUContext,
+ psPDDevPAddr) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+ goto cleanup;
+ }
+
+ if(bKernelContext)
+ {
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+ psDevMemoryInfo->pBMKernelContext = pBMContext;
+ }
+ else
+ {
+
+
+
+
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+ if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+ goto cleanup;
+ }
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+
+
+
+
+ pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+
+
+
+ List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+ BM_CreateContext_InsertHeap_ForEachVaCb,
+ psDeviceNode,
+ pBMContext);
+
+
+ List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+ }
+
+
+ pBMContext->ui32RefCount++;
+
+
+ pBMContext->hResItem = ResManRegisterRes(hResManContext,
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ pBMContext,
+ 0,
+ BM_DestroyContextCallBack);
+ if (pBMContext->hResItem == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+ goto cleanup;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_TRUE;
+ }
+ return (IMG_HANDLE)pBMContext;
+
+cleanup:
+ (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0);
+
+ return IMG_NULL;
+}
+
+
+IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+ psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+ if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID)
+ {
+
+ return psBMHeap;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_HEAP *psBMHeap;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+ if(!pBMContext)
+ {
+ return IMG_NULL;
+ }
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+
+
+
+ if(pBMContext->ui32RefCount > 0)
+ {
+ psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+ BM_CreateHeap_AnyVaCb,
+ psDevMemHeapInfo);
+
+ if (psBMHeap)
+ {
+ return psBMHeap;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_HEAP),
+ (IMG_PVOID *)&psBMHeap, IMG_NULL,
+ "Buffer Manager Heap") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+ return IMG_NULL;
+ }
+
+ OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+ psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+ psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+ psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+ psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+ psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+ psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+ psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+ psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+
+ psBMHeap->pBMContext = pBMContext;
+
+ psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+ &psBMHeap->sDevArena,
+ &psBMHeap->pVMArena);
+ if (!psBMHeap->pMMUHeap)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+ goto ErrorExit;
+ }
+
+
+ psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+ 0, 0, IMG_NULL,
+ psBMHeap->sDevArena.ui32DataPageSize,
+ BM_ImportMemory,
+ BM_FreeMemory,
+ IMG_NULL,
+ psBMHeap);
+ if(psBMHeap->pImportArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+ goto ErrorExit;
+ }
+
+ if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+
+
+
+
+ psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+ if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+ goto ErrorExit;
+ }
+ }
+
+
+ List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+ return (IMG_HANDLE)psBMHeap;
+
+
+ErrorExit:
+
+
+ if (psBMHeap->pMMUHeap != IMG_NULL)
+ {
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+ psDeviceNode->pfnMMUFinalise (pBMContext->psMMUContext);
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+ if(psBMHeap)
+ {
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+ return;
+ }
+
+
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+
+ List_BM_HEAP_Remove(psBMHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+ }
+}
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Alloc ( IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *pBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_UINT32 uFlags;
+
+ if (pui32Flags == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+ PVR_DBG_BREAK;
+ return IMG_FALSE;
+ }
+
+ uFlags = *pui32Flags;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+ SysAcquireData(&psSysData);
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ pBMContext = psBMHeap->pBMContext;
+
+ if(uDevVAddrAlignment == 0)
+ {
+ uDevVAddrAlignment = 1;
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (AllocMemory(pBMContext,
+ psBMHeap,
+ psDevVAddr,
+ uSize,
+ uFlags,
+ uDevVAddrAlignment,
+ pBuf) != IMG_TRUE)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x)=%08X",
+ uSize, uFlags, pBuf));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+
+ if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
+{
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32PageCount; i++)
+ {
+ IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
+{
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+#define WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *psBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddress;
+ IMG_UINT32 uFlags;
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+
+ uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+ if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+ {
+ uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+ ui32Size, ui32Offset, bPhysContig, pvCPUVAddr, uFlags));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+ if (bPhysContig)
+ {
+ if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+ else
+ {
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+
+ if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+#endif
+
+ sHashAddress = psSysAddr[0];
+
+
+ sHashAddress.uiAddr += ui32Offset;
+
+
+ pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, (IMG_UINTPTR_T) sHashAddress.uiAddr);
+
+ if(pBuf)
+ {
+ IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
+
+
+ if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+ pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+ ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+ pBuf->ui32RefCount++;
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ *pui32Flags = uFlags;
+
+ return IMG_TRUE;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ return IMG_FALSE;
+ }
+
+
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+
+ PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+ if (!HASH_Insert (psBMContext->pBufferHash, (IMG_UINTPTR_T) sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+ {
+ FreeBuf (pBuf, uFlags, IMG_TRUE);
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uFlags=0x%x)=%08X(devVAddr=%08X)",
+ ui32Size, uFlags, pBuf, pBuf->DevVAddr.uiAddr));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ {
+
+ *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+ }
+
+ return IMG_TRUE;
+}
+
+
+IMG_VOID BM_Export (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ pBuf->ui32ExportCount++;
+}
+
+IMG_VOID BM_FreeExport (BM_HANDLE hBuf, IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ pBuf->ui32ExportCount--;
+ FreeBuf (pBuf, ui32Flags, IMG_FALSE);
+}
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddr;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf));
+ PVR_ASSERT (pBuf!=IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ pBuf->ui32RefCount--;
+
+ if(pBuf->ui32RefCount == 0)
+ {
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+ sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+ HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddr.uiAddr);
+ }
+ FreeBuf (pBuf, ui32Flags, IMG_TRUE);
+ }
+}
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToCpuVaddr(h=%08X)=%08X",
+ hBuf, pBuf->CpuVAddr));
+ return pBuf->CpuVAddr;
+}
+
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+ return DevVAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=%08X)=%08X", hBuf, pBuf->DevVAddr));
+ return pBuf->DevVAddr;
+}
+
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ IMG_SYS_PHYADDR PhysAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+ return PhysAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=%08X)=%08X", hBuf, pBuf->CpuPAddr.uiAddr));
+ return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToOSMemHandle(h=%08X)=%08X",
+ hBuf, pBuf->hOSMemHandle));
+ return pBuf->hOSMemHandle;
+}
+
+IMG_BOOL
+BM_ContiguousStatistics (IMG_UINT32 uFlags,
+ IMG_UINT32 *pTotalBytes,
+ IMG_UINT32 *pAvailableBytes)
+{
+ if (pAvailableBytes || pTotalBytes || uFlags);
+ return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ IMG_UINT32 ui32PDumpSize = pMapping->uSize;
+#endif
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if(uFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+
+ pMapping->uSize *= 2;
+ }
+
+#ifdef PDUMP
+ if(uFlags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+#endif
+
+
+ if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+ pMapping->uSize,
+ pActualSize,
+ 0,
+ dev_vaddr_alignment,
+ &(pMapping->DevVAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+
+
+ PDUMPMALLOCPAGES(psDeviceNode->sDevId.eDeviceType, pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr, pMapping->hOSMemHandle, ui32PDumpSize, pMapping->pBMHeap->sDevArena.ui32DataPageSize, (IMG_HANDLE)pMapping);
+
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ case hm_wrapped_virtaddr:
+ case hm_contiguous:
+ {
+ psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ case hm_env:
+ {
+ psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ break;
+ }
+ case hm_wrapped_scatter:
+ case hm_wrapped_scatter_virtaddr:
+ {
+ psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "Illegal value %d for pMapping->eCpuMemoryOrigin",
+ pMapping->eCpuMemoryOrigin));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ IMG_UINT32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ ui32PSize = pMapping->uSize;
+ }
+
+ PDUMPFREEPAGES(pMapping->pBMHeap,
+ pMapping->DevVAddr,
+ ui32PSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+ (IMG_HANDLE)pMapping,
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+#endif
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase)
+{
+ BM_MAPPING *pMapping;
+ BM_HEAP *pBMHeap = pH;
+ BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uPSize;
+ IMG_UINT32 uDevVAddrAlignment = 0;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_ImportMemory (pBMContext=%08X, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+ pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+ PVR_ASSERT (ppsMapping != IMG_NULL);
+ PVR_ASSERT (pBMContext != IMG_NULL);
+
+ if (ppsMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+ goto fail_exit;
+ }
+
+ uSize = HOST_PAGEALIGN (uRequestSize);
+ PVR_ASSERT (uSize >= uRequestSize);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_MAPPING),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+ goto fail_exit;
+ }
+
+ pMapping->hOSMemHandle = 0;
+ pMapping->CpuVAddr = 0;
+ pMapping->DevVAddr.uiAddr = 0;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = pBMHeap;
+ pMapping->ui32Flags = uFlags;
+
+
+ if (pActualSize)
+ {
+ *pActualSize = uSize;
+ }
+
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+
+ if (OSAllocPages(ui32Attribs,
+ uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: OSAllocPages(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+
+ PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+ if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+ uPSize,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ 0,
+ (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ if(OSReservePhys(pMapping->CpuPAddr,
+ uPSize,
+ ui32Attribs,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed"));
+ goto fail_dev_mem_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_contiguous;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type"));
+ goto fail_mapping_alloc;
+ }
+
+
+ bResult = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_dev_mem_alloc;
+ }
+
+
+
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+
+ *pBase = pMapping->DevVAddr.uiAddr;
+ *ppsMapping = pMapping;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+ return IMG_TRUE;
+
+fail_dev_mem_alloc:
+ if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+ {
+ pMapping->uSize /= 2;
+ }
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *)pMapping->CpuVAddr,
+ pMapping->hOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ if(pMapping->CpuVAddr)
+ {
+ OSUnReservePhys(pMapping->CpuVAddr,
+ uPSize,
+ pBMHeap->ui32Attribs,
+ pMapping->hOSMemHandle);
+ }
+ sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+fail_mapping_alloc:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+fail_exit:
+ return IMG_FALSE;
+}
+
+
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+ BM_HEAP *pBMHeap = h;
+ IMG_SIZE_T uPSize;
+
+ PVR_UNREFERENCED_PARAMETER (_base);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)", h, _base, psMapping));
+
+ PVR_ASSERT (psMapping != IMG_NULL);
+
+ if (psMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+ return;
+ }
+
+ DevMemoryFree (psMapping);
+
+
+ if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+ {
+ psMapping->uSize /= 2;
+ }
+
+ if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = psMapping->uSize;
+ }
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *) psMapping->CpuVAddr,
+ psMapping->hOSMemHandle);
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+ sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: Invalid backing store type"));
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "..BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)",
+ h, _base, psMapping));
+}
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+ PVR_ASSERT (psMemInfo && psDevPAddr)
+
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+ sDevVPageAddr);
+}
+
+
+PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap, PVRSRV_HEAP_INFO *psHeapInfo)
+{
+ BM_HEAP *psBMHeap = (BM_HEAP *)hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetHeapInfo"));
+
+ psHeapInfo->hDevMemHeap = hDevMemHeap;
+ psHeapInfo->sDevVAddrBase = psBMHeap->sDevArena.BaseDevVAddr;
+ psHeapInfo->ui32HeapByteSize = psBMHeap->sDevArena.ui32Size;
+ psHeapInfo->ui32Attribs = psBMHeap->ui32Attribs;
+
+ return PVRSRV_OK;
+}
+
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+ return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+ PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+ return pBMContext->psMMUContext;
+}
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+ return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+ return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+ return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
new file mode 100644
index 0000000..2867a08
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
@@ -0,0 +1,2060 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "pvr_bridge_km.h"
+
+#include "lists.h"
+#include "emgd_drm.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
+#endif
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR);
+#endif
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+ IMG_HANDLE hExtSwapChain;
+ IMG_UINT32 ui32SwapChainID;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32RefCount;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_DC_BUFFER *psLastFlipBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+} PVRSRV_DC_SWAPCHAIN;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+ IMG_HANDLE hResItem;
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+ PVRSRV_DC_BUFFER sSystemBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PRESMAN_ITEM hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_BC_BUFFER *psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ IMG_HANDLE hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psDCPerContextInfo->psDCInfo;
+}
+
+
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psBCPerContextInfo->psBCInfo;
+}
+
+IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ IMG_UINT32 **ppui32DevID;
+ PVRSRV_DEVICE_CLASS peDeviceClass;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppui32DevID = va_arg(va, IMG_UINT32**);
+ peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+ if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+ && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+ {
+ (*pui32DevCount)++;
+ if(*ppui32DevID)
+ {
+ *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID )
+{
+
+ IMG_UINT ui32DevCount = 0;
+ SYS_DATA *psSysData;
+ IMG_UINT32 pui32Temp[PVRSRV_MAX_DEVICES];
+ int i;
+
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVEnumerateDCKM_ForEachVaCb,
+ &ui32DevCount,
+ &pui32DevID,
+ DeviceClass);
+
+ if(pui32DevCount)
+ {
+ *pui32DevCount = ui32DevCount;
+ }
+ else if(pui32DevID == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+
+
+ /* Note: The above macro returns the device IDs in the opposite order that
+ * they were registered in, which messes up EMGD's DIH (dual independant
+ * head) code. To fix that, we need to reverse the order of the device
+ * IDs:
+ */
+ /* 1st) make a temporary copy of the array, in the correct order: */
+ for (i=0; i<ui32DevCount; i++) {
+ pui32Temp[i] = *(--pui32DevID);
+ }
+ /* 2nd) make a final version of the array, in the correct order: */
+ for (i=0; i<ui32DevCount; i++) {
+ pui32DevID[i] = pui32Temp[i];
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCInfo),
+ (IMG_VOID **)&psDCInfo, IMG_NULL,
+ "Display Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+
+ *psDCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ SysRegisterExternalDevice(psDeviceNode);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psDCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ SysRemoveExternalDevice(psDeviceNode);
+
+
+
+
+ PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCInfo),
+ (IMG_VOID **)&psBCInfo, IMG_NULL,
+ "Buffer Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+
+ *psBCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psBCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+
+ if (!psDevNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+
+
+
+ if(psBCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+ psDCInfo = psDCPerContextInfo->psDCInfo;
+
+ psDCInfo->ui32RefCount--;
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+ psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+ if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ }
+
+ psDCInfo->hDevMemContext = IMG_NULL;
+ psDCInfo->hExtDevice = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCPerContextInfo),
+ (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+ "Display Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+ if(psDCInfo->ui32RefCount++ == 0)
+ {
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+ &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+ psDCInfo->ui32RefCount--;
+ return eError;
+ }
+
+
+ eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+ &psDCInfo->hExtDevice,
+ (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ return eError;
+ }
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+ }
+
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+ psDCPerContextInfo,
+ 0,
+ CloseDCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ /* Note: It is acceptable for psFormat to be NULL. In fact, this is the
+ * desired way in which to find out the number of pixel formats, so that
+ * memory can be allocated before a second call to this function, in order
+ * to get the pixel formats.
+ */
+ /* if(!hDeviceKM || !pui32Count || !psFormat)*/
+ if(!hDeviceKM || !pui32Count)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if(!hDeviceKM || !pui32Count || !psFormat)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_HANDLE hExtBuffer;
+
+ if(!hDeviceKM || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+ return eError;
+ }
+
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+ psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+
+ *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psDisplayInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+ if(!hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChainRef = hSwapChainRef;
+
+ eError = ResManFreeResByPtr(psSwapChainRef->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+ IMG_UINT32 i;
+ int timeout = 30;
+
+
+
+ if( psDCInfo->psDCSwapChainShared )
+ {
+ if( psDCInfo->psDCSwapChainShared == psSwapChain )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+ psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ while( psCurrentSwapChain->psNext )
+ {
+ if( psCurrentSwapChain->psNext != psSwapChain )
+ {
+ psCurrentSwapChain = psCurrentSwapChain->psNext;
+ continue;
+ }
+ psCurrentSwapChain->psNext = psSwapChain->psNext;
+ break;
+ }
+ }
+ }
+
+ if (psSwapChain->psQueue)
+ {
+ do
+ {
+ eError = PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+ } while (eError != PVRSRV_OK && (timeout-- > 0));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy command queue"));
+ }
+ }
+
+ eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+ return eError;
+ }
+
+
+ for(i=0; i<psSwapChain->ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if(--psSwapChainRef->psSwapChain->ui32RefCount == 0)
+ {
+ eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+ return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+ IMG_UINT32 ui32SwapChainID)
+{
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+ for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ psCurrentSwapChain;
+ psCurrentSwapChain = psCurrentSwapChain->psNext)
+ {
+ if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+ return psCurrentSwapChain;
+ }
+ return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DC_SWAPCHAIN *psSwapChain,
+ PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+ (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+ "Display Class Swapchain Reference") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+
+ psSwapChain->ui32RefCount++;
+
+
+ psSwapChainRef->psSwapChain = psSwapChain;
+ psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ psSwapChainRef,
+ 0,
+ &DestroyDCSwapChainRefCallBack);
+ *ppsSwapChainRef = psSwapChainRef;
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChainRef,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+ PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ DISPLAY_INFO sDisplayInfo;
+ int timeout = 30;
+
+
+ if(!hDeviceKM
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib
+ || !phSwapChainRef
+ || !pui32SwapChainID)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+#if 0 /* Removing limiation to allow 1 buffer allocations */
+ if (ui32BufferCount < 2)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
+ return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+ }
+#endif
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+ {
+
+ psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+ if( psSwapChain )
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVCreateDCSwapChainKM: found query"));
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ return eError;
+ }
+
+ *phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+ return PVRSRV_OK;
+ }
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ }
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN),
+ (IMG_VOID **)&psSwapChain, IMG_NULL,
+ "Display Class Swapchain") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+ if (ui32OEMFlags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
+ PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
+ PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY))
+ {
+ psQueue = NULL;
+ }
+ else
+ {
+ do
+ {
+ eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+ } while (eError != PVRSRV_OK && (timeout-- > 0));
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+ goto ErrorExit;
+ }
+ }
+
+ psSwapChain->psQueue = psQueue;
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psDCInfo->hDevMemContext,
+ &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+
+ psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+ psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+
+ apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psDCInfo = psDCInfo;
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+ return eError;
+ }
+
+
+ eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+ ui32Flags,
+ psDstSurfAttrib,
+ psSrcSurfAttrib,
+ ui32BufferCount,
+ apsSyncData,
+ ui32OEMFlags,
+ &psSwapChain->hExtSwapChain,
+ &psSwapChain->ui32SwapChainID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+ goto ErrorExit;
+ }
+
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->ui32RefCount = 1;
+ psSwapChain->ui32Flags = ui32Flags;
+
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+ {
+ if(! psDCInfo->psDCSwapChainShared )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ psSwapChain->psNext = psOldHead;
+ }
+ }
+
+
+ *pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+
+ *phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+ return eError;
+
+ErrorExit:
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+ if(psQueue)
+ {
+ PVRSRVDestroyCommandQueueKM(psQueue);
+ }
+
+ if(psSwapChain)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ pui32BufferCount,
+ ahExtBuffer);
+
+ PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+
+
+
+ for(i=0; i<*pui32BufferCount; i++)
+ {
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+ phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_BUFFER *psBuffer;
+ PVRSRV_QUEUE_INFO *psQueue;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 i;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+
+ if(!hDeviceKM || !hBuffer || !psClipRect)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psBuffer->psSwapChain->hExtSwapChain,
+ psBuffer->sDeviceClassBuffer.hExtBuffer,
+ hPrivateTag,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+ psQueue = psBuffer->psSwapChain->psQueue;
+
+ if (!psQueue)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Non-flippable swap chain"));
+ goto Exit;
+ }
+
+ apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+ psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+ {
+ apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = hPrivateTag;
+
+
+ psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+
+ psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
+
+ for(i=0; i<ui32ClipRectCount; i++)
+ {
+ psFlipCmd->psClipRect[i] = psClipRect[i];
+ }
+
+
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+
+
+
+
+
+
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ goto ProcessedQueues;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+
+ProcessedQueues:
+
+ psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+ psSwapChain = psSwapChainRef->psSwapChain;
+
+
+ psQueue = psSwapChain->psQueue;
+
+ if (!psQueue)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Non-flippable swap chain"));
+ goto Exit;
+ }
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer,
+ 0,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+
+ apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+ {
+
+ if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND));
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = IMG_NULL;
+
+
+ psFlipCmd->ui32ClipRectCount = 0;
+
+ psFlipCmd->ui32SwapInterval = 1;
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+
+
+
+
+
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ goto ProcessedQueues;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+
+ProcessedQueues:
+
+ psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+ eError = PVRSRV_OK;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
+ IMG_VOID *pvISRHandlerData,
+ IMG_UINT32 ui32ISRSourceMask,
+ IMG_UINT32 ui32DeviceID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_TRUE);
+
+ if (psDevNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+
+ psDevNode->pfnDeviceISR = pfnISRHandler;
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_UINT32 ui32State;
+ ui32State = va_arg(va, IMG_UINT32);
+
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+ if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+ {
+ psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+ }
+ }
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVSetDCState_ForEachVaCb,
+ ui32State);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+ psJTable->pfnPVRSRVRegisterDCDevice = PVRSRVRegisterDCDeviceKM;
+ psJTable->pfnPVRSRVRemoveDCDevice = PVRSRVRemoveDCDeviceKM;
+ psJTable->pfnPVRSRVOEMFunction = SysOEMFunction;
+ psJTable->pfnPVRSRVRegisterCmdProcList = PVRSRVRegisterCmdProcListKM;
+ psJTable->pfnPVRSRVRemoveCmdProcList = PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+ psJTable->pfnPVRSRVCmdComplete = OSVSyncMISR;
+#else
+ psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
+#endif
+ psJTable->pfnPVRSRVRegisterSystemISRHandler = PVRSRVRegisterSystemISRHandler;
+ psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+ psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
+#endif
+
+ return IMG_TRUE;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+ psBCInfo = psBCPerContextInfo->psBCInfo;
+
+ psBCInfo->ui32RefCount--;
+ if(psBCInfo->ui32RefCount == 0)
+ {
+ IMG_UINT32 i;
+
+
+ psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCPerContextInfo),
+ (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+ "Buffer Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+ if(psBCInfo->ui32RefCount++ == 0)
+ {
+ BUFFER_INFO sBufferInfo;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+ return eError;
+ }
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+ return eError;
+ }
+
+
+ psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+ (IMG_VOID **)&psBCInfo->psBuffer,
+ IMG_NULL,
+ "Array of Buffer Class Buffer");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+ return eError;
+ }
+ OSMemSet (psBCInfo->psBuffer,
+ 0,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psBCInfo->hDevMemContext,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+ goto ErrorExit;
+ }
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+ i,
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+ goto ErrorExit;
+ }
+
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+ }
+ }
+
+ psBCPerContextInfo->psBCInfo = psBCInfo;
+ psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+ psBCPerContextInfo,
+ 0,
+ CloseBCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+
+ return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psBufferInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ if(!hDeviceKM || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+ {
+ *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferIdFromTagKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE pidx)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ if(NULL == hDeviceKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Invalid parameters", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ if (NULL != psBCInfo->psFuncTable->pfnGetBufferIdFromTag) {
+ eError = psBCInfo->psFuncTable->pfnGetBufferIdFromTag(psBCInfo->hExtDevice,
+ ui32BufferIndex,
+ pidx);
+ if(eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,"%s : Failed to get BC Buffer Index", __FUNCTION__));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+ psJTable->pfnPVRSRVRegisterBCDevice = PVRSRVRegisterBCDeviceKM;
+ psJTable->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
+
+ return IMG_TRUE;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
new file mode 100644
index 0000000..1cf0c3c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
@@ -0,0 +1,1546 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+#include "mm.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+ PVRSRV_HEAP_INFO *psHeapInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 i;
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+
+ psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ }
+
+ for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+ psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+
+ hDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ psPerProc,
+ pbCreated);
+ if (hDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+ *phDevMemContext = hDevMemContext;
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_HANDLE hBuffer;
+
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ *ppsMemInfo = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+
+ psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+ bBMError = BM_Alloc (hDevMemHeap,
+ IMG_NULL,
+ ui32Size,
+ &psMemInfo->ui32Flags,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+ psMemInfo->ui32AllocSize = ui32Size;
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ *ppsMemInfo = psMemInfo;
+
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+ if (bFromAllocator)
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+ else
+ BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+
+
+ if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ if (psMemInfo->ui32RefCount == 0)
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+ return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+ if(psMemInfo->pvSysBackupBuffer)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+ return(PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo)
+{
+ IMG_HANDLE hSyncDevMemHeap;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ BM_CONTEXT *pBMContext;
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ (IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+ "Kernel Synchronization Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psKernelSyncInfo->ui32RefCount = 0;
+
+
+ pBMContext = (BM_CONTEXT*)hDevMemContext;
+ psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+
+ hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+
+
+
+ eError = AllocDeviceMem(hDevCookie,
+ hSyncDevMemHeap,
+ PVRSRV_MEM_CACHE_CONSISTENT,
+ sizeof(PVRSRV_SYNC_DATA),
+ sizeof(IMG_UINT32),
+ &psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ psSyncData = psKernelSyncInfo->psSyncData;
+
+ psSyncData->ui32WriteOpsPending = 0;
+ psSyncData->ui32WriteOpsComplete = 0;
+ psSyncData->ui32ReadOpsPending = 0;
+ psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32LastOpDumpVal = 0;
+ psSyncData->ui32LastReadOpDumpVal = 0;
+
+#if defined(PDUMP)
+ PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+ psKernelSyncInfo->psSyncDataMemInfoKM,
+ 0,
+ psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+
+ psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+
+ *ppsKernelSyncInfo = psKernelSyncInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (psKernelSyncInfo->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+
+ return eError;
+}
+
+static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+
+ if(psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ if(hOSWrapMem)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+}
+
+static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bFromAllocator)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+ psMemInfo->ui32RefCount--;
+
+
+ if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) && (bFromAllocator == IMG_TRUE))
+ {
+ IMG_HANDLE hMemInfo = IMG_NULL;
+
+
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+ return eError;
+ }
+
+
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
+ }
+ }
+
+
+ if (psMemInfo->ui32RefCount == 0)
+ {
+ switch(psMemInfo->memType)
+ {
+
+ case PVRSRV_MEMTYPE_WRAPPED:
+ freeWrapped(psMemInfo);
+ case PVRSRV_MEMTYPE_DEVICE:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ psMemInfo->psKernelSyncInfo->ui32RefCount--;
+
+ if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+ {
+ eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+ }
+ }
+ case PVRSRV_MEMTYPE_DEVICECLASS:
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+
+ return FreeDeviceMem2(psMemInfo, bFromAllocator);
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+ {
+ eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+ }
+ else
+ {
+
+ eError = FreeDeviceMemCallBack(psMemInfo, 0);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_ERROR eError;
+ BM_HEAP *psBMHeap;
+ IMG_HANDLE hDevMemContext;
+
+ if (!hDevMemHeap ||
+ (ui32Size == 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+ ((ui32Alignment % HOST_PAGESIZE()) != 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ eError = AllocDeviceMem(hDevCookie,
+ hDevMemHeap,
+ ui32Flags,
+ ui32Size,
+ ui32Alignment,
+ &psMemInfo);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+ psMemInfo->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto free_mainalloc;
+ }
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+ }
+
+
+ *ppsMemInfo = psMemInfo;
+
+ if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+ {
+ psMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+ else
+ {
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ psMemInfo,
+ 0,
+ FreeDeviceMemCallBack);
+ if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+ {
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto free_mainalloc;
+ }
+ }
+
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+
+ return (PVRSRV_OK);
+
+free_mainalloc:
+ FreeDeviceMem(psMemInfo);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock)
+{
+
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(pui32Total);
+ PVR_UNREFERENCED_PARAMETER(pui32Free);
+ PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+ return PVRSRV_OK;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psExtSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ PVRSRV_DEVICE_NODE* psDeviceNode;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ BM_HEAP *psBMHeap;
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL;
+ IMG_HANDLE hOSWrapMem = IMG_NULL;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_SIZE_T ui32PageCount = 0;
+ IMG_UINT32 i;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+ if (psDeviceNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(pvLinAddr)
+ {
+
+ ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+
+ ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset);
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+ ui32PageCount * ui32HostPageSize,
+ psIntSysPAddr,
+ &hOSWrapMem,
+ (ui32Flags != 0) ? IMG_TRUE : IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase1;
+ }
+
+
+ psExtSysPAddr = psIntSysPAddr;
+
+
+
+ bPhysContig = IMG_FALSE;
+ }
+ else
+ {
+
+ }
+
+
+ psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ErrorExitPhase2;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase2;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32PageOffset,
+ bPhysContig,
+ psExtSysPAddr,
+ IMG_NULL,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase3;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hOSWrapMem = hOSWrapMem;
+ psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExitPhase4;
+ }
+
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+
+ psMemInfo->ui32RefCount++;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ psMemInfo,
+ 0,
+ UnwrapExtMemoryCallBack);
+
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExitPhase4:
+ if(psMemInfo)
+ {
+ FreeDeviceMem(psMemInfo);
+
+
+
+ psMemInfo = IMG_NULL;
+ }
+
+ErrorExitPhase3:
+ if(psMemInfo)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ErrorExitPhase2:
+ if(psIntSysPAddr)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+
+ErrorExitPhase1:
+ if(psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
+ if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+ {
+ eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
+ return eError;
+ }
+ }
+
+ eError = FreeDeviceMem(psMapData->psMemInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+ return eError;
+ }
+
+
+ eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ IMG_SIZE_T ui32PageCount, ui32PageOffset;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+ IMG_DEV_PHYADDR sDevPAddr;
+ BM_BUF *psBuf;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL;
+
+
+ if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *ppsDstMemInfo = IMG_NULL;
+
+ ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+ ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)(psSrcMemInfo->sDevVAddr.uiAddr - ui32PageOffset);
+
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount*sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+
+ psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+
+ sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset);
+ for(i=0; i<ui32PageCount; i++)
+ {
+ BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+
+ psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+
+ sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+ (IMG_VOID **)&psMapData, IMG_NULL,
+ "Resource Manager Map Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDstDevMemHeap,
+ psSrcMemInfo->ui32AllocSize,
+ ui32PageOffset,
+ IMG_FALSE,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExit;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemBlock->psIntSysPAddr = psSysPAddr;
+
+
+ psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
+ psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ psMemInfo->ui32RefCount++;
+
+
+ psSrcMemInfo->ui32RefCount++;
+
+
+ BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+
+ psMapData->psMemInfo = psMemInfo;
+ psMapData->psSrcMemInfo = psSrcMemInfo;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ psMapData,
+ 0,
+ UnmapDeviceMemoryCallBack);
+
+ *ppsDstMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExit:
+
+ if(psSysPAddr)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+
+ }
+
+ if(psMemInfo)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ if(psMapData)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+ IMG_BOOL bPhysContig;
+ BM_CONTEXT *psBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ IMG_SIZE_T ui32ByteSize;
+ IMG_SIZE_T ui32Offset;
+ IMG_SIZE_T ui32PageSize = HOST_PAGESIZE();
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ IMG_UINT32 i;
+ IMG_BOOL bMapped = IMG_FALSE;
+
+ if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+ psDeviceClassBuffer->hExtBuffer,
+ &psSysPAddr,
+ &ui32ByteSize,
+ &pvCPUVAddr,
+ phOSMapInfo,
+ &bPhysContig,
+ &bMapped);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+ psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32Offset,
+ bPhysContig,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+ /* For Buffer Class of Texture Stream. Memory has been already mapped. */
+ if (IMG_FALSE == bMapped) {
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ } else {
+ psMemInfo->sDevVAddr.uiAddr = (IMG_UINT32)(psSysPAddr->uiAddr);
+ }
+
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+ psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ psMemInfo,
+ 0,
+ UnmapDeviceClassMemoryCallBack);
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ * PVRSRVGetPageListKM()
+ *
+ * This is an EMGD addition to PVR services. Given a PowerVR meminfo,
+ * returns a list of pages for that allocation. This can then be used
+ * by EMGD code for things like mapping into the GTT if the surface
+ * is going to be displayed.
+ *
+ * Note that the page list returned is the live page list and should
+ * not be modified or freed by the caller.
+ */
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetPageListKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ struct page ***pvPageList,
+ unsigned long *numpages,
+ unsigned long *offset)
+{
+ LinuxMemArea *ma;
+ unsigned long skippages, total_offset;
+
+ /* Sanity check the parameters */
+ if (!psMemInfo || !pvPageList || !numpages) {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ma = (LinuxMemArea*)psMemInfo->sMemBlk.hOSMemHandle;
+
+ /* # of pages isn't stored; needs to be calculated from number of bytes */
+ *numpages = (ma->ui32ByteSize + 4095) / 4096;
+
+ /*
+ * What type of memarea is this? We can handle ALLOC_PAGES, or SUB_ALLOC
+ * areas whose earliest ancestor is an ALLOC_PAGES.
+ */
+ switch (ma->eAreaType) {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ *pvPageList = ma->uData.sPageList.pvPageList;
+ *offset = 0;
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ /*
+ * This allocation may be a subarea of a larger allocation. We'll need to
+ * figure out the details of the parent allocation first so that we can
+ * calculate our subset of the page list and appropriate offset into the
+ * first page.
+ */
+ total_offset = 0;
+ while (ma->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) {
+ total_offset += ma->uData.sSubAlloc.ui32ByteOffset;
+ ma = ma->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+
+ /*
+ * We should now have the original ALLOC_PAGES memarea. Make sure
+ * it's actually the type we expect.
+ */
+ if (ma->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetPageListKM: meminfo for suballocation did not "
+ "originate from a a page-based allocation (type=%d)",
+ ma->eAreaType));
+ *numpages = 0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ /*
+ * After taking all nested suballocations into account, figure out
+ * where in the page list the allocation we care about really starts.
+ */
+ skippages = total_offset / 4096;
+ *offset = total_offset % 4096;
+ *pvPageList = &(ma->uData.sPageList.pvPageList)[skippages];
+
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetPageListKM: meminfo not a page-based allocation or sub-allocation (type=%d)",
+ ma->eAreaType));
+ *numpages = 0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
new file mode 100644
index 0000000..bfbd6b3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
@@ -0,0 +1,1545 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifdef PVR_SECURE_HANDLES
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef DEBUG
+#define HANDLE_BLOCK_SIZE 1
+#else
+#define HANDLE_BLOCK_SIZE 256
+#endif
+
+#define HANDLE_HASH_TAB_INIT_SIZE 32
+
+#define DEFAULT_MAX_INDEX_PLUS_ONE 0xfffffffful
+#define DEFAULT_MAX_HANDLE DEFAULT_MAX_INDEX_PLUS_ONE
+
+#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define INDEX_TO_HANDLE(psBase, idx) ((IMG_HANDLE)((idx) + 1))
+#define HANDLE_TO_INDEX(psBase, hand) ((IMG_UINT32)(hand) - 1)
+
+#define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
+#define HANDLE_TO_HANDLE_PTR(psBase, h) (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
+
+#define HANDLE_PTR_TO_INDEX(psBase, psHandle) (IMG_UINT32)((psHandle) - ((psBase)->psHandleArray))
+#define HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
+ INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
+
+#define ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
+
+#define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList
+{
+ IMG_UINT32 ui32Prev;
+ IMG_UINT32 ui32Next;
+ IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+ INTERNAL_HANDLE_FLAG_NONE = 0x00,
+ INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+ INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle
+{
+
+ PVRSRV_HANDLE_TYPE eType;
+
+
+ IMG_VOID *pvData;
+
+
+ IMG_UINT32 ui32NextIndexPlusOne;
+
+
+ enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+
+ IMG_UINT32 ui32Index;
+
+
+ struct sHandleList sChildren;
+
+
+ struct sHandleList sSiblings;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+
+ IMG_HANDLE hBaseBlockAlloc;
+
+
+ IMG_HANDLE hHandBlockAlloc;
+
+
+ struct sHandle *psHandleArray;
+
+
+ HASH_TABLE *psHashTab;
+
+
+ IMG_UINT32 ui32FreeHandCount;
+
+
+ IMG_UINT32 ui32FirstFreeIndex;
+
+
+ IMG_UINT32 ui32MaxIndexPlusOne;
+
+
+ IMG_UINT32 ui32TotalHandCount;
+
+
+ IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+
+ IMG_UINT32 ui32HandBatchSize;
+
+
+ IMG_UINT32 ui32TotalHandCountPreBatch;
+
+
+ IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+
+ IMG_UINT32 ui32BatchHandAllocFailures;
+
+
+ IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+{
+ psList->ui32Next = ui32Index;
+ psList->ui32Prev = ui32Index;
+ psList->hParent = hParent;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+
+ HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(psBase, ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+ IMG_BOOL bIsEmpty;
+
+ bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef DEBUG
+ {
+ IMG_BOOL bIsEmpty2;
+
+ bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef DEBUG
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psBase, psHandle));
+
+ return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings))
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
+ }
+ return IMG_FALSE;
+}
+#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+{
+ return psHandle->sSiblings.hParent;
+}
+
+#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+ ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+
+ struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+ PVR_ASSERT(psEntry->hParent == IMG_NULL);
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase, ui32ParentIndex));
+
+ psEntry->ui32Prev = psIns->ui32Prev;
+ psIns->ui32Prev = ui32EntryIndex;
+ psEntry->ui32Next = ui32InsIndex;
+ psPrevIns->ui32Next = ui32EntryIndex;
+
+ psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
+
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psBase, psParent));
+
+ HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psBase, psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+ if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+ {
+
+ struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
+ struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+
+ PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+ psPrev->ui32Next = psEntry->ui32Next;
+ psNext->ui32Prev = psEntry->ui32Prev;
+
+ HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+ }
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psHead->hParent);
+
+ PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+
+ for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+
+ struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+
+ ui32Index = psEntry->ui32Next;
+
+ eError = (*pfnIterFunc)(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ IMG_UINT32 ui32Index = HANDLE_TO_INDEX(psBase, hHandle);
+ struct sHandle *psHandle;
+
+
+ if (!INDEX_IS_VALID(psBase, ui32Index))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+ if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ *ppsHandle = psHandle;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+{
+ return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandle) : IMG_NULL;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+ aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+ aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->psHandleArray != IMG_NULL)
+ {
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psBase->ui32TotalHandCount * sizeof(struct sHandle),
+ psBase->psHandleArray,
+ psBase->hHandBlockAlloc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleArray: Error freeing memory (%d)", eError));
+ }
+ else
+ {
+ psBase->psHandleArray = IMG_NULL;
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HAND_KEY aKey;
+ IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+ PVRSRV_ERROR eError;
+
+
+ InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+ if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ IMG_HANDLE hHandle;
+ hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+ PVR_ASSERT(hHandle != IMG_NULL);
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(psBase, ui32Index));
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ }
+
+
+ UnlinkFromParent(psBase, psHandle);
+
+
+ eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+ return eError;
+ }
+
+
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+ if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+
+ SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+
+ return PVRSRV_OK;
+ }
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = ui32Index;
+ }
+ else
+ {
+
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+ INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
+ }
+
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+
+ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+ }
+
+ psBase->ui32FreeHandCount++;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ return eError;
+ }
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++)
+ {
+ struct sHandle *psHandle;
+
+ psHandle = INDEX_TO_HANDLE_PTR(psBase, i);
+
+ if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+ {
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+ break;
+ }
+
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ break;
+ }
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+ PVRSRVReleaseHandleBatch(psBase);
+ }
+
+
+ eError = FreeAllHandles(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+ return eError;
+ }
+
+
+ eError = FreeHandleArray(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+ return eError;
+ }
+
+ if (psBase->psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psBase->psHashTab);
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ psBase,
+ psBase->hBaseBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+ HAND_KEY aKey;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static PVRSRV_ERROR ReallocMem(IMG_PVOID *ppvMem, IMG_HANDLE *phBlockAlloc, IMG_UINT32 ui32NewSize, IMG_UINT32 ui32OldSize)
+{
+ IMG_VOID *pvOldMem = *ppvMem;
+ IMG_HANDLE hOldBlockAlloc = *phBlockAlloc;
+ IMG_UINT32 ui32CopySize = MIN(ui32NewSize, ui32OldSize);
+ IMG_VOID *pvNewMem = IMG_NULL;
+ IMG_HANDLE hNewBlockAlloc = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ if (ui32NewSize == ui32OldSize)
+ {
+ return (PVRSRV_OK);
+ }
+
+ if (ui32NewSize != 0)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NewSize,
+ &pvNewMem,
+ &hNewBlockAlloc,
+ "Memory Area");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't allocate new memory area (%d)", eError));
+ return eError;
+ }
+ }
+
+ if (ui32CopySize != 0)
+ {
+
+ OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
+ }
+
+ if (ui32OldSize != 0)
+ {
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32OldSize,
+ pvOldMem,
+ hOldBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't free old memory area (%d)", eError));
+ }
+ }
+
+ *ppvMem = pvNewMem;
+ *phBlockAlloc = hNewBlockAlloc;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReallocHandleArray)
+#endif
+static INLINE
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount, IMG_UINT32 ui32OldCount)
+{
+ return ReallocMem((IMG_PVOID *)&psBase->psHandleArray,
+ &psBase->hHandBlockAlloc,
+ ui32NewCount * sizeof(struct sHandle),
+ ui32OldCount * sizeof(struct sHandle));
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+ PVRSRV_ERROR eError;
+ struct sHandle *psHandle;
+ IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
+ IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+;
+
+ PVR_ASSERT(ui32Delta != 0);
+
+
+ if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+ {
+ ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+ ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+ if (ui32DeltaAdjusted < ui32Delta)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+
+ eError = ReallocHandleArray(psBase, ui32NewTotalHandCount, psBase->ui32TotalHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+ return eError;
+ }
+
+
+ for(psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
+ psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
+ psHandle++)
+ {
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+ psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psHandle->ui32NextIndexPlusOne = 0;
+ }
+
+
+ psBase->ui32FreeHandCount += ui32DeltaAdjusted;
+
+ if (psBase->ui32FirstFreeIndex == 0)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
+ }
+ else
+ {
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+ PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+
+ INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = psBase->ui32TotalHandCount + 1;
+ }
+ }
+
+ if (!psBase->bPurgingEnabled)
+ {
+ psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
+ }
+
+ psBase->ui32TotalHandCount = ui32NewTotalHandCount;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+ PVRSRV_ERROR eError;
+
+ if (ui32Free > psBase->ui32FreeHandCount)
+ {
+ IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+ eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ IMG_UINT32 ui32NewIndex;
+ struct sHandle *psNewHandle = IMG_NULL;
+ IMG_HANDLE hHandle;
+ HAND_KEY aKey;
+ PVRSRV_ERROR eError;
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ PVR_ASSERT(psBase->psHashTab != IMG_NULL);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+ }
+
+ if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
+ }
+
+
+ eError = EnsureFreeHandles(psBase, 1);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+ return eError;
+ }
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+
+ psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+ }
+ else
+ {
+
+ for(ui32NewIndex = psBase->ui32FirstFreeIndex; ui32NewIndex < psBase->ui32TotalHandCount; ui32NewIndex++)
+ {
+ psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+ if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+ {
+ break;
+ }
+
+ }
+ psBase->ui32FirstFreeIndex = 0;
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+ }
+ PVR_ASSERT(psNewHandle != IMG_NULL);
+
+
+ hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
+
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+
+ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ psBase->ui32FreeHandCount--;
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+ else
+ {
+
+ psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+ ui32NewIndex + 1 :
+ psNewHandle->ui32NextIndexPlusOne - 1;
+ }
+ }
+
+
+ psNewHandle->eType = eType;
+ psNewHandle->pvData = pvData;
+ psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psNewHandle->eFlag = eFlag;
+ psNewHandle->ui32Index = ui32NewIndex;
+
+ InitParentList(psBase, psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoChildren(psBase, psNewHandle));
+#endif
+
+ InitChildEntry(psBase, psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoParent(psBase, psNewHandle));
+#endif
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+ psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+
+ SET_BATCHED_HANDLE(psNewHandle);
+ }
+ else
+ {
+ psNewHandle->ui32NextIndexPlusOne = 0;
+ }
+
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ *phHandle = IMG_NULL;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle != IMG_NULL)
+ {
+ struct sHandle *psHandle;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+ return eError;
+ }
+
+
+ if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+ {
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hParentKey;
+ IMG_HANDLE hHandle;
+
+ *phHandle = IMG_NULL;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ hParent : IMG_NULL;
+
+
+ eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+ if (hHandle != IMG_NULL)
+ {
+ struct sHandle *psCHandle;
+ PVRSRV_ERROR eErr;
+
+ eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+ if (eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+ return eErr;
+ }
+
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent);
+
+
+ if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent)
+ {
+ *phHandle = hHandle;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
+
+ psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
+
+ AdoptChild(psBase, psPHand, psCHand);
+
+ *phHandle = hHandle;
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ IMG_HANDLE hHandle;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+
+ hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle == IMG_NULL)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+ *peType = psHandle->eType;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+
+ for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+ {
+ eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ *ppvData = psCHand->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+ *phParent = ParentHandle(psHandle);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32BatchSize == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = EnsureFreeHandles(psBase, ui32BatchSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+ return eError;
+ }
+
+ psBase->ui32HandBatchSize = ui32BatchSize;
+
+
+ psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+ PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+ IMG_UINT32 ui32IndexPlusOne;
+ IMG_BOOL bCommitBatch = bCommit;
+
+ if (!HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (psBase->ui32BatchHandAllocFailures != 0)
+ {
+ if (bCommit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+ }
+ bCommitBatch = IMG_FALSE;
+ }
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+ ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+ while(ui32IndexPlusOne != 0)
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
+ IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+ PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+ psHandle->ui32NextIndexPlusOne = 0;
+
+ if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ PVRSRV_ERROR eError;
+
+
+ if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+ else
+ {
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ ui32IndexPlusOne = ui32NextIndexPlusOne;
+ }
+
+#ifdef DEBUG
+ if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+ {
+ IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+ PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta));
+
+ }
+#endif
+
+ psBase->ui32HandBatchSize = 0;
+ psBase->ui32FirstBatchIndexPlusOne = 0;
+ psBase->ui32TotalHandCountPreBatch = 0;
+ psBase->ui32BatchHandAllocFailures = 0;
+
+ if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+ {
+ PVR_ASSERT(!bCommitBatch);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32MaxHandle == 0 || ui32MaxHandle >= DEFAULT_MAX_HANDLE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set becuase handles have already been allocated"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ if (psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+ return PVRSRV_OK;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->bPurgingEnabled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 ui32Handle;
+ IMG_UINT32 ui32NewHandCount;
+
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0; ui32Handle--)
+ {
+ struct sHandle *psHandle = HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
+ if (!HANDLE_STRUCT_IS_FREE(psHandle))
+ {
+ break;
+ }
+ }
+
+ ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
+
+
+ if (ui32NewHandCount >= ui32Handle && ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+ {
+ IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
+ PVRSRV_ERROR eError;
+
+
+
+ eError = ReallocHandleArray(psBase, ui32NewHandCount, psBase->ui32TotalHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ psBase->ui32TotalHandCount = ui32NewHandCount;
+ psBase->ui32FreeHandCount -= ui32Delta;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ PVRSRV_HANDLE_BASE *psBase;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ (IMG_PVOID *)&psBase,
+ &hBlockAlloc,
+ "Handle Base");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psBase, 0, sizeof(*psBase));
+
+
+ psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+ if (psBase->psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+ goto failure;
+ }
+
+ psBase->hBaseBlockAlloc = hBlockAlloc;
+
+ psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+ *ppsBase = psBase;
+
+ return PVRSRV_OK;
+failure:
+ (IMG_VOID)PVRSRVFreeHandleBase(psBase);
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+ eError = FreeHandleBase(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+ eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+ goto error;
+ }
+
+ eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+error:
+ (IMG_VOID) PVRSRVHandleDeInit();
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (gpsKernelHandleBase != IMG_NULL)
+ {
+ eError = FreeHandleBase(gpsKernelHandleBase);
+ if (eError == PVRSRV_OK)
+ {
+ gpsKernelHandleBase = IMG_NULL;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+ }
+ }
+
+ return eError;
+}
+#else
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
new file mode 100644
index 0000000..981702b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
@@ -0,0 +1,459 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define KEY_TO_INDEX(pHash, key, uSize) \
+ ((pHash)->pfnHashFunc((pHash)->uKeySize, key, uSize) % uSize)
+
+#define KEY_COMPARE(pHash, pKey1, pKey2) \
+ ((pHash)->pfnKeyComp((pHash)->uKeySize, pKey1, pKey2))
+
+struct _BUCKET_
+{
+
+ struct _BUCKET_ *pNext;
+
+
+ IMG_UINTPTR_T v;
+
+
+ IMG_UINTPTR_T k[];
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+
+ BUCKET **ppBucketTable;
+
+
+ IMG_UINT32 uSize;
+
+
+ IMG_UINT32 uCount;
+
+
+ IMG_UINT32 uMinimumSize;
+
+
+ IMG_UINT32 uKeySize;
+
+
+ HASH_FUNC *pfnHashFunc;
+
+
+ HASH_KEY_COMP *pfnKeyComp;
+};
+
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+ IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+ IMG_UINT32 uHashKey = 0;
+
+ PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+ uHashPart += (uHashPart << 12);
+ uHashPart ^= (uHashPart >> 22);
+ uHashPart += (uHashPart << 4);
+ uHashPart ^= (uHashPart >> 9);
+ uHashPart += (uHashPart << 10);
+ uHashPart ^= (uHashPart >> 2);
+ uHashPart += (uHashPart << 7);
+ uHashPart ^= (uHashPart >> 12);
+
+ uHashKey += uHashPart;
+ }
+
+ return uHashKey;
+}
+
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+ IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+ IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ if (*p1++ != *p2++)
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pBucket != IMG_NULL);
+ PVR_ASSERT (ppBucketTable != IMG_NULL);
+ PVR_ASSERT (uSize != 0);
+
+ if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ pBucket->pNext = ppBucketTable[uIndex];
+ ppBucketTable[uIndex] = pBucket;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+ BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+ BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex< uOldSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ BUCKET *pNextBucket = pBucket->pNext;
+ if (_ChainInsert (pHash, pBucket, ppNewTable, uNewSize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+ if (uNewSize != pHash->uSize)
+ {
+ BUCKET **ppNewTable;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Resize: oldsize=0x%x newsize=0x%x count=0x%x",
+ pHash->uSize, uNewSize, pHash->uCount));
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * uNewSize,
+ (IMG_PVOID*)&ppNewTable, IMG_NULL,
+ "Hash Table Buckets");
+ if (ppNewTable == IMG_NULL)
+ return IMG_FALSE;
+
+ for (uIndex=0; uIndex<uNewSize; uIndex++)
+ ppNewTable[uIndex] = IMG_NULL;
+
+ if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return IMG_TRUE;
+}
+
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+ HASH_TABLE *pHash;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(HASH_TABLE),
+ (IMG_VOID **)&pHash, IMG_NULL,
+ "Hash Table") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * pHash->uSize,
+ (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+ "Hash Table Buckets");
+
+ if (pHash->ppBucketTable == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ return IMG_NULL;
+ }
+
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = IMG_NULL;
+ return pHash;
+}
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+ if (pHash != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+ PVR_ASSERT (pHash->uCount==0);
+ if(pHash->uCount != 0)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+ PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ }
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+ pHash->ppBucketTable = IMG_NULL;
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+ BUCKET *pBucket;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert_Extended: Hash=%08X, pKey=%08X, v=0x%x", pHash, pKey, v));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+ return IMG_FALSE;
+ }
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize,
+ (IMG_VOID **)&pBucket, IMG_NULL,
+ "Hash Table entry") != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ pBucket->v = v;
+
+ OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ pHash->uCount++;
+
+
+ if (pHash->uCount << 1 > pHash->uSize)
+ {
+
+
+ _Resize (pHash, pHash->uSize << 1);
+ }
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert: Hash=%08X, k=0x%x, v=0x%x", pHash, k, v));
+
+ return HASH_Insert_Extended(pHash, &k, v);
+}
+
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=%08X, pKey=%08X", pHash, pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+
+
+ pHash->uCount--;
+
+
+ if (pHash->uSize > (pHash->uCount << 2) &&
+ pHash->uSize > pHash->uMinimumSize)
+ {
+
+
+ _Resize (pHash,
+ PRIVATE_MAX (pHash->uSize >> 1,
+ pHash->uMinimumSize));
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x%x",
+ pHash, pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash, pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=%08X, k=0x%x", pHash, k));
+
+ return HASH_Remove_Extended(pHash, &k);
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=%08X, pKey=%08X", pHash,pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x%x",
+ pHash, pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash, pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=%08X, k=0x%x", pHash,k));
+ return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+ IMG_UINT32 uIndex;
+ IMG_UINT32 uMaxLength=0;
+ IMG_UINT32 uEmptyCount=0;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ IMG_UINT32 uLength = 0;
+ if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+ uEmptyCount++;
+ for (pBucket=pHash->ppBucketTable[uIndex];
+ pBucket != IMG_NULL;
+ pBucket = pBucket->pNext)
+ uLength++;
+ uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+ }
+
+ PVR_TRACE(("hash table: uMinimumSize=%d size=%d count=%d",
+ pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+ PVR_TRACE((" empty=%d max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
new file mode 100644
index 0000000..1d7602a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+ IMG_UINT32 ui32DevIndex;
+ IMG_BOOL bIgnoreClass;
+ PVRSRV_DEVICE_CLASS eDevClass;
+
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+ bIgnoreClass = va_arg(va, IMG_BOOL);
+ if (!bIgnoreClass)
+ {
+ eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+ }
+ else
+ {
+
+
+ eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+ }
+
+ if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+ {
+ return psDeviceNode;
+ }
+ return IMG_NULL;
+}
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+ IMG_UINT32 ui32DeviceIndex;
+
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+ if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+ {
+ return psPowerDev;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
new file mode 100644
index 0000000..0dd99db
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
@@ -0,0 +1,147 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ OSFreePages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ psKernelMemInfo->pvLinAddrKM,
+ psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+ ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+ psKernelMemInfo->ui32Flags = ui32Flags;
+ psKernelMemInfo->ui32AllocSize = ui32Size;
+
+ if(OSAllocPages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ HOST_PAGESIZE(),
+ &psKernelMemInfo->pvLinAddrKM,
+ &psKernelMemInfo->sMemBlk.hOSMemHandle)
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ 0);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ psKernelMemInfo,
+ 0,
+ FreeSharedSysMemCallBack);
+
+ *ppsKernelMemInfo = psKernelMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+ }
+ else
+ {
+ eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!psKernelMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+ psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+
+ return eError;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
new file mode 100644
index 0000000..e9ae968
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
@@ -0,0 +1,246 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+
+
+
+
+
+
+
+
+ IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+ {
+ IMG_UINT8 *pui8Addr;
+ for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+ {
+ if (*pui8Addr != ui8Pattern)
+ {
+ return IMG_FALSE;
+ }
+ }
+ return IMG_TRUE;
+ }
+
+
+
+ IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+ {
+ OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (uSize != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, uSize, psInfo->uSize,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ else
+ {
+
+ uSize = psInfo->uSize;
+ }
+
+
+ if (uSize)
+ {
+ if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
+ " - referenced from %s:%d - allocated from %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ }
+ }
+
+
+ if (psInfo->eValid != isAllocated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
+ " - referenced %s:%d - freed %s:%d",
+ pvCpuVAddr, psInfo->eValid == isFree,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ }
+
+ IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+ {
+ IMG_SIZE_T i = 0;
+
+ for (; i < 128; i++)
+ {
+ *pDest = *pSrc;
+ if (*pSrc == '\0') break;
+ pDest++;
+ pSrc++;
+ }
+ }
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+ ui32Size + TEST_BUFFER_PADDING,
+ ppvCpuVAddr,
+ phBlockAlloc,
+ pszFilename,
+ ui32Line);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+ OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+ debug_strcpy(psInfo->sFileName, pszFilename);
+ psInfo->uLineNo = ui32Line;
+ psInfo->eValid = isAllocated;
+ psInfo->uSize = ui32Size;
+ psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+
+ *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+ PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+
+ OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+
+ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ psInfo->uSize = 0;
+ psInfo->uSizeParityCheck = 0;
+ psInfo->eValid = isFree;
+ psInfo->uLineNo = ui32Line;
+ debug_strcpy(psInfo->sFileName, pszFilename);
+
+ return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+ }
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
new file mode 100644
index 0000000..c1df322
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
@@ -0,0 +1,156 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X) asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X) ((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X) asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+ if (!pui32TimerRegister)
+ {
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+
+ if (bFirstTime)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+ bFirstTime = IMG_FALSE;
+ }
+
+ return 0;
+ }
+
+#if defined(__sh__)
+
+ return (0xffffffff-*pui32TimerRegister);
+
+#else
+
+ return 0;
+
+#endif
+}
+
+
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+ IMG_UINT32 ui32Time1, ui32Time2;
+
+ ui32Time1 = PVRSRVTimeNow();
+
+ OSWaitus(1000000);
+
+ ui32Time2 = PVRSRVTimeNow();
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+ return (ui32Time2 - ui32Time1);
+}
+
+
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+ IMG_UINT32 ui32Loop;
+
+ PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ asTimers[ui32Loop].ui32Total = 0;
+ asTimers[ui32Loop].ui32Count = 0;
+ }
+
+
+ #if defined(__sh__)
+
+
+
+
+
+ *TCR_2 = TIMER_DIVISOR;
+
+
+ *TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+
+ *TST_REG |= (IMG_UINT8)0x04;
+
+ pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+ #else
+
+ pui32TimerRegister = 0;
+
+ #endif
+
+}
+
+
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+ IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+ ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+ if (!ui32TicksPerMS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+ return;
+ }
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+ }
+ }
+#if 0
+
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
new file mode 100644
index 0000000..518a583
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
@@ -0,0 +1,1723 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(PDUMP)
+
+#include <stdarg.h>
+
+#include "services_headers.h"
+#if defined(SUPPORT_SGX)
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#endif
+#include "pdump_km.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
+#endif
+
+#if 1
+#define PDUMP_DBG(a) PDumpOSDebugPrintf a
+#else
+#define PDUMP_DBG(a)
+#endif
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define PTR_PLUS(t, p, x) ((t *)(((IMG_CHAR *)(p)) + (x)))
+#define VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID, p, x)
+#define VPTR_INC(p, x) (p = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+
+
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer == IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ &gpvTempBuffer,
+ &ghTempBufferBlockAlloc,
+ "PDUMP Temporary Buffer");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+ }
+ }
+
+ return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer != IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ gpvTempBuffer,
+ ghTempBufferBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+ }
+ else
+ {
+ gpvTempBuffer = IMG_NULL;
+ }
+ }
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+
+ (IMG_VOID) GetTempBuffer();
+
+
+ PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+
+ FreeTempBuffer();
+
+
+ PDumpDeInit();
+}
+
+#if defined(SGX_SUPPORT_COMMON_PDUMP)
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+ return PDumpOSIsSuspended();
+}
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_UINT32 ui32Reg, IMG_UINT32 ui32Data, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpRegWithFlagsKM"));
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :SGXREG:0x%8.8lX 0x%8.8lX\r\n", ui32Reg, ui32Data);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(IMG_UINT32 ui32Reg,IMG_UINT32 ui32Data)
+{
+ return PDumpRegWithFlagsKM(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, IMG_UINT32 ui32Flags)
+{
+
+ #define POLL_DELAY 1000UL
+ #define POLL_COUNT_LONG (2000000000UL / POLL_DELAY)
+ #define POLL_COUNT_SHORT (1000000UL / POLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PollCount;
+
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+
+ if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
+ {
+ ui32PollCount = POLL_COUNT_LONG;
+ }
+ else
+ {
+ ui32PollCount = POLL_COUNT_SHORT;
+ }
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :SGXREG:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %lu %d\r\n",
+ ui32RegAddr, ui32RegValue, ui32Mask, 0, ui32PollCount, POLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask)
+{
+ return PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_PUINT8 pui8LinAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+#if defined(LINUX)
+ PVR_ASSERT(hOSMemHandle);
+#else
+
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_ASSERT(((IMG_UINT32) pvLinAddr & (SGX_MMU_PAGE_MASK)) == 0);
+#endif
+
+ PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & (SGX_MMU_PAGE_MASK)) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_MASK)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :SGXMEM:VA_%8.8lX 0x%8.8lX %lu\r\n",
+ ui32DevVAddr, ui32NumBytes, ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+ pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+ ui32Offset = 0;
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ ui32PageSize,
+ &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr / ui32PageSize;
+
+ pui8LinAddr += ui32PageSize;
+ ui32Offset += ui32PageSize;
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :SGXMEM:PA_%8.8lX%8.8lX %lu %lu 0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag,
+ ui32Page * ui32PageSize,
+ ui32PageSize,
+ ui32PageSize,
+ ui32Page * ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINT32) pvLinAddr & (ui32PTSize - 1)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :SGXMEM:PAGE_TABLE 0x%8.8lX %lu\r\n", ui32PTSize, SGX_MMU_PAGE_SIZE);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ IMG_NULL,
+ 0,
+ (IMG_PUINT8) pvLinAddr,
+ SGX_MMU_PAGE_SIZE,
+ &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :SGXMEM:PA_%8.8lX%8.8lX 0x%lX %lu 0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag,
+ ui32Page * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ ui32Page * SGX_MMU_PAGE_SIZE);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages, ui32PageCounter;
+ IMG_DEV_PHYADDR sDevPAddr;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :SGXMEM:VA_%8.8lX\r\n", sDevVAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+ {
+ if (!bInterleaved || (ui32PageCounter % 2) == 0)
+ {
+ sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+ {
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n", (IMG_UINT32) hUniqueTag, sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ else
+ {
+
+ }
+
+ sDevVAddr.uiAddr += ui32PageSize;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+
+
+ PVR_ASSERT(((IMG_UINT32) pvLinAddr & (ui32PTSize-1UL)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :SGXMEM:PAGE_TABLE\r\n");
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ IMG_NULL,
+ 0,
+ (IMG_PUINT8) pvLinAddr,
+ SGX_MMU_PAGE_SIZE,
+ &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+ {
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n", (IMG_UINT32) hUniqueTag, ui32Page * SGX_MMU_PAGE_SIZE);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (IMG_UINT32)hUniqueTag,
+ (ui32Data & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :SGXREG:0x%8.8lX: SGXMEM:$1\r\n",
+ ui32Reg);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXREG:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ ui32Reg,
+ (IMG_UINT32) hUniqueTag,
+ (ui32Data & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PDE_ADDR_ALIGNSHIFT,
+ ui32Data & ~SGX_MMU_PDE_ADDR_MASK);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg (IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_HANDLE hUniqueTag)
+{
+ return PDumpPDRegWithFlags(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ #define MEMPOLL_DELAY (1000)
+ #define MEMPOLL_COUNT (2000000000 / MEMPOLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ PDUMP_GET_SCRIPT_STRING();
+
+
+ PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->ui32AllocSize);
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- POL :SGXMEM:VA_%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+ pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+
+ pui8LinAddr += ui32Offset;
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "POL :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+ (IMG_UINT32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32ParamOutPos;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+
+ PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32Bytes == 0 || PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+
+ if(pvAltLinAddr)
+ {
+ pui8DataLinAddr = pvAltLinAddr;
+ }
+ else if(psMemInfo->pvLinAddrKM)
+ {
+ pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+ }
+ pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+ sDevVAddr = psMemInfo->sDevVAddr;
+
+
+ sDevVAddr.uiAddr += ui32Offset;
+ pui8LinAddr += ui32Offset;
+
+ PVR_ASSERT(pui8DataLinAddr);
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pui8DataLinAddr,
+ ui32Bytes,
+ ui32Flags))
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%%lu.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :SGXMEM:VA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (IMG_UINT32)hUniqueTag,
+ psMemInfo->sDevVAddr.uiAddr,
+ ui32Offset,
+ ui32Bytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ &ui32PageByteOffset);
+ ui32NumPages = (ui32PageByteOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE();
+
+ while(ui32NumPages)
+ {
+#if 0
+ IMG_UINT32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
+ CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32CurrentOffset);
+#endif
+ ui32NumPages--;
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+#if 0
+ if(ui32PageByteOffset)
+ {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining, PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+
+ ui32PageByteOffset = 0;
+ }
+#endif
+
+ if (ui32PageByteOffset + ui32Bytes > HOST_PAGESIZE())
+ {
+
+ ui32BlockBytes = HOST_PAGESIZE() - ui32PageByteOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (IMG_UINT32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+ ui32PageByteOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ sDevVAddr.uiAddr += ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32ParamOutPos;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ if (!pvLinAddr || !PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+ if (bInitialisePages)
+ {
+
+
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pvLinAddr,
+ ui32Bytes,
+ PDUMP_FLAGS_CONTINUOUS))
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%%lu.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+
+
+
+
+ ui32PageOffset = (IMG_UINT32) pvLinAddr & (HOST_PAGESIZE() - 1);
+ ui32NumPages = (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE();
+ pui8LinAddr = (IMG_UINT8*) pvLinAddr;
+
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+
+ if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE())
+ {
+
+ ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+
+
+ if (bInitialisePages)
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (IMG_UINT32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ else
+ {
+ for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+ {
+ IMG_UINT32 ui32PTE = *((IMG_UINT32 *) (pui8LinAddr + ui32Offset));
+
+ if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0)
+ {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (IMG_UINT32)hUniqueTag2,
+ (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :SGXMEM:$1 :SGXMEM:$1 0x%8.8lX\r\n", ui32PTE & ~SGX_MMU_PDE_ADDR_MASK);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$1\r\n",
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK));
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK),
+ (IMG_UINT32) hUniqueTag2,
+ (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT,
+ ui32PTE & ~SGX_MMU_PDE_ADDR_MASK);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+#endif
+ }
+ else
+ {
+ PVR_ASSERT((ui32PTE & SGX_MMU_PTE_VALID) == 0UL);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK),
+ (ui32PTE << SGX_MMU_PTE_ADDR_ALIGNSHIFT),
+ (IMG_UINT32) hUniqueTag2);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+
+
+
+
+ ui32PageOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ (IMG_UINT8 *)&sPDDevPAddr,
+ sizeof(IMG_DEV_PHYADDR),
+ PDUMP_FLAGS_CONTINUOUS))
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ ui32PageByteOffset = sDevVAddr.uiAddr & (SGX_MMU_PAGE_MASK);
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+ sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+ if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0UL)
+ {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (IMG_UINT32)hUniqueTag2,
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "AND :SGXMEM:$2 :SGXMEM:$1 0xFFFFFFFF\r\n");
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr) & (SGX_MMU_PAGE_MASK));
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :SGXMEM:$2 :SGXMEM:$1 0x20\r\n");
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + 4) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr + 4) & (SGX_MMU_PAGE_MASK));
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ (IMG_UINT32) hUniqueTag2,
+ sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK,
+ sPDDevPAddr.uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+#endif
+ }
+ else
+ {
+ PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_MSG_STRING();
+ PDUMP_DBG(("PDumpCommentKM"));
+
+
+ if (!PDumpOSWriteString2("-- ", ui32Flags))
+ {
+ if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ else
+ {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+
+
+ eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszComment);
+ if( (eErr != PVRSRV_OK) &&
+ (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+ {
+ return eErr;
+ }
+
+
+ PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+ PDumpOSWriteString2(hMsg, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(hMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(hMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32MsgLen;
+ PDUMP_GET_MSG_STRING();
+
+
+ eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszString);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+ PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+ ui32MsgLen = PDumpOSBuflen(hMsg, ui32MaxLen);
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+ (IMG_UINT8 *)hMsg,
+ ui32MsgLen,
+ ui32Flags))
+ {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ else
+ {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM( IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ PDUMP_DATAMASTER_PIXEL,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height,
+ ui32StrideInBytes,
+ eMemFormat);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height,
+ ui32StrideInBytes,
+ eMemFormat);
+#endif
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :SGXREG:0x%08lX 0x%08lX %s\r\n",
+ ui32Address,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+ IMG_BOOL bFrameDumped;
+
+
+
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+ bFrameDumped = PDumpIsCaptureFrameKM();
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+ return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister (IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :SGXREG:0x%08X 0x%08X %s\r\n",
+ ui32Address,
+ *pui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32Flags);
+ *pui32FileOffset += ui32Size;
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PDumpRegisterRange(IMG_CHAR *pszFileName,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 i;
+ for (i = 0; i < ui32NumRegisters; i++)
+ {
+ PDumpSignatureRegister(pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+ }
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = 0;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_3d.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters (IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_ta.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters (IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+ ui32FileOffset = 0UL;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu.perf", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(const IMG_UINT32 ui32RegOffset, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n", ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(const IMG_UINT32 ui32RegOffset, IMG_BOOL bLastFrame)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n", ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpHWPerfCBKM (IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ "SAB :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+ PDUMP_DATAMASTER_EDM,
+#else
+ "SAB :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+#endif
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+
+
+ PDUMP_GET_SCRIPT_STRING();
+
+
+ PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->ui32AllocSize);
+
+ pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+ sDevVAddr = psROffMemInfo->sDevVAddr;
+
+
+ pui8LinAddr += ui32ROffOffset;
+ sDevVAddr.uiAddr += ui32ROffOffset;
+
+
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+ ui32ROffOffset,
+ pui8LinAddr,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX 0x%8.8lX\r\n",
+ (IMG_UINT32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpIDLWithFlags"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %lu\r\n", ui32Clocks);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+ return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+#endif
+
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_PVOID pvAltLinAddrUM,
+ IMG_PVOID pvLinAddrUM,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_VOID *pvAddrUM;
+ IMG_VOID *pvAddrKM;
+ IMG_UINT32 ui32BytesDumped;
+ IMG_UINT32 ui32CurrentOffset;
+
+ if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+ {
+
+ return PDumpMemKM(IMG_NULL,
+ psMemInfo,
+ ui32Offset,
+ ui32Bytes,
+ ui32Flags,
+ hUniqueTag);
+ }
+
+ pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+ pvAddrKM = GetTempBuffer();
+
+
+ PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+ if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+ {
+ PDumpCommentWithFlags(ui32Flags, "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+ }
+
+ ui32CurrentOffset = ui32Offset;
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToDump);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d), eError"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ if (ui32BytesDumped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+/* FIXME: This assert causes kernel to crash when using PDUMP */
+/* PVR_ASSERT(ui32BytesDumped == 0); */
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+ IMG_UINT32 i;
+
+
+ for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+ {
+ if((gui16MMUContextUsage & (1U << i)) == 0)
+ {
+
+ gui16MMUContextUsage |= 1U << i;
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+ if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+ {
+
+ gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_VOID *pvPDCPUAddr)
+{
+ IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32MMUContextID;
+ PVRSRV_ERROR eError;
+
+ eError = _PdumpAllocMMUContext(&ui32MMUContextID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eError));
+ return eError;
+ }
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+ PDumpComment("Set MMU Context\r\n");
+
+ PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType,
+ pszMemSpace,
+ hUniqueTag1,
+ sDevPAddr.uiAddr);
+
+
+ *pui32MMUContextID = ui32MMUContextID;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+
+ PDumpComment("MMU :%s:v%d %d\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType);
+
+ eError = _PdumpFreeMMUContext(ui32MMUContextID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
new file mode 100644
index 0000000..64e8faf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
@@ -0,0 +1,279 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+
+#define HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINTPTR_T uiPerProc;
+
+ PVR_ASSERT(psPerProc != IMG_NULL);
+
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+ if (uiPerProc == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+ PVR_ASSERT(psPerProc->ui32PID == 0);
+ }
+ else
+ {
+ PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+ PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+ }
+
+
+ if (psPerProc->psHandleBase != IMG_NULL)
+ {
+ eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ if (psPerProc->hPerProcData != IMG_NULL)
+ {
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+ return eError;
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ psPerProc,
+ psPerProc->hBlockAlloc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ return psPerProc;
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+ if (psPerProc == IMG_NULL)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ (IMG_PVOID *)&psPerProc,
+ &hBlockAlloc,
+ "Per Process Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+ psPerProc->hBlockAlloc = hBlockAlloc;
+
+ if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto failure;
+ }
+
+ psPerProc->ui32PID = ui32PID;
+ psPerProc->ui32RefCount = 0;
+
+
+ eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPerProc->hPerProcData,
+ psPerProc,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+ goto failure;
+ }
+ }
+
+ psPerProc->ui32RefCount++;
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+ ui32PID, psPerProc->ui32RefCount));
+
+ return eError;
+
+failure:
+ (IMG_VOID)FreePerProcessData(psPerProc);
+ return eError;
+}
+
+
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+ }
+ else
+ {
+ psPerProc->ui32RefCount--;
+ if (psPerProc->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+ "Last close from process 0x%x received", ui32PID));
+
+
+ PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+
+ eError = FreePerProcessData(psPerProc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+ }
+ }
+ }
+
+ eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+ PVR_ASSERT(psHashTab == IMG_NULL);
+
+
+ psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+ if (psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+ if (psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psHashTab);
+ psHashTab = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
new file mode 100644
index 0000000..b5b8585
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
@@ -0,0 +1,743 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ gbInitServerRunning = bState;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ gbInitServerRan = bState;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ gbInitSuccessful = bState;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetInitServerState : Unknown state %lx", eInitServerState));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ IMG_BOOL bReturnVal;
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ bReturnVal = gbInitServerRunning;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ bReturnVal = gbInitServerRan;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ bReturnVal = gbInitSuccessful;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetInitServerState : Unknown state %lx", eInitServerState));
+ bReturnVal = IMG_FALSE;
+ }
+
+ return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+ return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ IMG_UINT32 ui32Timeout = 1000000;
+
+#if defined(SUPPORT_LMA)
+
+ ui32Timeout *= 60;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ eError = SysPowerLockWrap(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+ do
+ {
+ eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+ ui32CallerID);
+ if (eError == PVRSRV_OK)
+ {
+ break;
+ }
+ else if (ui32CallerID == ISR_ID)
+ {
+
+
+ eError = PVRSRV_ERROR_RETRY;
+ break;
+ }
+
+ OSWaitus(1);
+ ui32Timeout--;
+ } while (ui32Timeout > 0);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ if (eError != PVRSRV_OK)
+ {
+ SysPowerLockUnwrap(psSysData);
+ }
+#endif
+ if ((eError == PVRSRV_OK) &&
+ !bSystemPowerEvent &&
+ !_IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+
+ PVRSRVPowerUnlock(ui32CallerID);
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
+{
+ OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ SysPowerLockUnwrap(gpsSysData);
+#endif
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+ if (psPowerDevice->pfnPrePower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+ eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ PVRSRVDevicePrePowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+
+ eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psPowerDevice->pfnPostPower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ PVRSRVDevicePostPowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ #if defined(PDUMP)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+
+
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+ if(eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ PDUMPSUSPEND();
+ }
+ #endif
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+
+Exit:
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+ }
+
+ if (!bRetainMutex || (eError != PVRSRV_OK))
+ {
+ PVRSRVPowerUnlock(ui32CallerID);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPrePowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ return eError;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPostPowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+ psSysData->eCurrentPowerState, eNewSysPowerState));
+
+ psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ if (_IsSystemStatePowered(eNewSysPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+
+
+
+ PVRSRVCommandCompleteCallbacks();
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnPrePower == IMG_NULL &&
+ pfnPostPower == IMG_NULL)
+ {
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+ }
+
+ SysAcquireData(&psSysData);
+
+ eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_POWER_DEV),
+ (IMG_VOID **)&psPowerDevice, IMG_NULL,
+ "Power Device");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+ return eError;
+ }
+
+
+ psPowerDevice->pfnPrePower = pfnPrePower;
+ psPowerDevice->pfnPostPower = pfnPostPower;
+ psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+ psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+ psPowerDevice->hDevCookie = hDevCookie;
+ psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+ psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+ psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+
+ List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+ return (PVRSRV_OK);
+}
+
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDev;
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDev = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDev)
+ {
+ List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+ if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+ OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+ {
+ return IMG_FALSE;
+ }
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+ return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+ ? IMG_TRUE : IMG_FALSE;
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+ if (bIdleDevice)
+ {
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%lx", eError));
+ return eError;
+ }
+ }
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+ if (bIdleDevice && eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+
+ return eError;
+}
+
+
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+
+ if (bIdleDevice)
+ {
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
new file mode 100644
index 0000000..82cc4dd
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
@@ -0,0 +1,1194 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "ra.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+ if (!psDeviceWalker->bInUse)
+ {
+ psDeviceWalker->bInUse = IMG_TRUE;
+ *pui32DevID = psDeviceWalker->uiID;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs "
+ "available!\nPerhaps need to increase SYS_DEVICE_COUNT (in "
+ "\"sysinfo.h\")."));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+
+ if (
+ (psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)
+ )
+ {
+ psDeviceWalker->bInUse = IMG_FALSE;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+ while (ui32Count)
+ {
+ WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+ psHWRegs++;
+ ui32Count--;
+ }
+}
+#endif
+
+IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+ {
+ *(*ppsDevIdList) = psDeviceNode->sDevId;
+ (*ppsDevIdList)++;
+ (*pui32DevCount)++;
+ }
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+
+ if (!pui32NumDevices || !psDevIdList)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+
+ for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+ {
+ psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+ }
+
+
+ *pui32NumDevices = 0;
+
+
+
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVEnumerateDevicesKM_ForEachVaCb,
+ pui32NumDevices,
+ &psDevIdList);
+
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = ResManInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ eError = PVRSRVPerProcessDataInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = PVRSRVHandleInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+
+ if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT) ,
+ (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+ "Event Object") != PVRSRV_OK)
+ {
+
+ goto Error;
+ }
+
+ if(OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ return eError;
+
+Error:
+ PVRSRVDeInit(psSysData);
+ return eError;
+}
+
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ if (psSysData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+ return;
+ }
+
+
+ if(psSysData->psGlobalEventObject)
+ {
+ OSEventObjectDestroy(psSysData->psGlobalEventObject);
+ OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT),
+ psSysData->psGlobalEventObject,
+ 0);
+ psSysData->psGlobalEventObject = IMG_NULL;
+ }
+
+ eError = PVRSRVHandleDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+ }
+
+ eError = PVRSRVPerProcessDataDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+ }
+
+ ResManDeInit();
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ eError = pfnRegisterDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+ return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+ }
+
+
+
+
+
+
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->psSysData = psSysData;
+ psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+ if(!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+
+ eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+ return eError;
+ }
+
+
+ if(psDeviceNode->pfnInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_DEFAULT,
+ KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+ SysAcquireData(&psSysData);
+
+ if (bInitSuccessful)
+ {
+ eError = SysFinalise();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+
+
+
+
+
+
+#if !defined(SUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION)
+ PDUMPENDINITPHASE();
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ if (psDeviceNode->pfnInitDeviceCompatCheck)
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+ else
+ return PVRSRV_OK;
+}
+
+IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ IMG_UINT32 ui32DevIndex;
+
+ eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+
+ if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+ (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+ {
+ return psDeviceNode;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+ eDeviceType,
+ ui32DevIndex);
+
+
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+ if (phDevCookie)
+ {
+ *phDevCookie = (IMG_HANDLE)psDeviceNode;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+
+ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ KERNEL_ID,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+ return eError;
+ }
+
+
+
+ eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+ RESMAN_CRITERIA_RESTYPE,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ IMG_NULL, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+ return eError;
+ }
+
+
+
+ if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+ return eError;
+ }
+ }
+
+
+
+ PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+ psDeviceNode->hResManContext = IMG_NULL;
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries)
+{
+ {
+ IMG_UINT32 uiMaxTime = ui32Tries * ui32Waitus;
+
+ LOOP_UNTIL_TIMEOUT(uiMaxTime)
+ {
+ if((*pui32LinMemAddr & ui32Mask) == ui32Value)
+ {
+ return PVRSRV_OK;
+ }
+ OSWaitus(ui32Waitus);
+ } END_LOOP_UNTIL_TIMEOUT();
+ }
+
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+#if defined (USING_ISR_INTERRUPTS)
+
+extern IMG_UINT32 gui32EventStatusServicesByISR;
+
+PVRSRV_ERROR PollForInterruptKM (IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries)
+{
+ IMG_UINT32 uiMaxTime;
+
+ uiMaxTime = ui32Tries * ui32Waitus;
+
+
+ LOOP_UNTIL_TIMEOUT(uiMaxTime)
+ {
+ if ((gui32EventStatusServicesByISR & ui32Mask) == ui32Value)
+ {
+ gui32EventStatusServicesByISR = 0;
+ return PVRSRV_OK;
+ }
+ OSWaitus(ui32Waitus);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 *pui32StrLen;
+
+ ppszStr = va_arg(va, IMG_CHAR**);
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+
+ if(psBMHeap->pImportArena)
+ {
+ RA_GetStats(psBMHeap->pImportArena,
+ ppszStr,
+ pui32StrLen);
+ }
+
+ if(psBMHeap->pVMArena)
+ {
+ RA_GetStats(psBMHeap->pVMArena,
+ ppszStr,
+ pui32StrLen);
+ }
+}
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) 0x%08X:\n",
+ (IMG_HANDLE)psBMContext);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+ PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+ if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+ List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+ PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen);
+ }
+
+
+ return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+ PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+ pui32StrLen,
+ pi32Count,
+ ppszStr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+{
+ SYS_DATA *psSysData;
+
+ if(!psMiscInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->ui32StatePresent = 0;
+
+
+ if(psMiscInfo->ui32StateRequest & ~( PVRSRV_MISC_INFO_TIMER_PRESENT
+ |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+ |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+ |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+ |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+ |PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT
+ |PVRSRV_MISC_INFO_RESET_PRESENT))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+ (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+ psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+ }
+ else
+ {
+ psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+ (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+ psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+ psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+ (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ RA_ARENA **ppArena;
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_INT32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+
+ ppArena = &psSysData->apsLocalDevMemArena[0];
+ while(*ppArena)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ RA_GetStats(*ppArena,
+ &pszStr,
+ &ui32StrLen);
+
+ ppArena++;
+ }
+
+
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+ PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count,
+ &pszStr);
+
+
+ i32Count = OSSNPrintf(pszStr, 100, "\n\0");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+ (psSysData->psGlobalEventObject != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+ psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+ }
+
+
+
+ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+ && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+ && (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_UINT32 ui32LenStrPerNum = 12;
+ IMG_INT32 i32Count;
+ IMG_INT i;
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+
+ psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
+ psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
+ psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
+ psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ for (i=0; i<4; i++)
+ {
+ if (ui32StrLen < ui32LenStrPerNum)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld", psMiscInfo->aui32DDKVersion[i]);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ if (i != 3)
+ {
+ i32Count = OSSNPrintf(pszStr, 2, ".");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+ }
+ }
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT) != 0UL)
+ {
+ if(psMiscInfo->bDeferCPUCacheFlush)
+ {
+
+ if(!psMiscInfo->bCPUCacheFlushAll)
+ {
+
+
+
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVGetMiscInfoKM: don't support deferred range flushes"));
+ PVR_DPF((PVR_DBG_MESSAGE," using deferred flush all instead"));
+ }
+
+ psSysData->bFlushAll = IMG_TRUE;
+ }
+ else
+ {
+
+ if(psMiscInfo->bCPUCacheFlushAll)
+ {
+
+ OSFlushCPUCacheKM();
+
+ psSysData->bFlushAll = IMG_FALSE;
+ }
+ else
+ {
+
+ OSFlushCPUCacheRangeKM(psMiscInfo->pvRangeAddrStart, psMiscInfo->pvRangeAddrEnd);
+ }
+ }
+ }
+#endif
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+ {
+ PVR_LOG(("User requested OS reset"));
+ OSPanic();
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFBStatsKM(IMG_UINT32 *pui32Total,
+ IMG_UINT32 *pui32Available)
+{
+ IMG_UINT32 ui32Total = 0, i = 0;
+ IMG_UINT32 ui32Available = 0;
+
+ *pui32Total = 0;
+ *pui32Available = 0;
+
+
+ while(BM_ContiguousStatistics(i, &ui32Total, &ui32Available) == IMG_TRUE)
+ {
+ *pui32Total += ui32Total;
+ *pui32Available += ui32Available;
+
+ i++;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+ goto out;
+ }
+ psSysData = psDeviceNode->psSysData;
+
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+ if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+ }
+
+ SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+ }
+
+out:
+ return bStatus;
+}
+
+IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+ IMG_BOOL *pbStatus;
+ IMG_UINT32 *pui32InterruptSource;
+ IMG_UINT32 *pui32ClearInterrupts;
+
+ pbStatus = va_arg(va, IMG_BOOL*);
+ pui32InterruptSource = va_arg(va, IMG_UINT32*);
+ pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+ {
+
+ *pbStatus = IMG_TRUE;
+ }
+
+ *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+ }
+ }
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+ IMG_UINT32 ui32ClearInterrupts = 0;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+ }
+ else
+ {
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+
+ if(ui32InterruptSource)
+ {
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVSystemLISR_ForEachVaCb,
+ &bStatus,
+ &ui32InterruptSource,
+ &ui32ClearInterrupts);
+
+ SysClearInterrupts(psSysData, ui32ClearInterrupts);
+ }
+ }
+ return bStatus;
+}
+
+
+IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+ }
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+ return;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVMISR_ForEachCb);
+
+
+ if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ PVRSRVProcessQueues(ISR_ID, IMG_FALSE);
+ }
+
+
+ if (psSysData->psGlobalEventObject)
+ {
+ IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+ if(hOSEventKM)
+ {
+ OSEventObjectSignal(hOSEventKM);
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID)
+{
+ return PVRSRVPerProcessDataConnect(ui32PID);
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+ IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+ IMG_SIZE_T uiBytesSaved = 0;
+ IMG_PVOID pvLocalMemCPUVAddr;
+ RA_SEGMENT_DETAILS sSegDetails;
+
+ if (hArena == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ sSegDetails.uiSize = 0;
+ sSegDetails.sCpuPhyAddr.uiAddr = 0;
+ sSegDetails.hSegment = 0;
+
+
+ while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+ {
+ if (pbyBuffer == IMG_NULL)
+ {
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+ }
+ else
+ {
+ if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+ {
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
+
+
+ pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (pvLocalMemCPUVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ if (bSave)
+ {
+
+ OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ else
+ {
+ IMG_UINT32 uiSize;
+
+ OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+ if (uiSize != sSegDetails.uiSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+ }
+ else
+ {
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ }
+
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+ OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+ if (pbyBuffer == IMG_NULL)
+ {
+ *puiBufSize = uiBytesSaved;
+ }
+
+ return (PVRSRV_OK);
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
new file mode 100644
index 0000000..d16ab6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
@@ -0,0 +1,1161 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "lists.h"
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+static IMG_INT
+QueuePrintCommands (PVRSRV_QUEUE_INFO * psQueue, IMG_CHAR * buffer, size_t size)
+{
+ off_t off = 0;
+ IMG_INT cmds = 0;
+ IMG_SIZE_T ui32ReadOffset = psQueue->ui32ReadOffset;
+ IMG_SIZE_T ui32WriteOffset = psQueue->ui32WriteOffset;
+ PVRSRV_COMMAND * psCmd;
+
+ while (ui32ReadOffset != ui32WriteOffset)
+ {
+ psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+ off = printAppend(buffer, size, off, "%p %p %5lu %6lu %3lu %5lu %2lu %2lu %3lu \n",
+ psQueue,
+ psCmd,
+ psCmd->ui32ProcessID,
+ psCmd->CommandType,
+ psCmd->ui32CmdSize,
+ psCmd->ui32DevIndex,
+ psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount,
+ psCmd->ui32DataSize);
+
+ ui32ReadOffset += psCmd->ui32CmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+ if (cmds == 0)
+ off = printAppend(buffer, size, off, "%p <empty>\n", psQueue);
+ return off;
+}
+
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+ PVRSRV_QUEUE_INFO * psQueue = (PVRSRV_QUEUE_INFO*)el;
+ IMG_INT cmds = 0;
+ IMG_SIZE_T ui32ReadOffset;
+ IMG_SIZE_T ui32WriteOffset;
+ PVRSRV_COMMAND * psCmd;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+ return;
+ }
+
+ ui32ReadOffset = psQueue->ui32ReadOffset;
+ ui32WriteOffset = psQueue->ui32WriteOffset;
+
+ while (ui32ReadOffset != ui32WriteOffset)
+ {
+ psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+ seq_printf(sfile, "%p %p %5lu %6lu %3lu %5lu %2lu %2lu %3lu \n",
+ psQueue,
+ psCmd,
+ psCmd->ui32ProcessID,
+ psCmd->CommandType,
+ psCmd->ui32CmdSize,
+ psCmd->ui32DevIndex,
+ psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount,
+ psCmd->ui32DataSize);
+
+ ui32ReadOffset += psCmd->ui32CmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+
+ if (cmds == 0)
+ seq_printf(sfile, "%p <empty>\n", psQueue);
+}
+
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+ PVRSRV_QUEUE_INFO * psQueue;
+ SYS_DATA * psSysData;
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+ for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+ return psQueue;
+}
+
+#endif
+
+off_t
+QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off)
+{
+ SYS_DATA * psSysData;
+ PVRSRV_QUEUE_INFO * psQueue;
+
+ SysAcquireData(&psSysData);
+
+ if (!off)
+ return printAppend (buffer, size, 0,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+
+
+
+ for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM)
+ ;
+
+ return psQueue ? QueuePrintCommands (psQueue, buffer, size) : END_OF_FILE;
+}
+#endif
+
+#define GET_SPACE_IN_CMDQ(psQueue) \
+ (((psQueue->ui32ReadOffset - psQueue->ui32WriteOffset) \
+ + (psQueue->ui32QueueSize - 1)) & (psQueue->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
+ psQueue->ui32WriteOffset = (psQueue->ui32WriteOffset + ui32Size) \
+ & (psQueue->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
+ (ui32OpsComplete >= ui32OpsPending)
+
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+ IMG_UINT32 i,
+ IMG_BOOL bIsSrc)
+{
+ PVRSRV_SYNC_OBJECT *psSyncObject;
+
+ psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+ if (psCmdCompleteData->bInUse)
+ {
+ PVR_LOG(("\t%s %lu: ROC DevVAddr:0x%lX ROP:0x%lx ROC:0x%lx, WOC DevVAddr:0x%lX WOP:0x%lx WOC:0x%lx",
+ bIsSrc ? "SRC" : "DEST", i,
+ psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+ psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete));
+ }
+ else
+ {
+ PVR_LOG(("\t%s %lu: (Not in use)", bIsSrc ? "SRC" : "DEST", i));
+ }
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ IMG_UINT32 i;
+ SYS_DATA *psSysData;
+ COMMAND_COMPLETE_DATA **ppsCmdCompleteData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+ SysAcquireData(&psSysData);
+
+ ppsCmdCompleteData = psSysData->ppsCmdCompleteData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+ if (ppsCmdCompleteData != IMG_NULL)
+ {
+ psCmdCompleteData = ppsCmdCompleteData[DC_FLIP_COMMAND];
+
+ PVR_LOG(("Command Complete Data for display device %lu:", psDeviceNode->sDevId.ui32DeviceIndex));
+
+ for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, i, IMG_TRUE);
+ }
+
+ for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, i, IMG_FALSE);
+ }
+ }
+ else
+ {
+ PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ }
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, QueueDumpDebugInfo_ForEachCb);
+}
+
+
+IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
+{
+ IMG_SIZE_T ui32Temp, ui32Result = 1;
+
+ if(!ui32Value)
+ return 0;
+
+ ui32Temp = ui32Value - 1;
+ while(ui32Temp)
+ {
+ ui32Result <<= 1;
+ ui32Temp >>= 1;
+ }
+
+ return ui32Result;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+ IMG_SIZE_T ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hMemBlock;
+
+ SysAcquireData(&psSysData);
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ (IMG_VOID **)&psQueueInfo, &hMemBlock,
+ "Queue Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+ goto ErrorExit;
+ }
+ OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+ psQueueInfo->hMemBlock[0] = hMemBlock;
+ psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+ &psQueueInfo->pvLinQueueKM, &hMemBlock,
+ "Command Queue") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+ goto ErrorExit;
+ }
+
+ psQueueInfo->hMemBlock[1] = hMemBlock;
+ psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+
+ PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+ PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+ psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSCreateResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+
+ if (OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID) != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ psQueueInfo->psNextKM = psSysData->psQueueList;
+ psSysData->psQueueList = psQueueInfo;
+
+ if (OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID) != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ *ppsQueueInfo = psQueueInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psQueueInfo)
+ {
+ if(psQueueInfo->pvLinQueueKM)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ SysAcquireData(&psSysData);
+
+ psQueue = psSysData->psQueueList;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+ eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+ goto ErrorExit;
+ }
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ if(psQueue == psQueueInfo)
+ {
+ psSysData->psQueueList = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ }
+ else
+ {
+ while(psQueue)
+ {
+ if(psQueue->psNextKM == psQueueInfo)
+ {
+ psQueue->psNextKM = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if(!psQueue)
+ {
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrorExit;
+ }
+ }
+
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSDestroyResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace)
+{
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+
+ ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
+
+ if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout == IMG_TRUE)
+ {
+ *ppvSpace = IMG_NULL;
+
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ }
+ else
+ {
+ *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize )
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_COMMAND *psCommand;
+ IMG_SIZE_T ui32CommandSize;
+ IMG_UINT32 i;
+
+
+ ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+
+ ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ + ui32DataByteSize;
+
+
+ eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ psCommand->ui32CmdSize = ui32CommandSize;
+ psCommand->ui32DevIndex = ui32DevIndex;
+ psCommand->CommandType = CommandType;
+ psCommand->ui32DstSyncCount = ui32DstSyncCount;
+ psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
+
+
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+ + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+ + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ psCommand->ui32DataSize = ui32DataByteSize;
+
+
+ for (i=0; i<ui32DstSyncCount; i++)
+ {
+ psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+ psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].ui32ReadOpsPending,
+ psCommand->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<ui32SrcSyncCount; i++)
+ {
+ psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+ psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].ui32ReadOpsPending,
+ psCommand->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+
+ *ppsCommand = psCommand;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand)
+{
+
+
+
+ if (psCommand->ui32DstSyncCount > 0)
+ {
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+ }
+
+ if (psCommand->ui32SrcSyncCount > 0)
+ {
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ }
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+ + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+
+ UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
+ PVRSRV_COMMAND *psCommand,
+ IMG_BOOL bFlush)
+{
+ PVRSRV_SYNC_OBJECT *psWalkerObj;
+ PVRSRV_SYNC_OBJECT *psEndObj;
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 ui32WriteOpsComplete;
+ IMG_UINT32 ui32ReadOpsComplete;
+
+
+ psWalkerObj = psCommand->psDstSync;
+ psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ {
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+
+ psWalkerObj++;
+ }
+
+
+ psWalkerObj = psCommand->psSrcSync;
+ psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ {
+ if (!bFlush &&
+ SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+ SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+ }
+
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+ psWalkerObj++;
+ }
+
+
+ if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVProcessCommand: invalid DeviceType 0x%x",
+ psCommand->ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psCmdCompleteData = psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->CommandType];
+ if (psCmdCompleteData->bInUse)
+ {
+
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+
+
+ psCmdCompleteData->bInUse = IMG_TRUE;
+
+
+ psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+ for (i=0; i<psCommand->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+ for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+
+
+
+
+
+
+
+
+
+
+ if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->CommandType]((IMG_HANDLE)psCmdCompleteData,
+ psCommand->ui32DataSize,
+ psCommand->pvData) == IMG_FALSE)
+ {
+
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+ return eError;
+}
+
+
+IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->bReProcessDeviceCommandComplete &&
+ psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bFlush)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_COMMAND *psCommand;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+
+ psSysData->bReProcessQueues = IMG_FALSE;
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ ui32CallerID);
+ if(eError != PVRSRV_OK)
+ {
+
+ psSysData->bReProcessQueues = IMG_TRUE;
+
+
+ if(ui32CallerID == ISR_ID)
+ {
+ if (bFlush)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
+ PVR_DPF((PVR_DBG_MESSAGE," This is due to MISR queue processing being interrupted by the Services driver."));
+ }
+
+ return PVRSRV_OK;
+ }
+
+ psQueue = psSysData->psQueueList;
+
+ if(!psQueue)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+ }
+
+ while (psQueue)
+ {
+ while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
+ {
+ psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
+
+ if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+ {
+
+ UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize)
+
+ if (bFlush)
+ {
+ continue;
+ }
+ }
+
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVProcessQueues_ForEachCb);
+
+
+
+ OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+
+ if(psSysData->bReProcessQueues)
+ {
+ return PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_INTERNAL
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+#endif
+}
+
+#endif
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+#endif
+}
+
+
+IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ IMG_SIZE_T ui32AllocSize;
+ PFN_CMD_PROC *ppfnCmdProc;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+
+ eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
+ (IMG_VOID **)&psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL,
+ "Internal Queue Info structure");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc queue"));
+ return eError;
+ }
+
+
+ ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
+
+
+ for (i=0; i<ui32CmdCount; i++)
+ {
+ ppfnCmdProc[i] = ppfnCmdProcList[i];
+ }
+
+
+ ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
+ eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL,
+ "Array of Pointers for Command Store");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+ goto ErrorExit;
+ }
+
+ for (i=0; i<ui32CmdCount; i++)
+ {
+
+
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[i][0]
+ + ui32MaxSyncsPerCmd[i][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex][i],
+ IMG_NULL,
+ "Command Complete Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",i));
+ goto ErrorExit;
+ }
+
+
+ OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00, ui32AllocSize);
+
+ psCmdCompleteData = psSysData->ppsCmdCompleteData[ui32DevIndex][i];
+
+
+ psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData)
+ + sizeof(COMMAND_COMPLETE_DATA));
+ psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+ + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+
+ psCmdCompleteData->ui32AllocSize = ui32AllocSize;
+ }
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+
+ if(psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL)
+ {
+ for (i=0; i<ui32CmdCount; i++)
+ {
+ if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
+ {
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[i][0]
+ + ui32MaxSyncsPerCmd[i][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex][i], IMG_NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
+ }
+ }
+ ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
+ }
+
+ if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
+ {
+ ui32AllocSize = ui32CmdCount * sizeof(PFN_CMD_PROC);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
+ psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+ if(psSysData->ppsCmdCompleteData[ui32DevIndex] == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveCmdProcListKM: Invalid command array"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ for(i=0; i<ui32CmdCount; i++)
+ {
+
+ if(psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i]->ui32AllocSize,
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i],
+ IMG_NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
+ }
+ }
+
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*),
+ psSysData->ppsCmdCompleteData[ui32DevIndex],
+ IMG_NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
+ }
+
+
+ if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
+ psSysData->ppfnCmdProcList[ui32DevIndex],
+ IMG_NULL);
+ psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
new file mode 100644
index 0000000..c2f7fb5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
@@ -0,0 +1,1867 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+ RESOURCE_SPAN_LIVE = 10,
+ RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_START,
+ IMPORTED_RESOURCE_SPAN_LIVE,
+ IMPORTED_RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+ IMPORTED_RESOURCE_TYPE = 20,
+ NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+struct _BT_
+{
+ enum bt_type
+ {
+ btt_span,
+ btt_free,
+ btt_live
+ } type;
+
+
+ IMG_UINTPTR_T base;
+ IMG_SIZE_T uSize;
+
+
+ struct _BT_ *pNextSegment;
+ struct _BT_ *pPrevSegment;
+
+ struct _BT_ *pNextFree;
+ struct _BT_ *pPrevFree;
+
+ BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+ RESOURCE_DESCRIPTOR eResourceSpan;
+ RESOURCE_TYPE eResourceType;
+
+
+ IMG_UINT32 ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+struct _RA_ARENA_
+{
+
+ IMG_CHAR *name;
+
+
+ IMG_SIZE_T uQuantum;
+
+
+ IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase);
+ IMG_VOID (*pImportFree) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *psMapping);
+ IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+
+ IMG_VOID *pImportHandle;
+
+
+#define FREE_TABLE_LIMIT 32
+
+
+ BT *aHeadFree [FREE_TABLE_LIMIT];
+
+
+ BT *pHeadSegment;
+ BT *pTailSegment;
+
+
+ HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+ RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE 32
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ struct proc_dir_entry* pProcInfo;
+ struct proc_dir_entry* pProcSegs;
+#else
+ IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+ IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+#endif
+
+ IMG_BOOL bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+
+#else
+static IMG_INT
+RA_DumpSegs(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+static IMG_INT
+RA_DumpInfo(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+ IMG_CHAR *pT;
+
+ for(pT = pS; *pT != 0; pT++)
+ {
+ if (*pT == ' ' || *pT == '\t')
+ {
+ *pT = '_';
+ }
+ }
+
+ return pS;
+}
+#endif
+
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+ IMG_SIZE_T _uSize,
+ IMG_SIZE_T *_pActualSize,
+ BM_MAPPING **_ppsMapping,
+ IMG_UINT32 _uFlags,
+ IMG_UINTPTR_T *_pBase)
+{
+ PVR_UNREFERENCED_PARAMETER (_h);
+ PVR_UNREFERENCED_PARAMETER (_uSize);
+ PVR_UNREFERENCED_PARAMETER (_pActualSize);
+ PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+ PVR_UNREFERENCED_PARAMETER (_uFlags);
+ PVR_UNREFERENCED_PARAMETER (_pBase);
+
+ return IMG_FALSE;
+}
+
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+ IMG_UINT32 l = 0;
+ n>>=1;
+ while (n>0)
+ {
+ n>>=1;
+ l++;
+ }
+ return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+ BT *pInsertionPoint,
+ BT *pBT)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+ if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBT->pNextSegment = pInsertionPoint->pNextSegment;
+ pBT->pPrevSegment = pInsertionPoint;
+ if (pInsertionPoint->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT;
+ else
+ pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+ pInsertionPoint->pNextSegment = pBT;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+ if (pArena->pHeadSegment == IMG_NULL)
+ {
+ pArena->pHeadSegment = pArena->pTailSegment = pBT;
+ pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+ BT *pBTScan;
+
+ if (pBT->base < pArena->pHeadSegment->base)
+ {
+
+ pBT->pNextSegment = pArena->pHeadSegment;
+ pArena->pHeadSegment->pPrevSegment = pBT;
+ pArena->pHeadSegment = pBT;
+ pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+
+
+
+
+ pBTScan = pArena->pHeadSegment;
+
+ while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
+ {
+ pBTScan = pBTScan->pNextSegment;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+ return eError;
+}
+
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ if (pBT->pPrevSegment == IMG_NULL)
+ pArena->pHeadSegment = pBT->pNextSegment;
+ else
+ pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT->pPrevSegment;
+ else
+ pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+ BT *pNeighbour;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pNeighbour, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pNeighbour->pPrevSegment = pBT;
+ pNeighbour->pNextSegment = pBT->pNextSegment;
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pNeighbour;
+ else
+ pBT->pNextSegment->pPrevSegment = pNeighbour;
+ pBT->pNextSegment = pNeighbour;
+
+ pNeighbour->type = btt_free;
+ pNeighbour->uSize = pBT->uSize - uSize;
+ pNeighbour->base = pBT->base + uSize;
+ pNeighbour->psMapping = pBT->psMapping;
+ pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ }
+ else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+
+ return pNeighbour;
+}
+
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ pBT->type = btt_free;
+ pBT->pNextFree = pArena->aHeadFree [uIndex];
+ pBT->pPrevFree = IMG_NULL;
+ if (pArena->aHeadFree[uIndex] != IMG_NULL)
+ pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+ pArena->aHeadFree [uIndex] = pBT;
+}
+
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ if (pBT->pNextFree != IMG_NULL)
+ pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+ if (pBT->pPrevFree == IMG_NULL)
+ pArena->aHeadFree[uIndex] = pBT->pNextFree;
+ else
+ pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_span;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->psMapping = IMG_NULL;
+
+ return pBT;
+}
+
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_free;
+ pBT->base = base;
+ pBT->uSize = uSize;
+
+ return pBT;
+}
+
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT != IMG_NULL)
+ {
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+ pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+ if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+ return IMG_NULL;
+ }
+ _FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+ pArena->sStatistics.uFreeResourceCount+=uSize;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ }
+ return pBT;
+}
+
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVRSRV_ERROR eError;
+ BT *pSpanStart;
+ BT *pSpanEnd;
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+ pArena->name, base, uSize));
+
+ pSpanStart = _BuildSpanMarker (base, uSize);
+ if (pSpanStart == IMG_NULL)
+ {
+ goto fail_start;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+ pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+ if (pSpanEnd == IMG_NULL)
+ {
+ goto fail_end;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+ pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto fail_bt;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ eError = _SegmentListInsert (pArena, pSpanStart);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ _FreeListInsert (pArena, pBT);
+
+ eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+#endif
+ return pBT;
+
+ fail_SegListInsert:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ fail_bt:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+
+ fail_end:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+
+ fail_start:
+ return IMG_NULL;
+}
+
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+ BT *pNeighbour;
+ IMG_UINTPTR_T uOrigBase;
+ IMG_SIZE_T uOrigSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (pBT!=IMG_NULL);
+
+ if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+ return;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount--;
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+ uOrigBase = pBT->base;
+ uOrigSize = pBT->uSize;
+
+
+ pNeighbour = pBT->pPrevSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pNeighbour->base + pNeighbour->uSize == pBT->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->base = pNeighbour->base;
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ pNeighbour = pBT->pNextSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pBT->base + pBT->uSize == pNeighbour->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+ {
+ IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
+
+
+ uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedStart < pBT->base)
+ {
+ uRoundedStart += pArena->uQuantum;
+ }
+
+
+ uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedEnd > (pBT->base + pBT->uSize))
+ {
+ uRoundedEnd -= pArena->uQuantum;
+ }
+
+ if (uRoundedStart < uRoundedEnd)
+ {
+ pArena->pBackingStoreFree(pArena->pImportHandle, uRoundedStart, uRoundedEnd, (IMG_HANDLE)0);
+ }
+ }
+
+ if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+ && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+ {
+ BT *next = pBT->pNextSegment;
+ BT *prev = pBT->pPrevSegment;
+ _SegmentListRemove (pArena, next);
+ _SegmentListRemove (pArena, prev);
+ _SegmentListRemove (pArena, pBT);
+ pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+ pArena->sStatistics.uExportCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+ pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ }
+ else
+ _FreeListInsert (pArena, pBT);
+}
+
+
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *base)
+{
+ IMG_UINT32 uIndex;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ if (uAlignment>1)
+ uAlignmentOffset %= uAlignment;
+
+
+
+ uIndex = pvr_log2 (uSize);
+
+#if 0
+
+ if (1u<<uIndex < uSize)
+ uIndex++;
+#endif
+
+ while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+ uIndex++;
+
+ while (uIndex < FREE_TABLE_LIMIT)
+ {
+ if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+ {
+
+ BT *pBT;
+
+ pBT = pArena->aHeadFree [uIndex];
+ while (pBT!=IMG_NULL)
+ {
+ IMG_UINTPTR_T aligned_base;
+
+ if (uAlignment>1)
+ aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+ else
+ aligned_base = pBT->base;
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_AttemptAllocAligned: pBT-base=0x%x "
+ "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+ pBT->base, pBT->uSize, aligned_base, uSize));
+
+ if (pBT->base + pBT->uSize >= aligned_base + uSize)
+ {
+ if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+ {
+ _FreeListRemove (pArena, pBT);
+
+ PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+
+ if (aligned_base > pBT->base)
+ {
+ BT *pNeighbour;
+
+ pNeighbour = _SegmentSplit (pArena, pBT, aligned_base-pBT->base);
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pBT);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+ #endif
+ pBT = pNeighbour;
+ }
+
+
+ if (pBT->uSize > uSize)
+ {
+ BT *pNeighbour;
+ pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pNeighbour);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+ #endif
+ }
+
+ pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+ }
+ else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+ if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+ {
+ _FreeBT (pArena, pBT, IMG_FALSE);
+ return IMG_FALSE;
+ }
+
+ if (ppsMapping!=IMG_NULL)
+ *ppsMapping = pBT->psMapping;
+
+ *base = pBT->base;
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+ }
+ }
+ pBT = pBT->pNextFree;
+ }
+
+ }
+ uIndex++;
+ }
+
+ return IMG_FALSE;
+}
+
+
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+ IMG_VOID *pImportHandle)
+{
+ RA_ARENA *pArena;
+ BT *pBT;
+ IMG_INT i;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+ name, base, uSize, imp_alloc, imp_free));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (*pArena),
+ (IMG_VOID **)&pArena, IMG_NULL,
+ "Resource Arena") != PVRSRV_OK)
+ {
+ goto arena_fail;
+ }
+
+ pArena->name = name;
+ pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : _RequestAllocFail;
+ pArena->pImportFree = imp_free;
+ pArena->pBackingStoreFree = backingstore_free;
+ pArena->pImportHandle = pImportHandle;
+ for (i=0; i<FREE_TABLE_LIMIT; i++)
+ pArena->aHeadFree[i] = IMG_NULL;
+ pArena->pHeadSegment = IMG_NULL;
+ pArena->pTailSegment = IMG_NULL;
+ pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount = 0;
+ pArena->sStatistics.uLiveSegmentCount = 0;
+ pArena->sStatistics.uFreeSegmentCount = 0;
+ pArena->sStatistics.uFreeResourceCount = 0;
+ pArena->sStatistics.uTotalResourceCount = 0;
+ pArena->sStatistics.uCumulativeAllocs = 0;
+ pArena->sStatistics.uCumulativeFrees = 0;
+ pArena->sStatistics.uImportCount = 0;
+ pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ if(strcmp(pArena->name,"") != 0)
+ {
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+ IMG_INT ret;
+ IMG_INT (*pfnCreateProcEntry)(const IMG_CHAR *, read_proc_t, write_proc_t, IMG_VOID *);
+
+ pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+ pfnCreateProcEntry = pArena->bInitProcEntry ? CreateProcEntry : CreatePerProcessProcEntry;
+
+ ret = snprintf(pArena->szProcInfoName, sizeof(pArena->szProcInfoName), "ra_info_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(pArena->szProcInfoName))
+ {
+ (IMG_VOID) pfnCreateProcEntry(ReplaceSpaces(pArena->szProcInfoName), RA_DumpInfo, 0, pArena);
+ }
+ else
+ {
+ pArena->szProcInfoName[0] = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+ }
+
+ ret = snprintf(pArena->szProcSegsName, sizeof(pArena->szProcSegsName), "ra_segs_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(pArena->szProcSegsName))
+ {
+ (IMG_VOID) pfnCreateProcEntry(ReplaceSpaces(pArena->szProcSegsName), RA_DumpSegs, 0, pArena);
+ }
+ else
+ {
+ pArena->szProcSegsName[0] = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+ }
+#else
+
+ IMG_INT ret;
+ IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+ IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+ struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+ IMG_VOID*,
+ pvr_next_proc_seq_t,
+ pvr_show_proc_seq_t,
+ pvr_off2element_proc_seq_t,
+ pvr_startstop_proc_seq_t,
+ write_proc_t);
+
+ pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+ pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+ ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+ RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcInfo = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+ }
+
+ ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+ RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcSegs = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+ }
+
+#endif
+
+ }
+#endif
+
+ pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+ if (pArena->pSegmentHash==IMG_NULL)
+ {
+ goto hash_fail;
+ }
+ if (uSize>0)
+ {
+ uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+ pBT = _InsertResource (pArena, base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto insert_fail;
+ }
+ pBT->psMapping = psMapping;
+
+ }
+ return pArena;
+
+insert_fail:
+ HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+arena_fail:
+ return IMG_NULL;
+}
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+ return;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Delete: name='%s'", pArena->name));
+
+ for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+ pArena->aHeadFree[uIndex] = IMG_NULL;
+
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed"));
+ PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+ }
+
+ _SegmentListRemove (pArena, pBT);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+#endif
+ }
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ {
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
+
+ pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+ if (pArena->pProcInfo != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcInfo );
+ }
+
+ if (pArena->pProcSegs != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcSegs );
+ }
+
+#else
+ IMG_VOID (*pfnRemoveProcEntry)(const IMG_CHAR *);
+
+ pfnRemoveProcEntry = pArena->bInitProcEntry ? RemoveProcEntry : RemovePerProcessProcEntry;
+
+ if (pArena->szProcInfoName[0] != 0)
+ {
+ pfnRemoveProcEntry(pArena->szProcInfoName);
+ }
+
+ if (pArena->szProcSegsName[0] != 0)
+ {
+ pfnRemoveProcEntry(pArena->szProcSegsName);
+ }
+
+#endif
+ }
+#endif
+ HASH_Delete (pArena->pSegmentHash);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+}
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena != IMG_NULL)
+ {
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
+
+ uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+ return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *base)
+{
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize = uRequestSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ if (pActualSize != IMG_NULL)
+ {
+ *pActualSize = uSize;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
+ pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+
+
+ bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset, base);
+ if (!bResult)
+ {
+ BM_MAPPING *psImportMapping;
+ IMG_UINTPTR_T import_base;
+ IMG_SIZE_T uImportSize = uSize;
+
+
+
+
+ if (uAlignment > pArena->uQuantum)
+ {
+ uImportSize += (uAlignment - 1);
+ }
+
+
+ uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+ bResult =
+ pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+ &psImportMapping, uFlags, &import_base);
+ if (bResult)
+ {
+ BT *pBT;
+ pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+
+ if (pBT == IMG_NULL)
+ {
+
+ pArena->pImportFree(pArena->pImportHandle, import_base,
+ psImportMapping);
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x failed!",
+ pArena->name, uSize));
+
+ return IMG_FALSE;
+ }
+ pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount += uImportSize;
+ pArena->sStatistics.uImportCount++;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset,
+ base);
+ if (!bResult)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s' uAlignment failed!",
+ pArena->name));
+ }
+ }
+ }
+#ifdef RA_STATS
+ if (bResult)
+ pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+ pArena->name, uSize, *base, bResult));
+
+
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+ return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+ BT* pSegment;
+ RESOURCE_DESCRIPTOR eNextSpan;
+
+ pSegment = pArena->pHeadSegment;
+
+ if (pSegment == IMG_NULL)
+ {
+ return 0;
+ }
+
+ if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case IMPORTED_RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_END:
+
+ if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+
+ case IMPORTED_RESOURCE_SPAN_START:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+ }
+ else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+ PVR_DBG_BREAK;
+ }
+
+ return 0;
+}
+
+#endif
+
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+ return;
+ }
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Free: name='%s', base=0x%x", pArena->name, base));
+
+ pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ if (pBT)
+ {
+ PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+ while ((IMG_UINT32)p & 3)
+ {
+ *p++ = 0xAA;
+ }
+ while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+ {
+ *(IMG_UINT32*)p = 0xAAAAAAAA;
+ p += sizeof(IMG_UINT32);
+ }
+ while (p < endp)
+ {
+ *p++ = 0xAA;
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize));
+}
+#endif
+ _FreeBT (pArena, pBT, bFreeBackingStore);
+ }
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+ BT *pBT;
+
+ if (psSegDetails->hSegment)
+ {
+ pBT = (BT *)psSegDetails->hSegment;
+ }
+ else
+ {
+ RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+ pBT = pArena->pHeadSegment;
+ }
+
+ while (pBT != IMG_NULL)
+ {
+ if (pBT->type == btt_live)
+ {
+ psSegDetails->uiSize = pBT->uSize;
+ psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+ psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+ return IMG_TRUE;
+ }
+
+ pBT = pBT->pNextSegment;
+ }
+
+ psSegDetails->uiSize = 0;
+ psSegDetails->sCpuPhyAddr.uiAddr = 0;
+ psSegDetails->hSegment = (IMG_HANDLE)-1;
+
+ return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+ BT *pBT;
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ if (pJFSavedArena != IMG_NULL)
+ {
+ for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ if (pBT->type == btt_free)
+ {
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+ while ((IMG_UINT32)p & 3)
+ {
+ if (*p++ != 0xAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ }
+ while (p < endp)
+ {
+ if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ p += 4;
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+ switch (eType)
+ {
+ case btt_span: return "span";
+ case btt_free: return "free";
+ case btt_live: return "live";
+ }
+ return "junk";
+}
+#endif
+
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+ PVR_DPF ((PVR_DBG_MESSAGE," alloc=%08X free=%08X handle=%08X quantum=%d",
+ pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+ pArena->uQuantum));
+ PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:"));
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment"));
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment"));
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
+ (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
+ pBT->pRef));
+ }
+
+#ifdef HASH_TRACE
+ HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ IMG_INT off = (IMG_INT)el;
+
+ switch (off)
+ {
+ case 1:
+ seq_printf(sfile, "quantum\t\t\t%lu\n", pArena->uQuantum);
+ break;
+ case 2:
+ seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+ break;
+#ifdef RA_STATS
+ case 3:
+ seq_printf(sfile,"span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+ break;
+ case 4:
+ seq_printf(sfile, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+ break;
+ case 5:
+ seq_printf(sfile, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+ break;
+ case 6:
+ seq_printf(sfile, "free resource count\t%lu (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ break;
+ case 7:
+ seq_printf(sfile, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+ break;
+ case 8:
+ seq_printf(sfile, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+ break;
+ case 9:
+ seq_printf(sfile, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+ break;
+ case 10:
+ seq_printf(sfile, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+ break;
+#endif
+ }
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+ if(off <= 9)
+#else
+ if(off <= 1)
+#endif
+ return (void*)(IMG_INT)(off+1);
+ return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = (BT*)el;
+
+ if (el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name);
+ return;
+ }
+
+ if (pBT)
+ {
+ seq_printf(sfile, "%08x %8x %4s %08x\n",
+ (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+ (IMG_UINT)pBT->psMapping);
+ }
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = 0;
+
+ if(off == 0)
+ return PVR_PROC_SEQ_START_TOKEN;
+
+ for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+ return (void*)pBT;
+}
+
+
+
+#else
+static IMG_INT
+RA_DumpSegs(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ BT *pBT = 0;
+ IMG_INT len = 0;
+ RA_ARENA *pArena = (RA_ARENA *)data;
+
+ if (count < 80)
+ {
+ *start = (IMG_CHAR *)0;
+ return (0);
+ }
+ *eof = 0;
+ *start = (IMG_CHAR *)1;
+ if (off == 0)
+ {
+ return printAppend(page, count, 0, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name);
+ }
+ for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment)
+ ;
+ if (pBT)
+ {
+ len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
+ (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+ (IMG_UINT)pBT->psMapping);
+ }
+ else
+ {
+ *eof = 1;
+ }
+ return (len);
+}
+
+static IMG_INT
+RA_DumpInfo(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ IMG_INT len = 0;
+ RA_ARENA *pArena = (RA_ARENA *)data;
+
+ if (count < 80)
+ {
+ *start = (IMG_CHAR *)0;
+ return (0);
+ }
+ *eof = 0;
+ switch (off)
+ {
+ case 0:
+ len = printAppend(page, count, 0, "quantum\t\t\t%lu\n", pArena->uQuantum);
+ break;
+ case 1:
+ len = printAppend(page, count, 0, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+ break;
+#ifdef RA_STATS
+ case 2:
+ len = printAppend(page, count, 0, "span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+ break;
+ case 3:
+ len = printAppend(page, count, 0, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+ break;
+ case 4:
+ len = printAppend(page, count, 0, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+ break;
+ case 5:
+ len = printAppend(page, count, 0, "free resource count\t%lu (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ break;
+ case 6:
+ len = printAppend(page, count, 0, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+ break;
+ case 7:
+ len = printAppend(page, count, 0, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+ break;
+ case 8:
+ len = printAppend(page, count, 0, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+ break;
+ case 9:
+ len = printAppend(page, count, 0, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+ break;
+#endif
+
+ default:
+ *eof = 1;
+ }
+ *start = (IMG_CHAR *)1;
+ return (len);
+}
+#endif
+#endif
+
+
+#ifdef RA_STATS
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen)
+{
+ IMG_CHAR *pszStr = *ppszStr;
+ IMG_UINT32 ui32StrLen = *pui32StrLen;
+ IMG_INT32 i32Count;
+ BT *pBT;
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
+ pArena->pImportAlloc,
+ pArena->pImportFree,
+ pArena->pImportHandle,
+ pArena->uQuantum);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
+ (IMG_UINT32) pBT->base,
+ pBT->uSize,
+ _BTType(pBT->type),
+ pBT->psMapping);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
new file mode 100644
index 0000000..14b16fe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
@@ -0,0 +1,704 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+static DEFINE_MUTEX(lock);
+
+#define ACQUIRE_SYNC_OBJ do { \
+ if (in_interrupt()) { \
+ printk ("ISR cannot take RESMAN mutex\n"); \
+ BUG(); \
+ } \
+ else mutex_lock(&lock); \
+} while (0)
+#define RELEASE_SYNC_OBJ mutex_unlock(&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_ITEM_ **ppsThis;
+ struct _RESMAN_ITEM_ *psNext;
+
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32ResType;
+
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ RESMAN_FREE_FN pfnFreeResource;
+} RESMAN_ITEM;
+
+
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_CONTEXT_ **ppsThis;
+ struct _RESMAN_CONTEXT_ *psNext;
+
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ RESMAN_ITEM *psResItemList;
+
+} RESMAN_CONTEXT;
+
+
+typedef struct
+{
+ RESMAN_CONTEXT *psContextList;
+
+} RESMAN_LIST, *PRESMAN_LIST;
+
+
+PRESMAN_LIST gpsResList = IMG_NULL;
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback);
+
+
+#ifdef DEBUG
+ static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+ #define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+ #define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+ if (gpsResList == IMG_NULL)
+ {
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*gpsResList),
+ (IMG_VOID **)&gpsResList, IMG_NULL,
+ "Resource Manager List") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ gpsResList->psContextList = IMG_NULL;
+
+
+ VALIDATERESLIST();
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+ if (gpsResList != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+ gpsResList = IMG_NULL;
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext)
+{
+ PVRSRV_ERROR eError;
+ PRESMAN_CONTEXT psResManContext;
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+ (IMG_VOID **)&psResManContext, IMG_NULL,
+ "Resource Manager Context");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+ }
+
+#ifdef DEBUG
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psResManContext->psResItemList = IMG_NULL;
+ psResManContext->psPerProc = hPerProc;
+
+
+ List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+ IMG_BOOL bKernelContext)
+{
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+
+
+ if (!bKernelContext)
+ {
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+ }
+
+
+ PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+
+ List_RESMAN_CONTEXT_Remove(psResManContext);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+
+
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+
+ RELEASE_SYNC_OBJ;
+}
+
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource)
+{
+ PRESMAN_ITEM psNewResItem;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+ return (PRESMAN_ITEM) IMG_NULL;
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+ "FreeFunc %08X",
+ psResManContext, ui32ResType, (IMG_UINT32)pvParam,
+ ui32Param, pfnFreeResource));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+ IMG_NULL,
+ "Resource Manager Item") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item"));
+
+
+ RELEASE_SYNC_OBJ;
+
+ return((PRESMAN_ITEM)IMG_NULL);
+ }
+
+
+#ifdef DEBUG
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->ui32Param = ui32Param;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+ psNewResItem->ui32Flags = 0;
+
+
+ List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(psNewResItem);
+}
+
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X", psResItem));
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = FreeResourceByPtr(psResItem, IMG_TRUE);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(eError);
+}
+
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+ "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+ psResManContext, ui32SearchCriteria, ui32ResType,
+ (IMG_UINT32)pvParam, ui32Param));
+
+
+ eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+ ui32ResType, pvParam, ui32Param,
+ IMG_TRUE);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
+ PRESMAN_CONTEXT psNewResManContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ if (psNewResManContext != IMG_NULL)
+ {
+
+ List_RESMAN_ITEM_Remove(psResItem);
+
+
+ List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+ }
+ else
+ {
+ eError = FreeResourceByPtr(psResItem, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+ return eError;
+ }
+ }
+
+ return eError;
+}
+
+IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ RESMAN_ITEM *psItem;
+
+ psItem = va_arg(va, RESMAN_ITEM*);
+
+ return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
+ RESMAN_ITEM *psItem)
+{
+ PVRSRV_ERROR eResult;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ psItem, psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psResManContext,
+ psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
+ psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+ if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+ ResManFindResourceByPtr_AnyVaCb,
+ psItem))
+ {
+ eResult = PVRSRV_OK;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_NOT_OWNER;
+ }
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eResult;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if (psItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ psItem, psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
+ psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+ List_RESMAN_ITEM_Remove(psItem);
+
+
+
+ RELEASE_SYNC_OBJ;
+
+
+ if (bExecuteCallback)
+ {
+ eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+ }
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ if(OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory"));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return(eError);
+}
+
+IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+ ui32Param = va_arg(va, IMG_UINT32);
+
+
+ if(
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+ (psCurItem->ui32Param == ui32Param))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+ FreeResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam,
+ ui32Param)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
+ }
+
+ return eError;
+}
+
+
+#ifdef DEBUG
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+ PRESMAN_ITEM psCurItem, *ppsThisItem;
+ PRESMAN_CONTEXT psCurContext, *ppsThisContext;
+
+
+ if (psResList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+ return;
+ }
+
+ psCurContext = psResList->psContextList;
+ ppsThisContext = &psResList->psContextList;
+
+
+ while(psCurContext != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurContext->ppsThis != ppsThisContext)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+ psCurContext, psCurContext->ppsThis,
+ psCurContext->psNext, ppsThisContext));
+ PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+ }
+
+
+ psCurItem = psCurContext->psResItemList;
+ ppsThisItem = &psCurContext->psResItemList;
+ while(psCurItem != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurItem->ppsThis != ppsThisItem)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+ psCurItem, psCurItem->ppsThis, psCurItem->psNext, ppsThisItem));
+ PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+ }
+
+
+ ppsThisItem = &psCurItem->psNext;
+ psCurItem = psCurItem->psNext;
+ }
+
+
+ ppsThisContext = &psCurContext->psNext;
+ psCurContext = psCurContext->psNext;
+ }
+}
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
new file mode 100644
index 0000000..ad24b6f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
@@ -0,0 +1,2772 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+
+#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+
+#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+typedef struct _MMU_PT_INFO_
+{
+
+ IMG_VOID *hPTPageOSMemHandle;
+ IMG_CPU_VIRTADDR PTPageCpuVAddr;
+ IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+struct _MMU_CONTEXT_
+{
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+
+ IMG_VOID *hPDOSMemHandle;
+
+
+ MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+ IMG_UINT32 ui32PDumpMMUContextID;
+#endif
+
+ struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+
+ MMU_CONTEXT *psMMUContext;
+
+
+
+
+ IMG_UINT32 ui32PDBaseIndex;
+
+ IMG_UINT32 ui32PageTableCount;
+
+ IMG_UINT32 ui32PTETotal;
+
+ IMG_UINT32 ui32PDEPageSizeCtrl;
+
+
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ IMG_UINT32 ui32DataPageBitWidth;
+
+ IMG_UINT32 ui32DataPageMask;
+
+
+
+
+ IMG_UINT32 ui32PTShift;
+
+ IMG_UINT32 ui32PTBitWidth;
+
+ IMG_UINT32 ui32PTMask;
+
+ IMG_UINT32 ui32PTSize;
+
+ IMG_UINT32 ui32PTECount;
+
+
+
+
+ IMG_UINT32 ui32PDShift;
+
+ IMG_UINT32 ui32PDBitWidth;
+
+ IMG_UINT32 ui32PDMask;
+
+
+
+ RA_ARENA *psVMArena;
+ DEV_ARENA_DESCRIPTOR *psDevArena;
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF
+#endif
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag);
+#endif
+
+#define PAGE_TEST 0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#define PT_DEBUG 0
+#if PT_DEBUG
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i;
+
+
+ for(i = 0; i < 1024; i += 8)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "%.8lx %.8lx %.8lx %.8lx %.8lx %.8lx %.8lx %.8lx\n",
+ p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+ p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+ }
+}
+
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i, ui32Count = 0;
+
+
+ for(i = 0; i < 1024; i++)
+ if(p[i] & SGX_MMU_PTE_VALID)
+ ui32Count++;
+
+ if(psPTInfoList->ui32ValidPTECount != ui32Count)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %lu ui32Count: %lu\n",
+ psPTInfoList->ui32ValidPTECount, ui32Count));
+ DumpPT(psPTInfoList);
+ BUG();
+ }
+}
+#else
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+ ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+ #else
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+
+IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+ MMU_PT_INFO *psPTInfoList,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+ &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+ return IMG_FALSE;
+ }
+
+
+ if(psPTInfoList->PTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->PTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+ }
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+
+
+
+ if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+ return IMG_FALSE;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+
+ psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psPTInfoList->hPTPageOSMemHandle);
+ if(!psPTInfoList->PTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+ return IMG_FALSE;
+ }
+
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+ #endif
+ }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ {
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+
+ pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+
+ for(i=0; i<pMMUHeap->ui32PTECount; i++)
+ {
+ pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+ }
+#else
+
+ OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, PDUMP_PT_UNIQUETAG);
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+ *psDevPAddr = sDevPAddr;
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ psPTInfoList->PTPageCpuVAddr,
+ psPTInfoList->hPTPageOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->PTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+
+
+ OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psPTInfoList->hPTPageOSMemHandle);
+
+
+
+
+ RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+ IMG_UINT32 *pui32PDEntry;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ SYS_DATA *psSysData;
+ MMU_PT_INFO **ppsPTInfoList;
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+#if PT_DEBUG
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+ {
+ DumpPT(ppsPTInfoList[ui32PTIndex]);
+
+ }
+#endif
+
+
+ PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+ }
+
+
+ PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+ {
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, PDUMP_PT_UNIQUETAG);
+ }
+
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+ return;
+ }
+ }
+
+
+ if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+ {
+ if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+ {
+ IMG_PUINT32 pui32Tmp;
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+
+ for(i=0;
+ (i<pMMUHeap->ui32PTETotal) && (i<pMMUHeap->ui32PTECount);
+ i++)
+ {
+ pui32Tmp[i] = 0;
+ }
+
+
+
+ if(bOSFreePT)
+ {
+ _FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+ }
+
+
+
+
+ pMMUHeap->ui32PTETotal -= i;
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+ }
+
+ if(bOSFreePT)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MMU_PT_INFO),
+ ppsPTInfoList[ui32PTIndex],
+ IMG_NULL);
+ ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+ }
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+ }
+
+ PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+ IMG_UINT32 i;
+
+ for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+ {
+ _DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+ }
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ IMG_UINT32 ui32PageTableCount;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 i;
+ IMG_UINT32 *pui32PDEntry;
+ MMU_PT_INFO **ppsPTInfoList;
+ SYS_DATA *psSysData;
+ IMG_DEV_VIRTADDR sHighDevVAddr;
+
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+ PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+
+ if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+ < (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+ {
+
+ sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+ }
+ else
+ {
+ sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+ + ui32Size
+ + pMMUHeap->ui32DataPageMask
+ + pMMUHeap->ui32PTMask;
+ }
+
+ ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+ ui32PageTableCount -= ui32PDIndex;
+
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PageTableCount);
+ PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PageTableCount);
+
+
+ for(i=0; i<ui32PageTableCount; i++)
+ {
+ if(ppsPTInfoList[i] == IMG_NULL)
+ {
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_PT_INFO),
+ (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+ "MMU Page Table Info");
+ if (ppsPTInfoList[i] == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+ }
+
+ if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+ && ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+ {
+ IMG_DEV_PHYADDR sDevPAddr;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 j;
+#else
+
+ PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+
+ if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+ return IMG_FALSE;
+ }
+
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+ return IMG_FALSE;
+ }
+ }
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+
+
+
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+ }
+ else
+ {
+
+ PVR_ASSERT(pui32PDEntry[i] != 0);
+ }
+ }
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+ #endif
+
+ return IMG_TRUE;
+}
+
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ MMU_CONTEXT *psMMUContext;
+ IMG_HANDLE hPDOSMemHandle;
+ SYS_DATA *psSysData;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+ SysAcquireData(&psSysData);
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_CONTEXT),
+ (IMG_VOID **)&psMMUContext, IMG_NULL,
+ "MMU Context");
+ if (psMMUContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ psMMUContext->psDevInfo = psDevInfo;
+
+
+ psMMUContext->psDeviceNode = psDeviceNode;
+
+
+ if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if(pvPDCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(pvPDCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &psDevInfo->pvDummyPTPageCpuVAddr,
+ &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if(psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyPTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &psDevInfo->pvDummyDataPageCpuVAddr,
+ &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if(psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyDataPageCpuVAddr);
+ }
+ else
+ {
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPDOSMemHandle);
+ if(!pvPDCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyPTPageOSMemHandle);
+ if(!psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyDataPageOSMemHandle);
+ if(!psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+#endif
+ }
+
+
+ PDUMPCOMMENT("Alloc page directory");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+
+ if (pvPDCpuVAddr)
+ {
+ pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ }
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+
+
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+ for(i=0; i<SGX_MMU_PT_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+
+ PDUMPCOMMENT("Dummy Page table contents");
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+ for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+ {
+ pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+ }
+
+ PDUMPCOMMENT("Dummy Data Page contents");
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#else
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+#endif
+
+
+ PDUMPCOMMENT("Page directory contents");
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+#if defined(PDUMP)
+ if(PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+ "SGXMEM",
+ &psMMUContext->ui32PDumpMMUContextID,
+ 2,
+ PDUMP_PT_UNIQUETAG,
+ pvPDCpuVAddr) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+
+
+ psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+ psMMUContext->sPDDevPAddr = sPDDevPAddr;
+ psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+
+ *ppsMMUContext = psMMUContext;
+
+
+ *psPDDevPAddr = sPDDevPAddr;
+
+
+ psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+ psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 *pui32Tmp, i;
+ SYS_DATA *psSysData;
+ MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+ MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+ SysAcquireData(&psSysData);
+
+
+ PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, "SGXMEM", psMMUContext->ui32PDumpMMUContextID, 2);
+
+
+ PDUMPCOMMENT("Free page directory");
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+#endif
+
+ pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+
+
+
+
+
+ if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psMMUContext->pvPDCpuVAddr,
+ psMMUContext->hPDOSMemHandle);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyPTPageCpuVAddr,
+ psDevInfo->hDummyPTPageOSMemHandle);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyDataPageCpuVAddr,
+ psDevInfo->hDummyDataPageOSMemHandle);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->pvPDCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psMMUContext->hPDOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyPTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyPTPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyDataPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyDataPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+#endif
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+
+ ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+ while(*ppsMMUContext)
+ {
+ if(*ppsMMUContext == psMMUContext)
+ {
+
+ *ppsMMUContext = psMMUContext->psNext;
+ break;
+ }
+
+
+ ppsMMUContext = &((*ppsMMUContext)->psNext);
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+
+}
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+ IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+
+ pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+ pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+
+
+ PDUMPCOMMENT("Page directory shared heap range copy");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+ {
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+
+
+ pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+ if (pui32PDCpuVAddr[ui32PDEntry])
+ {
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+ }
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ if (bInvalidateDirectoryCache)
+ {
+
+
+
+
+ MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+ }
+#endif
+}
+
+
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+
+ continue;
+ }
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (!pui32Tmp)
+ {
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08lX (VAddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+ CheckPT(ppsPTInfoList[0]);
+ }
+
+
+
+ if (ppsPTInfoList[0] && ppsPTInfoList[0]->ui32ValidPTECount == 0)
+ {
+ _DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+ }
+
+ if(bInvalidateDirectoryCache)
+ {
+ MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+ else
+ {
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(psMMUHeap,
+ sDevVAddr,
+ psMMUHeap->ui32DataPageSize * ui32PageCount,
+ IMG_TRUE,
+ hUniqueTag);
+#endif
+}
+
+
+IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+ IMG_SIZE_T ui32Start,
+ IMG_SIZE_T ui32End,
+ IMG_HANDLE hUniqueTag)
+{
+ MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+ IMG_DEV_VIRTADDR Start;
+
+ Start.uiAddr = ui32Start;
+
+ MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (ui32End - ui32Start) >> pMMUHeap->ui32PTShift, hUniqueTag);
+}
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_UINT32 ui32ScaleSize;
+
+ PVR_ASSERT (psDevArena != IMG_NULL);
+
+ if (psDevArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_HEAP),
+ (IMG_VOID **)&pMMUHeap, IMG_NULL,
+ "MMU Heap");
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+ return IMG_NULL;
+ }
+
+ pMMUHeap->psMMUContext = psMMUContext;
+ pMMUHeap->psDevArena = psDevArena;
+
+
+
+
+ switch(pMMUHeap->psDevArena->ui32DataPageSize)
+ {
+ case 0x1000:
+ ui32ScaleSize = 0;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+ break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ case 0x4000:
+ ui32ScaleSize = 2;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+ break;
+ case 0x10000:
+ ui32ScaleSize = 4;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+ break;
+ case 0x40000:
+ ui32ScaleSize = 6;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+ break;
+ case 0x100000:
+ ui32ScaleSize = 8;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+ break;
+ case 0x400000:
+ ui32ScaleSize = 10;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+ break;
+#endif
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+ goto ErrorFreeHeap;
+ }
+
+
+ pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+ pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+ pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+
+ pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+ pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+ pMMUHeap->ui32PTSize = (1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+
+ if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+ {
+ pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+ }
+ pMMUHeap->ui32PTECount = pMMUHeap->ui32PTSize >> 2;
+
+
+ pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+ pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+
+
+
+
+ if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+ {
+
+
+
+ PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+ & (pMMUHeap->ui32DataPageMask
+ | pMMUHeap->ui32PTMask)) == 0);
+ }
+
+
+ pMMUHeap->ui32PTETotal = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+
+ pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+
+
+
+ pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotal + pMMUHeap->ui32PTECount - 1)
+ >> pMMUHeap->ui32PTBitWidth;
+
+
+ pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+ psDevArena->BaseDevVAddr.uiAddr,
+ psDevArena->ui32Size,
+ IMG_NULL,
+ pMMUHeap->ui32DataPageSize,
+ IMG_NULL,
+ IMG_NULL,
+ MMU_FreePageTables,
+ pMMUHeap);
+
+ if (pMMUHeap->psVMArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+ goto ErrorFreePagetables;
+ }
+
+#if 0
+
+ if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32XTileStride;
+
+
+
+
+
+
+ ui32XTileStride = 2;
+
+ ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
+ & ((psDevArena->BaseDevVAddr.uiAddr>>20)
+ << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
+ & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
+ << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_CFG_MASK
+ & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
+ PDUMPREG(EUR_CR_BIF_TILE0, ui32RegVal);
+ }
+#endif
+
+
+
+ *ppsVMArena = pMMUHeap->psVMArena;
+
+ return pMMUHeap;
+
+
+ErrorFreePagetables:
+ _DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+ if (pMMUHeap != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+ if(pMMUHeap->psVMArena)
+ {
+ RA_Delete (pMMUHeap->psVMArena);
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+ _DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *psDevVAddr)
+{
+ IMG_BOOL bStatus;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+ uSize, uFlags, uDevVAddrAlignment));
+
+
+
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+ IMG_UINTPTR_T uiAddr;
+
+ bStatus = RA_Alloc (pMMUHeap->psVMArena,
+ uSize,
+ pActualSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ 0,
+ &uiAddr);
+ if(!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));
+ return bStatus;
+ }
+
+ psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+ }
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+
+ bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize);
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+ if (!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+
+ RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+ }
+ }
+
+ return bStatus;
+}
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+ return;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_Free: mmu=%08X, dev_vaddr=%08X", pMMUHeap, DevVAddr.uiAddr));
+
+ if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+ (DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+ {
+ RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't find DevVAddr %08X in a DevArena",DevVAddr.uiAddr));
+}
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 ui32NumPTEntries;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32PTEntry;
+
+ MMU_PT_INFO **ppsPTInfoList;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTDumpCount;
+
+
+ ui32NumPTEntries = (uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift;
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+
+ while(ui32NumPTEntries > 0)
+ {
+ MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+ if(ui32NumPTEntries <= pMMUHeap->ui32PTECount - ui32PTIndex)
+ {
+ ui32PTDumpCount = ui32NumPTEntries;
+ }
+ else
+ {
+ ui32PTDumpCount = pMMUHeap->ui32PTECount - ui32PTIndex;
+ }
+
+ if (psPTInfo)
+ {
+ pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+
+
+ ui32NumPTEntries -= ui32PTDumpCount;
+
+
+ ui32PTIndex = 0;
+ }
+
+ PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif
+
+
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_DEV_PHYADDR DevPAddr,
+ IMG_UINT32 ui32MemFlags)
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 ui32MMUFlags = 0;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+
+
+ if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+ {
+
+ ui32MMUFlags = 0;
+ }
+ else if(PVRSRV_MEM_READ & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+ }
+ else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+ }
+
+
+ if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+ }
+
+#if !defined(FIX_HW_BRN_25503)
+
+ if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+ }
+#endif
+
+
+
+
+
+ ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if (pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08lX PDIdx:%u PTIdx:%u",
+ DevVAddr.uiAddr,
+ DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+ ui32Index ));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08lX", pui32Tmp[ui32Index]));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08lX", DevPAddr.uiAddr));
+ }
+
+ PVR_ASSERT((pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID) == 0);
+#endif
+
+
+ ppsPTInfoList[0]->ui32ValidPTECount++;
+
+
+ pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ & ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+ | SGX_MMU_PTE_VALID
+ | ui32MMUFlags;
+
+ CheckPT(ppsPTInfoList[0]);
+}
+
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount, i;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
+ {
+ IMG_SYS_PHYADDR sSysAddr;
+
+ sSysAddr = psSysAddr[i];
+
+
+
+ PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+ DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize));
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapPages: mmu=%08X, devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+ pMMUHeap, DevVAddr.uiAddr, SysPAddr.uiAddr, uSize));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+ for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += ui32VAdvance;
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uByteSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 uOffset = 0;
+ IMG_DEV_VIRTADDR MapDevVAddr;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapShadow: %08X, 0x%x, %08X",
+ MapBaseDevVAddr.uiAddr,
+ uByteSize,
+ CpuVAddr));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+
+ PVR_ASSERT(((IMG_UINT32)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i=0; i<uByteSize; i+=ui32VAdvance)
+ {
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ if(CpuVAddr)
+ {
+ CpuPAddr = OSMapLinToCPUPhys ((IMG_VOID *)((IMG_UINT32)CpuVAddr + uOffset));
+ }
+ else
+ {
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ }
+ DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset,
+ (IMG_UINTPTR_T)CpuVAddr + uOffset,
+ CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr,
+ DevPAddr.uiAddr));
+
+ MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+
+ MapDevVAddr.uiAddr += ui32VAdvance;
+ uOffset += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 uPageSize = psMMUHeap->ui32DataPageSize;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+
+
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08lX (VAddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08lX", pui32Tmp[ui32PTIndex]));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+ }
+
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif
+}
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+ IMG_UINT32 *pui32PageTable;
+ IMG_UINT32 ui32Index;
+ IMG_DEV_PHYADDR sDevPAddr;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ sDevPAddr.uiAddr = 0;
+ return sDevPAddr;
+ }
+
+
+ ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+
+ sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+
+ sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+ return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+ return (pMMUContext->sPDDevPAddr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_DEV_PHYADDR DevPAddr;
+
+
+
+ pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+ DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+ return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hOSMemHandle = IMG_NULL;
+ IMG_BYTE *pui8MemBlock = IMG_NULL;
+ IMG_SYS_PHYADDR sMemBlockSysPAddr;
+ IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui8MemBlock,
+ &hOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+
+ if(pui8MemBlock)
+ {
+ sMemBlockCpuPAddr = OSMapLinToCPUPhys(pui8MemBlock);
+ }
+ else
+ {
+
+ sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+ }
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ 3 * SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+ pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 3,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hOSMemHandle);
+ if(!pui8MemBlock)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+
+ psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+ psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+
+
+ psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+ psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+
+ OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+
+ OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_SYS_PHYADDR sPDSysPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BIFResetPD,
+ psDevInfo->hBIFResetPDOSMemHandle);
+ }
+ else
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+ 3 * SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBIFResetPDOSMemHandle);
+
+ sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+ RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+ IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
+ IMG_UINT32 *pui32PD = IMG_NULL;
+ IMG_UINT32 *pui32PT = IMG_NULL;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sPTDevPAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui32PT,
+ &hPTPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui32PD,
+ &hPDPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+
+ if(pui32PT)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(pui32PT);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+ }
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ if(pui32PD)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(pui32PD);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE * 2,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
+ pui32PT = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPTPageOSMemHandle);
+ if(!pui32PT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ pui32PD = pui32PT + 1024;
+ sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + 4096;
+ }
+
+ OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
+ psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
+ psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
+ psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
+ psDevInfo->pui32BRN22997PD = pui32PD;
+ psDevInfo->pui32BRN22997PT = pui32PT;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
+ IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ volatile IMG_UINT32 *pui32HostPort;
+ IMG_UINT32 ui32BIFCtrl;
+
+
+
+
+ pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
+
+
+ sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
+
+ ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_VALID;
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+ psDevInfo->sBRN22997PDDevPAddr.uiAddr);
+ PDUMPPDREG(EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
+
+
+ ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl);
+
+
+ if (pui32HostPort)
+ {
+
+ IMG_UINT32 ui32Tmp;
+ ui32Tmp = *pui32HostPort;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
+ }
+
+
+
+
+
+
+
+ PDUMPCOMMENT("RDW :SGXMEM:v4:%08lX\r\n", sDevVAddr.uiAddr);
+
+ PDUMPCOMMENT("SAB :SGXMEM:v4:%08lX 4 0 hostport.bin", sDevVAddr.uiAddr);
+
+
+ pui32PD[ui32PDIndex] = 0;
+ pui32PT[ui32PTIndex] = 0;
+
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl);
+}
+
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PD,
+ psDevInfo->hBRN22997PDPageOSMemHandle);
+ }
+
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PT,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+ }
+ }
+ else
+ {
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+
+
+ RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+}
+#endif
+
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+ IMG_UINT32 *pui32PD;
+ IMG_UINT32 *pui32PT = IMG_NULL;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sPTDevPAddr;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui32PT,
+ &hPTPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+
+ if(pui32PT)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(pui32PT);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+ }
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ pui32PT = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPTPageOSMemHandle);
+ if(!pui32PT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+ psDevInfo->sExtSystemCacheRegsPTSysPAddr = sSysPAddr;
+ }
+
+ OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ pui32PD[ui32PDIndex] = (sPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_VALID;
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+ psDevInfo->pui32ExtSystemCacheRegsPT = pui32PT;
+ psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle = hPTPageOSMemHandle;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 *pui32PD;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ pui32PD[ui32PDIndex] = 0;
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32ExtSystemCacheRegsPT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32ExtSystemCacheRegsPT,
+ psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle);
+ }
+ }
+ else
+ {
+ if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32ExtSystemCacheRegsPT,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle);
+
+ RA_Free(psLocalDevMemArena, psDevInfo->sExtSystemCacheRegsPTSysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+ volatile IMG_UINT32 ui32WriteData;
+ volatile IMG_UINT32 ui32ReadData;
+ volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+ IMG_INT n;
+ IMG_BOOL bOK=IMG_TRUE;
+
+ ui32WriteData = 0xffffffff;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ ui32WriteData = 0;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ if (bOK)
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr));
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr));
+ }
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
new file mode 100644
index 0000000..287d4f3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
@@ -0,0 +1,135 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena);
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMU);
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMU,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_UINT32 ui32Size);
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMU);
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMU);
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP * pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR * pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR dev_vaddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_SGXDEV_INFO *psDevInfo);
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
new file mode 100644
index 0000000..93f356d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
@@ -0,0 +1,454 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PVRSRV_ERROR eError;
+
+ psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ IMG_UINT32 i;
+ PRESMAN_ITEM psResItem;
+
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * psStubPBDesc->ui32SubKernelMemInfosCount,
+ (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ExitNotFound;
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ 0);
+
+
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ExitNotFound;
+ }
+
+ *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+ *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+ *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+ *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+ *ui32SharedPBDescSubKernelMemInfosCount =
+ psStubPBDesc->ui32SubKernelMemInfosCount;
+
+ *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+ for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+ {
+ ppsSharedPBDescSubKernelMemInfos[i] =
+ psStubPBDesc->ppsSubKernelMemInfos[i];
+ }
+
+ psStubPBDesc->ui32RefCount++;
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ return PVRSRV_OK;
+ }
+
+ eError = PVRSRV_OK;
+ if (bLockOnFailure)
+ {
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ psPerProc,
+ 0,
+ &SGXCleanupSharedPBDescCreateLockCallback);
+
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ExitNotFound;
+ }
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ psPerProcCreateSharedPB = psPerProc;
+ }
+ else
+ {
+ eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+ }
+ExitNotFound:
+ *phSharedPBDesc = IMG_NULL;
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+
+
+
+ psStubPBDescIn->ui32RefCount--;
+ if (psStubPBDescIn->ui32RefCount == 0)
+ {
+ List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+ for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+ {
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+ psStubPBDescIn->ppsSubKernelMemInfos[i]);
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+ psStubPBDescIn->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDescIn,
+ 0);
+
+
+
+ SGXCleanupRequest(psDeviceNode,
+ IMG_NULL,
+ PVRSRV_CLEANUPCMD_PB);
+ }
+ return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+#ifdef DEBUG
+ PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+ PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+ PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psPerProcCreateSharedPB = IMG_NULL;
+ psResItemCreateSharedPB = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+ PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+ return ResManFreeResByPtr(hSharedPBDesc);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+ PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC;
+ IMG_UINT32 i;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PRESMAN_ITEM psResItem;
+
+
+ if (psPerProcCreateSharedPB != psPerProc)
+ {
+ goto NoAdd;
+ }
+ else
+ {
+ PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+ ResManFreeResByPtr(psResItemCreateSharedPB);
+
+ PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ }
+
+ psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+ }
+
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXAddSharedPBDescKM: "
+ "Failed to register existing shared "
+ "PBDesc with the resource manager"));
+ goto NoAddKeepPB;
+ }
+
+
+ psStubPBDesc->ui32RefCount++;
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ eRet = PVRSRV_OK;
+ goto NoAddKeepPB;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ (IMG_VOID **)&psStubPBDesc,
+ 0,
+ "Stub Parameter Buffer Description") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+ "StubPBDesc"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * ui32SharedPBDescSubKernelMemInfosCount,
+ (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+ 0,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to alloc "
+ "StubPBDesc->ppsSubKernelMemInfos"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ psStubPBDesc->ui32RefCount = 1;
+ psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+ psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+ psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+ psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+ psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+ psStubPBDesc->ui32SubKernelMemInfosCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+ if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to dissociate shared PBDesc "
+ "from process"));
+ goto NoAdd;
+ }
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to register shared PBDesc "
+ " with the resource manager"));
+ goto NoAdd;
+ }
+ psStubPBDesc->hDevCookie = hDevCookie;
+
+
+ List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+ psStubPBDesc);
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+ return PVRSRV_OK;
+
+NoAdd:
+ if(psStubPBDesc)
+ {
+ if(psStubPBDesc->ppsSubKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ psStubPBDesc->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDesc,
+ 0);
+
+ }
+
+NoAddKeepPB:
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+ }
+
+ PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+ return eRet;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
new file mode 100644
index 0000000..bfc726f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
@@ -0,0 +1,143 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle,
+ SGX_CCB_KICK *psCCBKick);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext);
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_IMPORT
+PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 *pui32Old,
+ IMG_BOOL bNew,
+ IMG_UINT32 ui32New,
+ IMG_UINT32 ui32NewReset,
+ IMG_UINT32 ui32CountersReg,
+ IMG_UINT32 ui32Reg2,
+ IMG_BOOL *pbActive,
+ PVRSRV_SGXDEV_DIFF_INFO *psDiffs);
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **psSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount);
+
+
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
new file mode 100644
index 0000000..58415d8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
@@ -0,0 +1,161 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION 1
+#define DEV_MINOR_VERSION 0
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+#if 0 /* ORIGIAL_SGX_MAP */
+ #if defined(SGX_FEATURE_2D_HARDWARE)
+ #define SGX_2D_HEAP_BASE 0x00100000
+ #define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #else
+ #if defined(FIX_HW_BRN_26915)
+ #define SGX_CGBUFFER_HEAP_BASE 0x00100000
+ #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #endif
+ #endif
+
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x08000000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000)
+ #endif
+
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC8000000-0x00001000)
+#else /* EMGD Mapping */
+ /* Leave 0 - 0x10000000 (256MB) untouched */
+ #define SGX_2D_HEAP_BASE 0x10000000
+ #define SGX_2D_HEAP_SIZE (0x08000000-0x00001000)
+
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x18000000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x30000000-0x00001000)
+ #endif
+
+ #define SGX_VIDEO_HEAP_BASE 0x48000000
+ #define SGX_VIDEO_HEAP_SIZE (0x18000000-0x00001000)
+
+ #define SGX_GENERAL_HEAP_BASE 0x60000000
+ #define SGX_GENERAL_HEAP_SIZE (0x78000000-0x00001000)
+
+#else
+
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x18000000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000)
+ #endif
+
+ #define SGX_GENERAL_HEAP_BASE 0x20000000
+ #define SGX_GENERAL_HEAP_SIZE (0xB8000000-0x00001000)
+
+#endif
+
+#endif
+ #define SGX_3DPARAMETERS_HEAP_BASE 0xD8000000
+ #define SGX_3DPARAMETERS_HEAP_SIZE (0x10000000-0x00001000)
+
+ #define SGX_TADATA_HEAP_BASE 0xE8000000
+ #define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0xF5000000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0xF6000000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x02000000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0xF8000000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0xF8400000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x01C00000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE 0xFA000000
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-0x00001000)
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0xFF000000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0xFF800000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
+
+
+ #define SGX_CORE_IDENTIFIED
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x00001000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000)
+ #endif
+
+ #define SGX_GENERAL_HEAP_BASE 0x01800000
+ #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000)
+
+ #define SGX_3DPARAMETERS_HEAP_BASE 0x08800000
+ #define SGX_3DPARAMETERS_HEAP_SIZE (0x04000000-0x00001000)
+
+ #define SGX_TADATA_HEAP_BASE 0x0C800000
+ #define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0x0D800000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x00400000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0x0DC00000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0x0E400000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0x0E800000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE 0x0F000000
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-0x00001000)
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0x0F400000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
+
+
+ #define SGX_CORE_IDENTIFIED
+
+#endif
+
+#if !defined(SGX_CORE_IDENTIFIED)
+ #error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
new file mode 100644
index 0000000..b4fd589
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
@@ -0,0 +1,348 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_HOSTPORT_PRESENT 0x00000001UL
+
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+
+ IMG_UINT8 ui8VersionMajor;
+ IMG_UINT8 ui8VersionMinor;
+ IMG_UINT32 ui32CoreConfig;
+ IMG_UINT32 ui32CoreFlags;
+
+
+ IMG_PVOID pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_PVOID pvHostPortBaseKM;
+
+ IMG_UINT32 ui32HPSize;
+
+ IMG_SYS_PHYADDR sHPSysPAddr;
+#endif
+
+
+ IMG_HANDLE hRegMapping;
+
+
+ IMG_SYS_PHYADDR sRegsPhysBase;
+
+ IMG_UINT32 ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+
+ IMG_UINT32 *pui32ExtSystemCacheRegsPT;
+
+ IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle;
+
+ IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32uKernelTimerClock;
+
+ PVRSRV_STUB_PBDESC *psStubPBDescListKM;
+
+
+
+ IMG_DEV_PHYADDR sKernelPDDevPAddr;
+
+ IMG_VOID *pvDeviceMemoryHeap;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo;
+ PVRSRV_SGX_KERNEL_CCB *psKernelCCB;
+ PPVRSRV_SGX_CCB_INFO psKernelCCBInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo;
+ PVRSRV_SGX_CCB_CTL *psKernelCCBCtl;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo;
+ IMG_UINT32 *pui32KernelCCBEventKicker;
+#if defined(PDUMP)
+ IMG_UINT32 ui32KernelCCBEventKickerDumpVal;
+#endif
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+#if defined(SGX_SUPPORT_HWPROFILING)
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+ IMG_UINT32 ui32KickTACounter;
+ IMG_UINT32 ui32KickTARenderCounter;
+#if defined(SUPPORT_SGX_HWPERF)
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
+ IMG_UINT32 ui32HWGroupRequested;
+ IMG_UINT32 ui32HWReset;
+#endif
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+ PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ PPVRSRV_KERNEL_MEM_INFO psKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ PPVRSRV_KERNEL_MEM_INFO psKernelTmpDPMStateMemInfo;
+#endif
+
+
+ IMG_UINT32 ui32ClientRefCount;
+
+
+ IMG_UINT32 ui32CacheControl;
+
+
+ IMG_UINT32 ui32ClientBuildOptions;
+
+
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+
+
+
+ IMG_VOID *pvMMUContextList;
+
+
+ IMG_BOOL bForcePTOff;
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+#endif
+ SGX_INIT_SCRIPTS sScripts;
+
+
+ IMG_HANDLE hBIFResetPDOSMemHandle;
+ IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPageDevPAddr;
+ IMG_UINT32 *pui32BIFResetPD;
+ IMG_UINT32 *pui32BIFResetPT;
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_HANDLE hBRN22997PTPageOSMemHandle;
+ IMG_HANDLE hBRN22997PDPageOSMemHandle;
+ IMG_DEV_PHYADDR sBRN22997PTDevPAddr;
+ IMG_DEV_PHYADDR sBRN22997PDDevPAddr;
+ IMG_UINT32 *pui32BRN22997PT;
+ IMG_UINT32 *pui32BRN22997PD;
+ IMG_SYS_PHYADDR sBRN22997SysPAddr;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+ IMG_HANDLE hTimer;
+
+ IMG_UINT32 ui32TimeStamp;
+#endif
+
+
+ IMG_UINT32 ui32NumResets;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
+
+ IMG_UINT32 ui32Flags;
+
+ #if defined(PDUMP)
+ PVRSRV_SGX_PDUMP_CONTEXT sPDContext;
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ IMG_VOID *pvDummyPTPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyPTDevPAddr;
+ IMG_HANDLE hDummyPTPageOSMemHandle;
+ IMG_VOID *pvDummyDataPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyDataDevPAddr;
+ IMG_HANDLE hDummyDataPageOSMemHandle;
+#endif
+
+ IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
+
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32HWRecoveryFreq;
+ IMG_BOOL bEnableActivePM;
+ IMG_UINT32 ui32ActivePowManLatencyms;
+ IMG_UINT32 ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+typedef struct _SGX_DEVICE_MAP_
+{
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SYS_PHYADDR sRegsSysPBase;
+ IMG_CPU_PHYADDR sRegsCpuPBase;
+ IMG_CPU_VIRTADDR pvRegsCpuVBase;
+ IMG_UINT32 ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ IMG_SYS_PHYADDR sHPSysPBase;
+ IMG_CPU_PHYADDR sHPCpuPBase;
+ IMG_UINT32 ui32HPSize;
+#endif
+
+
+ IMG_SYS_PHYADDR sLocalMemSysPBase;
+ IMG_DEV_PHYADDR sLocalMemDevPBase;
+ IMG_CPU_PHYADDR sLocalMemCpuPBase;
+ IMG_UINT32 ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+#endif
+
+
+ IMG_UINT32 ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
+ SGX_TIMING_INFORMATION sTimingInfo;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32TotalPBSize;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSubKernelMemInfos;
+ IMG_UINT32 ui32SubKernelMemInfosCount;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_STUB_PBDESC *psNext;
+ PVRSRV_STUB_PBDESC **ppsThis;
+};
+
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+ SGXMKIF_COMMAND *psCommands;
+ IMG_UINT32 *pui32WriteOffset;
+ volatile IMG_UINT32 *pui32ReadOffset;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32StatusRegister,
+ IMG_UINT32 ui32StatusValue,
+ IMG_UINT32 ui32StatusMask)
+{
+ IMG_UINT32 ui32RegVal;
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+ ui32RegVal &= ~ui32StatusMask;
+ ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
new file mode 100644
index 0000000..45c16dc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
@@ -0,0 +1,2267 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+#endif
+
+#define VAR(x) #x
+
+#define CHECK_SIZE(NAME) \
+{ \
+ if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+ { \
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+ VAR(NAME), \
+ psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+ psSGXStructSizes->ui32Sizeof_##NAME )); \
+ bStructSizesFailed = IMG_TRUE; \
+ } \
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+IMG_UINT32 gui32EventStatusServicesByISR = 0;
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (OSInLISR(psDeviceNode->psSysData))
+ {
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#else
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+ {
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+
+ PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ psDevInfo->sScripts = psInitInfo->sScripts;
+
+ psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+ psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+ psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+ psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+ psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+ psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+ psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
+#endif
+
+ psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+
+ psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGX_CCB_INFO),
+ (IMG_VOID **)&psKernelCCBInfo, 0,
+ "SGX Circular Command Buffer Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+ goto failed_allockernelccb;
+ }
+
+
+ OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+ psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
+ psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
+ psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
+ psKernelCCBInfo->pui32WriteOffset = &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+ psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+ psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+
+
+ OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+ SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+ psDevInfo->bForcePTOff = IMG_FALSE;
+
+ psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+ psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+ psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+ psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+ psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+ psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+#endif
+
+
+
+ OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+ return PVRSRV_OK;
+
+failed_allockernelccb:
+ DeinitDevInfo(psDevInfo);
+
+ return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+ IMG_UINT32 ui32PC;
+ SGX_INIT_COMMAND *psComm;
+
+ for (ui32PC = 0, psComm = psScript;
+ ui32PC < ui32NumInitCommands;
+ ui32PC++, psComm++)
+ {
+ switch (psComm->eOp)
+ {
+ case SGX_INIT_OP_WRITE_HW_REG:
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ PDUMPREG(psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ break;
+ }
+#if defined(PDUMP)
+ case SGX_INIT_OP_PDUMP_HW_REG:
+ {
+ PDUMPREG(psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+ break;
+ }
+#endif
+ case SGX_INIT_OP_HALT:
+ {
+ return PVRSRV_OK;
+ }
+ case SGX_INIT_OP_ILLEGAL:
+
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+#if defined(PDUMP)
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+ return (PVRSRV_ERROR_GENERIC);
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+
+ SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+
+
+
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+ PDUMPREG(EUR_CR_POWER, 1);
+#else
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+ PDUMPREG(EUR_CR_POWER, 0);
+#endif
+#endif
+
+
+ *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+ if (bFirstTime)
+ {
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ }
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+ return (PVRSRV_ERROR_GENERIC);
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+
+ psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Reset the SGX microkernel initialisation status\n");
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+#if defined(PDUMP)
+
+
+
+
+
+
+ if (bFirstTime)
+ {
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ PDUMPREG(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "First increment of the SGX event kicker value\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPREG(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+ bFirstTime = IMG_FALSE;
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+
+
+ if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_RETRY;
+ }
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Wait for the SGX microkernel initialisation to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+
+
+ WorkaroundBRN22997ReadHostPort(psDevInfo);
+#endif
+
+ PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+ PVRSRV_ERROR eError;
+
+
+ if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+ return (PVRSRV_ERROR_GENERIC);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hKernelDevMemContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGX Initialisation Part 1");
+
+
+ PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+#ifdef SGX_CORE_REV
+ PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#else
+ PDUMPCOMMENT("SGX Core Revision Information: head rtl");
+#endif
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+ #endif
+ #endif
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ (IMG_VOID **)&psDevInfo, IMG_NULL,
+ "SGX Device Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+
+ psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
+ psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
+
+
+ psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+
+ psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+
+ hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ IMG_NULL,
+ IMG_NULL);
+ if (hKernelDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+
+ for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+ {
+ IMG_HANDLE hDevMemHeap;
+
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+
+ psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+ break;
+ }
+ }
+ }
+
+ eError = MMU_BIFResetPDAlloc(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+ eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+ PDUMPCOMMENT("SGX Initialisation Part 2");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+
+
+ eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+ goto failed_init_dev_info;
+ }
+
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+
+ if (psSGXDeviceMap->pvRegsCpuVBase)
+ {
+ psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+ }
+ else
+ {
+
+ psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+ psSGXDeviceMap->ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvRegsBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+ psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+ psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+ psSGXDeviceMap->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvHostPortBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+ psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+ }
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pvISRData = psDeviceNode;
+
+ PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif
+
+
+ psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+
+ eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+ SGXPrePowerState, SGXPostPowerState,
+ SGXPreClockSpeedChange, SGXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+ return eError;
+ }
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ eError = WorkaroundBRN22997Alloc(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+ psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+ eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+ return eError;
+ }
+#endif
+
+
+
+ OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+ OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+ OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+ PDUMPCOMMENT("Initialise Kernel CCB");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Control");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+ return PVRSRV_OK;
+
+failed_init_dev_info:
+ return eError;
+}
+
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Heap;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+
+ if (!psDevInfo)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_HW_RECOVERY)
+ if (psDevInfo->hTimer)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+ return eError;
+ }
+ psDevInfo->hTimer = IMG_NULL;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+ return eError;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ WorkaroundBRN22997Free(psDevInfo);
+#endif
+
+ MMU_BIFResetPDFree(psDevInfo);
+
+
+
+
+ DeinitDevInfo(psDevInfo);
+
+
+ psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+ for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+ {
+ switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+ {
+ BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+ }
+ break;
+ }
+ }
+ }
+
+
+ eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+ return eError;
+ }
+
+
+ eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+ return eError;
+ }
+
+
+ if (!psSGXDeviceMap->pvRegsCpuVBase)
+ {
+
+ if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32RegSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+ psDevInfo->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+#endif
+
+
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ psDevInfo,
+ 0);
+
+ psDeviceNode->pvDevice = IMG_NULL;
+
+ if (psDeviceMemoryHeap != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ psDeviceMemoryHeap,
+ 0);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXDumpDebugInfo (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_BOOL bDumpSGXRegs)
+{
+ IMG_UINT ui32RegVal;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ if (bDumpSGXRegs)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear): 0x%08X", psDevInfo->pvRegsBaseKM));
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase));
+
+
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ if (ui32RegVal & (EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK | EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK))
+ {
+ PVR_LOG(("DPM out of memory!!"));
+ }
+ PVR_LOG(("EUR_CR_EVENT_STATUS: %x", ui32RegVal));
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ PVR_LOG(("EUR_CR_EVENT_STATUS2: %x", ui32RegVal));
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ PVR_LOG(("EUR_CR_BIF_CTRL: %x", ui32RegVal));
+
+ #if defined(EUR_CR_BIF_BANK0)
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0);
+ PVR_LOG(("EUR_CR_BIF_BANK0: %x", ui32RegVal));
+ #endif
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ PVR_LOG(("EUR_CR_BIF_INT_STAT: %x", ui32RegVal));
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ PVR_LOG(("EUR_CR_BIF_FAULT: %x", ui32RegVal));
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_REQ_STAT);
+ PVR_LOG(("EUR_CR_BIF_MEM_REQ_STAT: %x", ui32RegVal));
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL);
+ PVR_LOG(("EUR_CR_CLKGATECTL: %x", ui32RegVal));
+
+ #if defined(EUR_CR_PDS_PC_BASE)
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_PDS_PC_BASE);
+ PVR_LOG(("EUR_CR_PDS_PC_BASE: %x", ui32RegVal));
+ #endif
+
+
+ }
+
+ #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ {
+ IMG_UINT32 *pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LastStatusCode, ui32WriteOffset;
+
+ ui32LastStatusCode = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+ ui32WriteOffset = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+
+ PVR_LOG(("Last SGX microkernel status code: 0x%x", ui32LastStatusCode));
+
+ #if defined(PVRSRV_DUMP_MK_TRACE)
+
+
+ {
+ IMG_UINT32 ui32LoopCounter;
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+ ui32LoopCounter++)
+ {
+ IMG_UINT32 *pui32BufPtr;
+ pui32BufPtr = pui32MKTraceBuffer +
+ (((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+ PVR_LOG(("(MKT%u) %08X %08X %08X %08X", ui32LoopCounter,
+ pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+ }
+ }
+ #endif
+ }
+ #endif
+
+ {
+
+
+ IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psDevInfo->psSGXHostCtl;
+ IMG_UINT32 ui32LoopCounter;
+
+ PVR_LOG(("SGX Host control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t0x%X: 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+ pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+ pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ {
+
+
+ IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LoopCounter;
+
+ PVR_LOG(("SGX TA/3D control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->ui32AllocSize / sizeof(*pui32TA3DCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t0x%X: 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+ pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+ pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ QueueDumpDebugInfo();
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Component,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+
+
+
+ PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+ return;
+ }
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+ PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+ SGXDumpDebugInfo(psDeviceNode, IMG_TRUE);
+
+
+ PDUMPSUSPEND();
+
+
+ eError = SGXInitialise(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+ }
+
+
+ PDUMPRESUME();
+
+ PVRSRVPowerUnlock(ui32CallerID);
+
+
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+
+
+
+ PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
+}
+#endif
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ static IMG_UINT32 ui32EDMTasks = 0;
+ static IMG_UINT32 ui32LockupCounter = 0;
+ static IMG_UINT32 ui32NumResets = 0;
+ IMG_UINT32 ui32CurrentEDMTasks;
+ IMG_BOOL bLockup = IMG_FALSE;
+ IMG_BOOL bPoweredDown;
+
+
+ psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+ bPoweredDown = IMG_TRUE;
+#else
+ bPoweredDown = SGXIsDevicePowered(psDeviceNode) ? IMG_FALSE : IMG_TRUE;
+#endif
+
+
+
+ if (bPoweredDown)
+ {
+ ui32LockupCounter = 0;
+ }
+ else
+ {
+
+ ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+ if (psDevInfo->ui32EDMTaskReg1 != 0)
+ {
+ ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+ }
+ if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+ (psDevInfo->ui32NumResets == ui32NumResets))
+ {
+ ui32LockupCounter++;
+ if (ui32LockupCounter == 3)
+ {
+ ui32LockupCounter = 0;
+ PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+ bLockup = IMG_TRUE;
+ }
+ }
+ else
+ {
+ ui32LockupCounter = 0;
+ ui32EDMTasks = ui32CurrentEDMTasks;
+ ui32NumResets = psDevInfo->ui32NumResets;
+ }
+ }
+
+ if (bLockup)
+ {
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32HostDetectedLockups ++;
+
+ PVR_LOG(("HWRecoveryResetSGX: From Kernel"));
+
+ HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
+ }
+}
+#endif
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+ IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+
+ {
+ IMG_UINT32 ui32EventStatus, ui32EventEnable;
+ IMG_UINT32 ui32EventClear = 0;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+
+ if(pvData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+ return bInterruptProcessed;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+
+
+ gui32EventStatusServicesByISR = ui32EventStatus;
+
+
+ ui32EventStatus &= ui32EventEnable;
+
+ if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+ {
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+ }
+
+ if (ui32EventClear)
+ {
+ bInterruptProcessed = IMG_TRUE;
+
+
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+ }
+ }
+
+ return bInterruptProcessed;
+}
+
+
+IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+ {
+ PVR_LOG(("HWRecoveryResetSGX: From ISR"));
+ HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+ }
+
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (psDeviceNode->bReProcessDeviceCommandComplete)
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#endif
+
+ SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+}
+#endif
+
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
+ psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
+
+ psDeviceNode->pfnInitDevice = DevInitSGXPart1;
+ psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
+
+
+
+ psDeviceNode->pfnMMUInitialise = MMU_Initialise;
+ psDeviceNode->pfnMMUFinalise = MMU_Finalise;
+ psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
+ psDeviceNode->pfnMMUCreate = MMU_Create;
+ psDeviceNode->pfnMMUDelete = MMU_Delete;
+ psDeviceNode->pfnMMUAlloc = MMU_Alloc;
+ psDeviceNode->pfnMMUFree = MMU_Free;
+ psDeviceNode->pfnMMUMapPages = MMU_MapPages;
+ psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
+ psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
+ psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
+ psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
+ psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+ psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+
+
+ psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
+
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+
+ psDevMemoryInfo->ui32Flags = 0;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+ "Array of Device Memory Heap Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "General";
+ psDeviceMemoryHeap->pszBSName = "General BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "TA Data";
+ psDeviceMemoryHeap->pszBSName = "TA Data BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "Kernel Code";
+ psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "KernelData";
+ psDeviceMemoryHeap->pszBSName = "KernelData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PIXELSHADER_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_VERTEXSHADER_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "CacheCoherent";
+ psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeap->pszName = "3DParameters";
+ psDeviceMemoryHeap->pszBSName = "3DParameters BS";
+#if defined(SUPPORT_PERCONTEXT_PB)
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#else
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "GeneralMapping";
+ psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+
+
+
+
+
+
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#else
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#endif
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "2D";
+ psDeviceMemoryHeap->pszBSName = "2D BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(FIX_HW_BRN_26915)
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "CGBuffer";
+ psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VIDEO_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VIDEO_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_VIDEO_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "Video";
+ psDeviceMemoryHeap->pszBSName = "Video BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+ psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+
+
+ psDevInfo->ui32ClientRefCount++;
+
+#if defined(PDUMP)
+
+ psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+#endif
+
+
+ psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+
+ OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXPanic(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_LOG(("SGX panic"));
+ SGXDumpDebugInfo(psDeviceNode, IMG_FALSE);
+ OSPanic();
+}
+
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch;
+#if !defined(NO_HARDWARE)
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ IMG_BOOL bStructSizesFailed;
+
+
+ IMG_BOOL bCheckCoreRev;
+ const IMG_UINT32 aui32CoreRevExceptions[] =
+ {
+ 0x10100, 0x10101
+ };
+ const IMG_UINT32 ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+ IMG_UINT i;
+#endif
+
+
+ if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto chk_exit;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+
+ ui32BuildOptions = (SGX_BUILD_OPTIONS);
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+ /* Workaround: During development, the DEBUG bit can get out of sync, so
+ * ignore that bit:
+ */
+ if (0x1 & ui32BuildOptions) {
+ psDevInfo->ui32ClientBuildOptions =
+ psDevInfo->ui32ClientBuildOptions | 0x1;
+ } else {
+ psDevInfo->ui32ClientBuildOptions =
+ psDevInfo->ui32ClientBuildOptions & 0xfffffffe;
+ }
+#endif
+ if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ psDevInfo->ui32ClientBuildOptions;
+ if ( (psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+ "extra options present in client-side driver: (0x%lx). Please check sgx_options.h",
+ psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+ }
+
+ if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+ "extra options present in KM: (0x%lx). Please check sgx_options.h",
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Client-side and KM driver build options match. [ OK ]"));
+ }
+
+#if !defined (NO_HARDWARE)
+ psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
+ psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version"));
+ goto chk_exit;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+ if( (psSGXFeatures->ui32DDKVersion !=
+ ((PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH) ) ||
+ (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD) )
+ {
+ PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%ld)/device DDK revision (%ld).",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ PVR_DBG_BREAK;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: driver DDK (%ld) and device DDK (%ld) match. [ OK ]",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+ }
+
+
+ if (psSGXFeatures->ui32CoreRevSW == 0)
+ {
+
+
+ PVR_LOG(("SGXInit: HW core rev (%lx) check skipped.",
+ psSGXFeatures->ui32CoreRev));
+ }
+ else
+ {
+
+ bCheckCoreRev = IMG_TRUE;
+ for(i=0; i<ui32NumCoreExceptions; i+=2)
+ {
+ if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+ (psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1]) )
+ {
+ PVR_LOG(("SGXInit: HW core rev (%lx), SW core rev (%lx) check skipped.",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreRevSW));
+ bCheckCoreRev = IMG_FALSE;
+ }
+ }
+
+ if (bCheckCoreRev)
+ {
+ if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%lx) and SW core rev (%lx).",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%lx) and SW core rev (%lx) match. [ OK ]",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ }
+ }
+ }
+
+
+ psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+ bStructSizesFailed = IMG_FALSE;
+
+ CHECK_SIZE(HOST_CTL);
+ CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ CHECK_SIZE(2DCMD);
+ CHECK_SIZE(2DCMD_SHARED);
+#endif
+ CHECK_SIZE(CMDTA);
+ CHECK_SIZE(CMDTA_SHARED);
+ CHECK_SIZE(TRANSFERCMD);
+ CHECK_SIZE(TRANSFERCMD_SHARED);
+
+ CHECK_SIZE(3DREGISTERS);
+ CHECK_SIZE(HWPBDESC);
+ CHECK_SIZE(HWRENDERCONTEXT);
+ CHECK_SIZE(HWRENDERDETAILS);
+ CHECK_SIZE(HWRTDATA);
+ CHECK_SIZE(HWRTDATASET);
+ CHECK_SIZE(HWTRANSFERCONTEXT);
+
+ if (bStructSizesFailed == IMG_TRUE)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+ }
+
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+ /* Workaround: During development, the DEBUG bit can get out of sync, so
+ * ignore that bit:
+ */
+ if (0x1 & (SGX_BUILD_OPTIONS)) {
+ ui32BuildOptions = psSGXFeatures->ui32BuildOptions | 0x1;
+ } else {
+ ui32BuildOptions = psSGXFeatures->ui32BuildOptions & 0xfffffffe;
+ }
+#else
+ ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
+#endif
+ if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
+ if ( ((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+ "extra options present in driver: (0x%lx). Please check sgx_options.h",
+ (SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch ));
+ }
+
+ if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+ "extra options present in microkernel: (0x%lx). Please check sgx_options.h",
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
+ }
+#endif
+
+ eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+ return PVRSRV_OK;
+#else
+ return eError;
+#endif
+}
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ SGXMKIF_COMMAND sCommandData;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+ if (! psMemInfo->pvLinAddrKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+ psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+ psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+
+ OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+ OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_GETMISCINFO,
+ &sCommandData,
+ KERNEL_ID,
+ 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if !defined(NO_HARDWARE)
+ {
+ IMG_BOOL bExit;
+
+ bExit = IMG_FALSE;
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+ {
+ bExit = IMG_TRUE;
+ break;
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ if (!bExit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext)
+{
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+ IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+
+ *pui32MiscInfoFlags = 0;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+ switch(psMiscInfo->eRequest)
+ {
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+ {
+ IMG_UINT32 ui32RegOffset;
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32BaseRegOffset;
+ IMG_UINT32 ui32BaseRegVal;
+ IMG_UINT32 ui32MaskRegOffset;
+ IMG_UINT32 ui32MaskRegVal;
+
+ switch(psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex)
+ {
+ case 0:
+ ui32RegOffset = EUR_CR_BREAKPOINT0;
+ ui32BaseRegOffset = EUR_CR_BREAKPOINT0_BASE;
+ ui32MaskRegOffset = EUR_CR_BREAKPOINT0_MASK;
+ break;
+ case 1:
+ ui32RegOffset = EUR_CR_BREAKPOINT1;
+ ui32BaseRegOffset = EUR_CR_BREAKPOINT1_BASE;
+ ui32MaskRegOffset = EUR_CR_BREAKPOINT1_MASK;
+ break;
+ case 2:
+ ui32RegOffset = EUR_CR_BREAKPOINT2;
+ ui32BaseRegOffset = EUR_CR_BREAKPOINT2_BASE;
+ ui32MaskRegOffset = EUR_CR_BREAKPOINT2_MASK;
+ break;
+ case 3:
+ ui32RegOffset = EUR_CR_BREAKPOINT3;
+ ui32BaseRegOffset = EUR_CR_BREAKPOINT3_BASE;
+ ui32MaskRegOffset = EUR_CR_BREAKPOINT3_MASK;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"SGXGetMiscInfoKM: SGX_MISC_INFO_REQUEST_SET_BREAKPOINT invalid BP idx %d", psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+ {
+
+ IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+
+
+ ui32MaskRegVal = EUR_CR_BREAKPOINT0_MASK_REGION_MASK | EUR_CR_BREAKPOINT0_MASK_DM_MASK;
+
+
+ ui32BaseRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_BASE_ADDRESS_MASK;
+
+
+ ui32RegVal = EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK
+ | EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK
+ | EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK;
+ }
+ else
+ {
+
+ ui32RegVal = ui32BaseRegVal = ui32MaskRegVal = 0;
+ }
+
+
+
+
+
+
+
+
+
+
+ return PVRSRV_OK;
+ }
+#endif
+
+ case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+ {
+ psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SGXREV:
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%lx, sw ID 0x%lx, sw Rev 0x%lx\n",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreIdSW,
+ psSGXFeatures->ui32CoreRevSW));
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%lx, DDK build 0x%lx\n",
+ psSGXFeatures->ui32DDKVersion,
+ psSGXFeatures->ui32DDKBuild));
+
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+ {
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(PVRSRV_SGX_MISCINFO_INFO));
+
+ psSGXFeatures->ui32DDKVersion =
+ (PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH;
+ psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+
+ psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
+
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ case SGX_MISC_INFO_REQUEST_MEMREAD:
+ {
+ PVRSRV_ERROR eError;
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ PVRSRV_SGX_MISCINFO_MEMREAD *psSGXMemReadData;
+
+ psSGXMemReadData = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemReadData;
+
+
+ *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+
+
+ if(psMiscInfo->hDevMemContext != IMG_NULL)
+ {
+ SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemReadData->sPDDevPAddr);
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if(psMiscInfo->sDevVAddr.uiAddr != 0)
+ {
+ psSGXMemReadData->sDevVAddr = psMiscInfo->sDevVAddr;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+#endif
+
+#ifdef SUPPORT_SGX_HWPERF
+ case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+ {
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ IMG_UINT ui32MatchingFlags;
+
+
+ if ((psMiscInfo->uData.ui32NewHWPerfStatus & ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON | PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ ui32MatchingFlags = psMiscInfo->uData.ui32NewHWPerfStatus & psDevInfo->psSGXHostCtl->ui32HWPerfFlags;
+ if((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON) == 0UL)
+ {
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
+ }
+ if((ui32MatchingFlags & PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL)
+ {
+ psHWPerfCB->ui32OrdinalMK_EXECUTION = 0xffffffffUL;
+ }
+
+
+ psDevInfo->psSGXHostCtl->ui32HWPerfFlags = psMiscInfo->uData.ui32NewHWPerfStatus;
+ #if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX ukernel HWPerf status %lu\n",
+ psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32HWPerfFlags),
+ sizeof(psDevInfo->psSGXHostCtl->ui32HWPerfFlags), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
+ {
+
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
+
+ psDevInfo->psSGXHostCtl->ui32HWPerfFlags |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
+ {
+
+ psDevInfo->psSGXHostCtl->ui32HWPerfFlags = 0;
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
+ {
+
+ SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve = &psMiscInfo->uData.sRetrieveCB;
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ IMG_UINT i;
+
+ for (i = 0; psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < psRetrieve->ui32ArraySize; i++)
+ {
+ SGXMKIF_HWPERF_CB_ENTRY *psData = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+
+
+ psRetrieve->psHWPerfData[i].ui32FrameNo = psData->ui32FrameNo;
+ psRetrieve->psHWPerfData[i].ui32Type = (psData->ui32Type & PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
+ psRetrieve->psHWPerfData[i].ui32StartTime = psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32StartTimeWraps = psData->ui32TimeWraps;
+ psRetrieve->psHWPerfData[i].ui32EndTime = psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32EndTimeWraps = psData->ui32TimeWraps;
+ psRetrieve->psHWPerfData[i].ui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ psRetrieve->psHWPerfData[i].ui32TimeMax = psDevInfo->ui32uKernelTimerClock;
+ psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+ psRetrieve->ui32DataCount = i;
+ psRetrieve->ui32Time = OSClockus();
+ return PVRSRV_OK;
+ }
+#endif
+ case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+ {
+ PVR_LOG(("User requested SGX debug info"));
+
+
+ SGXDumpDebugInfo(psDeviceNode, IMG_FALSE);
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_PANIC:
+ {
+ PVR_LOG(("User requested SGX panic"));
+
+ SGXPanic(psDeviceNode);
+
+ return PVRSRV_OK;
+ }
+
+ default:
+ {
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+}
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_EXPORT
+PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 *pui32Old,
+ IMG_BOOL bNew,
+ IMG_UINT32 ui32New,
+ IMG_UINT32 ui32NewReset,
+ IMG_UINT32 ui32CountersReg,
+ IMG_UINT32 ui32Reg2,
+ IMG_BOOL *pbActive,
+ PVRSRV_SGXDEV_DIFF_INFO *psDiffs)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+ IMG_BOOL bPowered = IMG_FALSE;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+
+ if(bNew)
+ {
+ psDevInfo->ui32HWGroupRequested = ui32New;
+ }
+ psDevInfo->ui32HWReset |= ui32NewReset;
+
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ psDeviceNode->sDevId.ui32DeviceIndex);
+
+ if (psPowerDevice)
+ {
+ bPowered = (IMG_BOOL)(psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON);
+ }
+
+
+
+ *pbActive = bPowered;
+
+
+
+ {
+ IMG_UINT32 ui32rval = 0;
+
+
+ if(bPowered)
+ {
+ IMG_UINT32 i;
+
+
+ *pui32Old = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
+
+ for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
+ {
+ psDiffs->aui32Counters[i] = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32CountersReg + (i * 4));
+ }
+
+ if(ui32Reg2)
+ {
+ ui32rval = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg2);
+ }
+
+
+
+ if (psDevInfo->ui32HWGroupRequested != *pui32Old)
+ {
+
+ if(psDevInfo->ui32HWReset != 0)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg, psDevInfo->ui32HWGroupRequested | psDevInfo->ui32HWReset);
+ psDevInfo->ui32HWReset = 0;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg, psDevInfo->ui32HWGroupRequested);
+ }
+ }
+
+ psDiffs->ui32Time[0] = OSClockus();
+ psDiffs->ui32Time[1] = psDevInfo->psSGXHostCtl->ui32TimeWraps;
+ psDiffs->ui32Time[2] = ui32rval;
+
+ psDiffs->ui32Marker[0] = psDevInfo->ui32KickTACounter;
+ psDiffs->ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
+ }
+
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ SGXTestActivePowerEvent(psDeviceNode, KERNEL_ID);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ IMG_UINT i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+ i++)
+ {
+ SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+ psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+ psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+ psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
+ psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+ psMKPerfEntry->ui32TimeWraps,
+ psMKPerfEntry->ui32Time);
+ OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
+ &psMKPerfEntry->ui32Counters[0],
+ sizeof(psMKPerfEntry->ui32Counters));
+
+ psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+
+ *pui32DataCount = i;
+ *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ *pui32HostTimeStamp = OSClockus();
+
+ return eError;
+}
+#else
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
new file mode 100644
index 0000000..575ca69
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
@@ -0,0 +1,740 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+IMG_EXPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+ SGXMKIF_CMDTA_SHARED *psTACmd;
+ IMG_UINT32 i;
+#if defined(SUPPORT_SGX_HWPERF)
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ if (psCCBKick->bKickRender)
+ {
+ ++psDevInfo->ui32KickTARenderCounter;
+ }
+ ++psDevInfo->ui32KickTACounter;
+#endif
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+ psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->sTA3DDependency.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psTACmd->sTATQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psTACmd->s3DTQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui323DTQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+ if (psCCBKick->ui32NumTAStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+ psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+ if (psCCBKick->ui32Num3DStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs;
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs;
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#else
+
+ psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#endif
+
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+ PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->ui32AllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+ (sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+ psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ 0,
+ sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+#endif
+
+ for (i=0; i<ui32NumDstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+ #if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+ + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+ IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+ IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+
+ PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ ui32SyncOffset,
+ sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32WOpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ ui32ModifiedValue = 0;
+ PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psHWDstSyncListMemInfo,
+ ui32ROpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+ #endif
+ }
+ else
+ {
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+ }
+ }
+ }
+
+
+
+
+ psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("Shared part of TA command\r\n");
+
+ PDUMPMEM(psTACmd,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_CMDTA_SHARED),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+#endif
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+ PDUMPMEM(&psCCBKick->asTAStatusUpdate[i].ui32LastStatusUpdateDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+ PDUMPMEM(&psCCBKick->as3DStatusUpdate[i].ui32LastStatusUpdateDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+ }
+#endif
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+#endif
+ }
+ }
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#endif
+
+ return eError;
+ }
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#else
+
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#endif
+
+ if (psCCBKick->bTerminateOrAbort)
+ {
+ if (psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+
+ for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+ if (psSyncInfo)
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+ }
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+ }
+ }
+#endif
+
+ return eError;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
new file mode 100644
index 0000000..af4d52a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
@@ -0,0 +1,465 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGX_TIMING_INFORMATION *psSGXTimingInfo,
+ IMG_HANDLE *phTimer)
+{
+
+
+
+ *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+ 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+ if(*phTimer == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ SGX_TIMING_INFORMATION sSGXTimingInfo = {0};
+#else
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+#endif
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ SGX_TIMING_INFORMATION *psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ psSGXTimingInfo = &sSGXTimingInfo;
+ SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+ SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32OlduKernelFreq;
+
+ if (psDevInfo->hTimer != IMG_NULL)
+ {
+ ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+ if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+ {
+
+
+ IMG_HANDLE hNewTimer;
+
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+ if (eError == PVRSRV_OK)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+ }
+ psDevInfo->hTimer = hNewTimer;
+ }
+ else
+ {
+
+ }
+ }
+ }
+ else
+ {
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+ psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+ }
+#endif
+
+
+ psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+ psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+
+ psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+ PDUMPCOMMENT("Host Control - Microkernel clock");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ if (psSGXTimingInfo->bEnableActivePM)
+ {
+ ui32ActivePowManSampleRate =
+ psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+
+
+
+
+
+
+
+
+ ui32ActivePowManSampleRate += 1;
+ }
+ else
+ {
+ ui32ActivePowManSampleRate = 0;
+ }
+
+ psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SUPPORT_HW_RECOVERY)
+ PVRSRV_ERROR eError;
+
+ eError = OSEnableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+ }
+ #else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+
+
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Register,
+ IMG_UINT32 ui32RegisterValue,
+ IMG_CHAR *pszComment)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32Register);
+ PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+
+ #if !defined(NO_HARDWARE)
+ PVR_ASSERT(psDevInfo != IMG_NULL);
+
+
+ if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+ 0,
+ ui32RegisterValue,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: %s failed.", pszComment));
+ }
+ #endif
+
+ PDUMPCOMMENT(pszComment);
+ PDUMPREGPOL(ui32Register, 0, ui32RegisterValue);
+}
+
+
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32PowerCmd, ui32CompleteStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+ IMG_UINT32 ui32Core;
+
+ #if defined(SUPPORT_HW_RECOVERY)
+
+ eError = OSDisableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+ return eError;
+ }
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+ PDUMPCOMMENT("SGX power off request");
+ }
+ else
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+ PDUMPCOMMENT("SGX idle request");
+ }
+
+ sCommand.ui32Data[1] = ui32PowerCmd;
+
+ eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+ return eError;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+ PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+ PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT; ui32Core++)
+ {
+
+ SGXPollForClockGating(psDevInfo,
+ SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+ psDevInfo->ui32ClkGateStatusMask,
+ "Wait for SGX clock gating");
+ }
+
+ #if defined(SGX_FEATURE_MP)
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32MasterClkGateStatusReg,
+ psDevInfo->ui32MasterClkGateStatusMask,
+ "Wait for SGX master clock gating");
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ eError = SGXDeinitialise(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %lu", eError));
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32PowerStatus = 0;
+ #if defined(PDUMP)
+ PDUMPCOMMENT("TA/3D CCB Control - Reset power status");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+
+
+ eError = SGXInitialise(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+ return eError;
+ }
+ }
+ else
+ {
+
+
+ SGXMKIF_COMMAND sCommand = {0};
+
+ sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+ eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %lu", eError));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ SGXStartTimer(psDevInfo);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ if (bIdleDevice)
+ {
+
+ PDUMPSUSPEND();
+
+ eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+ PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPRESUME();
+ return eError;
+ }
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %luHz",
+ psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ PVRSRV_ERROR eError;
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+ if (bIdleDevice)
+ {
+
+ eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+ PVRSRV_DEV_POWER_STATE_IDLE);
+
+ PDUMPRESUME();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ else
+ {
+ SGXStartTimer(psDevInfo);
+ }
+
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %luHz to %luHz",
+ ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
new file mode 100644
index 0000000..a746b88
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
@@ -0,0 +1,485 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bResetBIF,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32SoftResetRegVal;
+
+#if defined(SGX_FEATURE_MP)
+ ui32SoftResetRegVal =
+ EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+ if (bResetBIF)
+ {
+ ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+ }
+#endif
+
+ ui32SoftResetRegVal =
+
+ EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_SOFT_RESET_TA_RESET_MASK |
+ EUR_CR_SOFT_RESET_USE_RESET_MASK |
+ EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+ EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ if (bResetBIF)
+ {
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+ }
+}
+
+
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+
+ OSWaitus(1000 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+ if (bPDump)
+ {
+ PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+ PDumpRegRead(EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+ }
+
+
+
+}
+
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32RegVal;
+
+
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+ ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+ }
+#else
+ ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+#endif
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+
+
+
+ if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+ 0,
+ EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+ PVR_DBG_BREAK;
+ }
+
+ if (bPDump)
+ {
+ PDUMPREGPOLWITHFLAGS(EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags);
+ }
+ }
+#endif
+}
+
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags)
+{
+ IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#ifndef PDUMP
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ psDevInfo->ui32NumResets++;
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & ui32BifFaultMask)
+ {
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+ }
+#endif
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#endif
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#if defined(SGX_FEATURE_MP)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#endif
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+ IMG_UINT32 ui32DirList, ui32DirListReg;
+
+ for (ui32DirList = 1;
+ ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+ ui32DirList++)
+ {
+ ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+ PDUMPREGWITHFLAGS(ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+ }
+ }
+#endif
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+
+
+ ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+ (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+ (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#if defined(SGX_FEATURE_MP)
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ #error SGX_BYPASS_SYSTEM_CACHE not supported
+ #else
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+ (0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+ PDUMPREG(EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+ PDUMPREG(EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+ #endif
+#else
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ ui32RegVal = EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK;
+ #else
+ #if defined(FIX_HW_BRN_26620)
+ ui32RegVal = 0;
+ #else
+
+ ui32RegVal = EUR_CR_MNE_CR_CTRL_BYP_CC_MASK;
+ #endif
+ #endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MNE_CR_CTRL, ui32RegVal);
+ PDUMPREG(EUR_CR_MNE_CR_CTRL, ui32RegVal);
+#endif
+#endif
+
+
+
+
+
+
+ ui32RegVal = psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+
+ for (;;)
+ {
+ IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ IMG_DEV_VIRTADDR sBifFault;
+ IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+ if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+ {
+ break;
+ }
+
+
+
+
+ sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+ ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr
+ >>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+ }
+
+
+
+
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+ #if defined(SGX_FEATURE_2D_HARDWARE)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+ #endif
+
+ #if defined(FIX_HW_BRN_23410)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+ #endif
+
+ {
+ IMG_UINT32 ui32EDMDirListReg;
+
+
+ #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+ #else
+
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+ #endif
+
+#if defined(FIX_HW_BRN_28011)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ PDUMPPDREGWITHFLAGS(EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ PDUMPPDREGWITHFLAGS(ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+ }
+
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+ #if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+ #error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+ ui32RegVal = 0;
+#if defined(SGX_FEATURE_MP)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+#endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
new file mode 100644
index 0000000..9899f92
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
@@ -0,0 +1,549 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "regpaths.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+int do_wait_vblank(void *display, int headline, int footline);
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick)
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui32TASyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ else
+ {
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ else
+ {
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+
+ psSharedTransferCmd->ui32SrcWriteOpPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32SrcReadOpPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sSrcWriteOpsCompleteDevAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sSrcReadOpsCompleteDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ }
+
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+
+ psSharedTransferCmd->ui32DstWriteOpPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32DstReadOpPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sDstWriteOpsCompleteDevAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sDstReadOpsCompleteDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ }
+
+
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+
+
+ if (psKick->ui32NumDstSync > 1 || psKick->ui32NumSrcSync > 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Transfer command doesn't support more than 1 sync object per src/dst\ndst: %d, src: %d",
+ psKick->ui32NumDstSync, psKick->ui32NumSrcSync));
+ }
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ PDUMPCOMMENT("Shared part of transfer command\r\n");
+ PDUMPMEM(psSharedTransferCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ if((psKick->ui32NumSrcSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+ PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32SrcWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32SrcReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ }
+ if((psKick->ui32NumDstSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+ {
+ psSyncInfo = psKick->ahDstSyncInfo[0];
+
+ PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32DstWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32DstReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ }
+
+
+ if((psKick->ui32NumSrcSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING)== 0UL))
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+ if((psKick->ui32NumDstSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+ if (psKick->display)
+ do_wait_vblank(psKick->display, psKick->headline, psKick->footline);
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+ }
+#endif
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+ {
+ IMG_UINT32 i;
+
+
+ for(i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ for(i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+#endif
+
+ return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_2DCMD_SHARED *ps2DCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+
+ PDUMPCOMMENT("Shared part of 2D command\r\n");
+ PDUMPMEM(ps2DCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_2DCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+ }
+#endif
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+
+
+
+#if defined(NO_HARDWARE)
+
+ for(i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#endif
+
+ return eError;
+}
+#endif
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
new file mode 100644
index 0000000..8ffa3fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
@@ -0,0 +1,1054 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+#ifdef __linux__
+#include <linux/tty.h>
+#else
+#include <stdio.h>
+#endif
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32NumActivePowerEvents++;
+
+ if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+ {
+
+
+
+ if (ui32CallerID == ISR_ID)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+ }
+}
+
+
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+ {
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+
+ PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+
+
+
+ eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_OK)
+ {
+ SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+ }
+#endif
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+ psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+ eError = PVRSRV_OK;
+ }
+
+
+ PDUMPRESUME();
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu", eError));
+ }
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+ {
+ return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_SGX_CCB_INFO *psKernelCCB;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SGXMKIF_COMMAND *psSGXCommand;
+#if defined(PDUMP)
+ IMG_VOID *pvDumpCommand;
+ IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+
+
+
+
+ if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
+ ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+ ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+ {
+ #if defined(PDUMP)
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ #endif
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ SGXMKIF_COMMAND sCacheCommand = {0};
+
+ eError = SGXScheduleCCBCommand(psDevInfo,
+ SGXMKIF_CMD_PROCESS_QUEUES,
+ &sCacheCommand,
+ ui32CallerID,
+ ui32PDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ 2 * MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+
+ #if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+ {
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ }
+ #endif
+ }
+#endif
+
+ psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+ psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+
+ if(!psSGXCommand)
+ {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+
+
+ psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+ psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+
+ psDevInfo->ui32CacheControl = 0;
+
+
+ *psSGXCommand = *psCommandData;
+
+ if (eCmdType >= SGXMKIF_CMD_MAX)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM: Unknown command type: %d", eCmdType)) ;
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+ }
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+ {
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ if (psSysData->bFlushAll)
+ {
+ OSFlushCPUCacheKM();
+
+ psSysData->bFlushAll = IMG_FALSE;
+ }
+ }
+#endif
+
+ psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+ {
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+ 0xff,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command\r\n");
+ pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+ PDUMPMEM(pvDumpCommand,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+ sizeof(SGXMKIF_COMMAND),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+
+ PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+ offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+
+ psDevInfo->sPDContext.ui32CacheControl = 0;
+ }
+ }
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+ *psKernelCCB->pui32WriteOffset,
+ 0xFF,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT);
+ if (eError != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+#endif
+
+
+
+ *psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+ {
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff),
+ 0xFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ #endif
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+ }
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+ PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+ psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+ #else
+ PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+ #endif
+ }
+#endif
+
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+#if defined(NO_HARDWARE)
+
+ *psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+
+ PDUMPSUSPEND();
+
+
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ ui32CallerID,
+ IMG_TRUE);
+
+ PDUMPRESUME();
+
+ if (eError == PVRSRV_OK)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+ }
+ else
+ {
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (ui32CallerID == ISR_ID)
+ {
+
+
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ eError = PVRSRV_OK;
+ }
+ else
+ {
+
+
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%ld eError:%lu", ui32CallerID, eError));
+ }
+
+ return eError;
+ }
+
+ eError = SGXScheduleCCBCommand(psDevInfo, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags);
+
+ PVRSRVPowerUnlock(ui32CallerID);
+
+ if (ui32CallerID != ISR_ID)
+ {
+
+
+
+ SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
+ }
+
+ return eError;
+}
+
+
+#define print_error(function, variable)\
+{\
+ printk(KERN_ERR "ERROR!\nERROR!\nERROR!\n");\
+ printk(KERN_ERR "ERROR: %s() about to dereference a NULL pointer!\n", function);\
+ printk(KERN_ERR " %s is NULL\n", variable);\
+ printk(KERN_ERR " The client-side program needs to call SrvInit()\n");\
+ printk(KERN_ERR " Working-around error by exiting the function early\n");\
+}
+
+
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ /* Note: If the client-side code doesn't call SrvInit(), the normal
+ * implementation of this function will chase a NULL pointer. The
+ * workaround is to use an extra set of curly braces, and then to check the
+ * pointers normally used during the variable initialization code. if a
+ * problem is found, exit early and provide a helpful error message in the
+ * kernel log file.
+ */
+ if (NULL == psDeviceNode) {
+ print_error(__FUNCTION__, "psDeviceNode");
+ return PVRSRV_OK;
+ } else {
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ if (NULL == psDevInfo) {
+ print_error(__FUNCTION__, "psDevInfo");
+ return PVRSRV_OK;
+ }
+ if (NULL == psDevInfo->psKernelSGXHostCtlMemInfo) {
+ print_error(__FUNCTION__, "psDevInfo->psKernelSGXHostCtlMemInfo");
+ return PVRSRV_OK;
+ }
+ if (NULL == psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM) {
+ print_error(__FUNCTION__,
+ "psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM");
+ return PVRSRV_OK;
+ }
+ }
+ /* Below starts the extra set of curly-braces, and the original function: */
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32PowerStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+
+ ui32PowerStatus = psHostCtl->ui32PowerStatus;
+ if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %lu", eError));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+}
+
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+ psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+
+ psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+ (IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType)
+{
+ /* Note: If the client-side code doesn't call SrvInit(), the normal
+ * implementation of this function will chase a NULL pointer. The
+ * workaround is to use an extra set of curly braces, and then to check the
+ * pointers normally used during the variable initialization code. if a
+ * problem is found, exit early and provide a helpful error message in the
+ * kernel log file.
+ */
+ if (NULL == psDeviceNode) {
+ print_error(__FUNCTION__, "psDeviceNode");
+ return;
+ } else {
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo = psDeviceNode->pvDevice;
+ if (NULL == psSGXDevInfo) {
+ print_error(__FUNCTION__, "psSGXDevInfo");
+ return;
+ }
+ if (NULL == psSGXDevInfo->psKernelSGXHostCtlMemInfo) {
+ print_error(__FUNCTION__,"psSGXDevInfo->psKernelSGXHostCtlMemInfo");
+ return;
+ } else {
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo =
+ psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+ if (NULL == psSGXHostCtlMemInfo->pvLinAddrKM) {
+ print_error(__FUNCTION__, "psSGXHostCtlMemInfo->pvLinAddrKM");
+ return;
+ }
+ }
+ }
+ /* Below starts the extra set of curly-braces, and the original function: */
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+
+ if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ {
+
+ }
+ else
+ {
+ SGXMKIF_COMMAND sCommand = {0};
+
+ PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resouce clean-up");
+ sCommand.ui32Data[0] = ui32CleanupType;
+ sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+ PVR_DBG_BREAK;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psSGXHostCtl->ui32CleanupStatus,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up failed"));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ #endif
+
+ psSGXHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ psSGXDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+ #else
+ psSGXDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+ #endif
+ }
+}
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWRenderContextDevVAddr,
+ PVRSRV_CLEANUPCMD_RC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWTransferContextDevVAddr,
+ PVRSRV_CLEANUPCMD_TC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Render Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ (IMG_VOID *)psCleanup,
+ 0,
+ &SGXCleanupHWRenderContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Transfer Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHWTransferContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHW2DContextDevVAddr,
+ PVRSRV_CLEANUPCMD_2DC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware 2D Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHW2DContextDevVAddr = *psHW2DContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHW2DContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+ if (hHW2DContext == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32ReadOpsPending,
+ IMG_UINT32 ui32WriteOpsPending)
+{
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ return (IMG_BOOL)(
+ (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+ (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+ );
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete)
+{
+ IMG_UINT32 ui32ReadOpsPending, ui32WriteOpsPending;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+
+ if (!bWaitForComplete)
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: %p, Syncdata: %p", psSyncInfo, psSyncData));
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+ }
+#endif
+
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode, IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
+{
+ PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+ SGXCleanupRequest(psDeviceNode,
+ &sHWRTDataSetDevVAddr,
+ PVRSRV_CLEANUPCMD_RT);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+ return ui32Time;
+#else
+ IMG_UINT64 ui64Clocks;
+ IMG_UINT32 ui32Clocksx16;
+
+ ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+ (psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+ ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+ return ui32Clocksx16;
+#endif
+}
+
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
new file mode 100644
index 0000000..ead8d56
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "perproc.h"
+#include "sgxinfokm.h"
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+ ((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \
+ ((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type)))
+
+#define CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+ ((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+ (psCCBKick)->offset))
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo, IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time);
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType);
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
new file mode 100644
index 0000000..a16a2fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
@@ -0,0 +1,62 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+typedef struct _PVR_PCI_DEV_TAG
+{
+ struct pci_dev *psPCIDev;
+ HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+ IMG_VOID *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+ IMG_BOOL bLISRInstalled;
+ IMG_BOOL bMISRInstalled;
+ IMG_UINT32 ui32IRQ;
+ IMG_VOID *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct work_struct sMISRWork;
+ IMG_VOID *pvMISRData;
+#else
+ struct tasklet_struct sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
new file mode 100644
index 0000000..c9fbad9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+ IMG_HANDLE hBlockAlloc;
+ struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
new file mode 100644
index 0000000..1a928d1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
@@ -0,0 +1,272 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+#include <asm/exec.h>
+#include <asm/cmpxchg.h>
+#include <asm/auxvec.h>
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+ rwlock_t sLock;
+ struct list_head sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+ atomic_t sTimeStamp;
+ IMG_UINT32 ui32TimeStampPrevious;
+#if defined(DEBUG)
+ IMG_UINT ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ IMG_HANDLE hResItem;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ (IMG_VOID **)&psEvenObjectList, IMG_NULL,
+ "Linux Event Object List") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+ rwlock_init(&psEvenObjectList->sLock);
+
+ *phEventObjectList = (IMG_HANDLE *) psEvenObjectList;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+ if(psEvenObjectList)
+ {
+ if (!list_empty(&psEvenObjectList->sList))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEvenObjectList, IMG_NULL);
+
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+ if(hOSEventObjectList)
+ {
+ if(hOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+ if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+ }
+ }
+ return PVRSRV_ERROR_GENERIC;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+ (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+ "Linux Event Object") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT,
+ psLinuxEventObject,
+ 0,
+ &LinuxEventObjectDeleteCallback);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ struct list_head *psListEntry, *psListEntryTemp, *psList;
+ psList = &psLinuxEventObjectList->sList;
+
+ read_lock(&psLinuxEventObjectList->sLock);
+ list_for_each_safe(psListEntry, psListEntryTemp, psList)
+ {
+
+ psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+ read_unlock(&psLinuxEventObjectList->sLock);
+
+ return PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+ IMG_UINT32 ui32TimeStamp;
+ DEFINE_WAIT(sWait);
+
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+ IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ do
+ {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+ ui32TimeStamp = atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ {
+ break;
+ }
+
+ mutex_unlock(&gPVRSRVLock);
+
+ ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+ mutex_lock(&gPVRSRVLock);
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
new file mode 100644
index 0000000..908014e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
new file mode 100644
index 0000000..887689f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
@@ -0,0 +1,151 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+
+MODULE ?= pvrsrvkm
+
+MODULE_CFLAGS =
+
+ifeq ($(PVR_KBUILD_IN_KERNEL),1)
+# PVRKROOT is the relative path to the PVR sources.
+# DRVKROOT should point to the non-PVR sources, if any.
+PVRKROOT ?= .
+KBUILDROOT = $(PVRKROOT)/services4
+else
+KBUILDROOT = ../../../..
+endif
+
+clean-dirs :=
+
+INCLUDES = -I$(EURASIAROOT)/include4 \
+ -I$(EURASIAROOT)/services4/include \
+ -I$(EURASIAROOT)/services4/srvkm/env/linux \
+ -I$(EURASIAROOT)/services4/srvkm/include \
+ -I$(EURASIAROOT)/services4/srvkm/bridged \
+ -I$(EURASIAROOT)/services4/system/include \
+ -I$(EURASIAROOT)/services4/system/plb \
+ -I$(EURASIAROOT)/services4/system/tnc
+
+
+SOURCES = $(KBUILDROOT)/srvkm/env/linux/osfunc.c \
+ $(KBUILDROOT)/srvkm/env/linux/mutils.c \
+ $(KBUILDROOT)/srvkm/env/linux/mmap.c \
+ $(KBUILDROOT)/srvkm/env/linux/module.c \
+ $(KBUILDROOT)/srvkm/env/linux/pdump.c \
+ $(KBUILDROOT)/srvkm/env/linux/proc.c \
+ $(KBUILDROOT)/srvkm/env/linux/pvr_bridge_k.c \
+ $(KBUILDROOT)/srvkm/env/linux/pvr_debug.c \
+ $(KBUILDROOT)/srvkm/env/linux/mm.c \
+ $(KBUILDROOT)/srvkm/env/linux/mutex.c \
+ $(KBUILDROOT)/srvkm/env/linux/event.c \
+ $(KBUILDROOT)/srvkm/env/linux/osperproc.c
+
+SOURCES += $(KBUILDROOT)/srvkm/common/buffer_manager.c \
+ $(KBUILDROOT)/srvkm/common/devicemem.c \
+ $(KBUILDROOT)/srvkm/common/deviceclass.c \
+ $(KBUILDROOT)/srvkm/common/handle.c \
+ $(KBUILDROOT)/srvkm/common/hash.c \
+ $(KBUILDROOT)/srvkm/common/metrics.c \
+ $(KBUILDROOT)/srvkm/common/pvrsrv.c \
+ $(KBUILDROOT)/srvkm/common/queue.c \
+ $(KBUILDROOT)/srvkm/common/ra.c \
+ $(KBUILDROOT)/srvkm/common/resman.c \
+ $(KBUILDROOT)/srvkm/common/power.c \
+ $(KBUILDROOT)/srvkm/common/mem.c \
+ $(KBUILDROOT)/srvkm/common/pdump_common.c \
+ $(KBUILDROOT)/srvkm/bridged/bridged_support.c \
+ $(KBUILDROOT)/srvkm/bridged/bridged_pvr_bridge.c \
+ $(KBUILDROOT)/srvkm/common/perproc.c \
+ $(KBUILDROOT)/../services4/system/plb/sysconfig.c \
+ $(KBUILDROOT)/../services4/system/tnc/sysconfig.c \
+ $(KBUILDROOT)/../services4/system/common/sysconfig.c \
+ $(KBUILDROOT)/../services4/system/common/sysutils.c \
+ $(KBUILDROOT)/srvkm/common/lists.c \
+ $(KBUILDROOT)/srvkm/common/mem_debug.c
+
+INCLUDES += -I$(EURASIAROOT)/services4/srvkm/hwdefs
+
+SYM_VERS_DEPS = $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux
+
+
+#
+# Device dependent
+#
+
+ifeq ($(SUPPORT_SGX), 1)
+
+INCLUDES += -I$(EURASIAROOT)/services4/srvkm/bridged/sgx \
+ -I$(EURASIAROOT)/services4/srvkm/devices/sgx
+
+SOURCES += $(KBUILDROOT)/srvkm/bridged/sgx/bridged_sgx_bridge.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxinit.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxpower.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxreset.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxutils.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxkick.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/sgxtransfer.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/mmu.c \
+ $(KBUILDROOT)/srvkm/devices/sgx/pb.c
+
+else
+
+ifeq ($(SUPPORT_VGX), 1)
+
+INCLUDES += -I$(EURASIAROOT)/services4/srvkm/bridged/vgx \
+ -I$(EURASIAROOT)/services4/srvkm/devices/vgx
+
+#FIXME: We need to cerate a subset of vgxdefs.h from $(EURASIAROOT)/hwdefs
+# and put it into srvkm/hwdefs for GPL compliance
+INCLUDES += -I$(EURASIAROOT)/hwdefs
+
+SOURCES += $(KBUILDROOT)/srvkm/bridged/vgx/bridged_vgx_bridge.c \
+ $(KBUILDROOT)/srvkm/devices/vgx/vgxinit.c \
+ $(KBUILDROOT)/srvkm/devices/vgx/vgxreset.c \
+ $(KBUILDROOT)/srvkm/devices/vgx/mmu.c \
+ $(KBUILDROOT)/srvkm/devices/vgx/pb.c \
+ $(KBUILDROOT)/srvkm/env/linux/pdump_vgx.c
+endif
+
+endif # SUPPORT_SGX
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+ SOURCES += $(KBUILDROOT)/srvkm/env/linux/pvr_drm.c
+ INCLUDES += -I$(KERNELDIR)/include/drm \
+ -I$(EURASIAROOT)/services4/include/env/linux
+
+ifneq ("$(DISPLAY_CONTROLLER_DIR)","")
+include $(EURASIAROOT)/services4/$(DISPLAY_CONTROLLER_DIR)/makefile.linux.common
+endif
+
+ifeq ($(PDUMP),1)
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
+endif
+
+endif
+
+ifeq ($(PVR_MODULE_TEST),1)
+INCLUDES += -I$(EURASIAROOT)/moduletests/include
+SOURCES += $(KBUILDROOT)/../moduletests/services_test/kern_test.c
+SYS_CFLAGS += -DMODULE_TEST
+endif
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
new file mode 100644
index 0000000..a124f78
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_INT32 PVRSRV_BridgeDispatchKM(struct file *file, IMG_UINT cmd, IMG_UINT32 arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+
+#endif
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
new file mode 100644
index 0000000..4a18e01
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+extern struct mutex gPVRSRVLock;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
new file mode 100644
index 0000000..8844f0a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
@@ -0,0 +1,2377 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "sysconfig.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ #include "lists.h"
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ DEBUG_MEM_ALLOC_TYPE_IO,
+ DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_COUNT
+}DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+ IMG_VOID *pvCpuVAddr;
+ IMG_UINT32 ulCpuPAddr;
+ IMG_VOID *pvPrivateData;
+ IMG_UINT32 ui32Bytes;
+ pid_t pid;
+ IMG_CHAR *pszFileName;
+ IMG_UINT32 ui32Line;
+
+ struct _DEBUG_MEM_ALLOC_REC *psNext;
+ struct _DEBUG_MEM_ALLOC_REC **ppsThis;
+}DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static IMG_UINT32 g_SysRAMWaterMark;
+static IMG_UINT32 g_SysRAMHighWaterMark;
+
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#else
+static off_t printMemoryRecords(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32Flags;
+ pid_t pid;
+
+ struct _DEBUG_LINUX_MEM_AREA_REC *psNext;
+ struct _DEBUG_LINUX_MEM_AREA_REC **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static struct mutex g_sDebugMutex;
+#endif
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_SeqFileMemArea=0;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+
+#else
+static off_t printLinuxMemAreaRecords(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+#endif
+
+static LinuxKMemCache *psLinuxMemAreaCache;
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ mutex_init(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_SeqFileMemArea = CreateProcReadEntrySeq(
+ "mem_areas",
+ NULL,
+ ProcSeqNextMemArea,
+ ProcSeqShowMemArea,
+ ProcSeqOff2ElementMemArea,
+ ProcSeqStartstopDebugMutex
+ );
+ iStatus = !g_SeqFileMemArea ? -1 : 0;
+#else
+ iStatus = CreateProcReadEntry("mem_areas", printLinuxMemAreaRecords);
+#endif
+ if(iStatus!=0)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
+ "meminfo",
+ NULL,
+ ProcSeqNextMemoryRecords,
+ ProcSeqShowMemoryRecords,
+ ProcSeqOff2ElementMemoryRecords,
+ ProcSeqStartstopDebugMutex
+ );
+
+ iStatus = !g_SeqFileMemoryRecords ? -1 : 0;
+#else
+ iStatus = CreateProcReadEntry("meminfo", printMemoryRecords);
+#endif
+ if(iStatus!=0)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+
+ psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+ if(!psLinuxMemAreaCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%ld bytes",
+ __FUNCTION__,
+ psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+ psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s "
+ "CpuVAddr=%p "
+ "CpuPAddr=0x%08lx, "
+ "allocated @ file=%s,line=%d",
+ __FUNCTION__,
+ DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line));
+ switch(psCurrentRecord->eAllocType)
+ {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+ VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+ KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+ break;
+ default:
+ PVR_ASSERT(0);
+ }
+}
+#endif
+
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ if(g_LinuxMemAreaCount)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%ld bytes)",
+ __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+ }
+
+ List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
+ LinuxMMCleanup_MemAreas_ForEachCb);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_SeqFileMemArea );
+#else
+ RemoveProcEntry("mem_areas");
+#endif
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+
+
+ List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
+ LinuxMMCleanup_MemRecords_ForEachVa);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_SeqFileMemoryRecords );
+#else
+ RemoveProcEntry("meminfo");
+#endif
+
+ }
+#endif
+
+ if(psLinuxMemAreaCache)
+ {
+ KMemCacheDestroyWrapper(psLinuxMemAreaCache);
+ psLinuxMemAreaCache=NULL;
+ }
+}
+
+
+IMG_VOID *
+_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+ pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ ui32ByteSize,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ return pvRet;
+}
+
+
+IMG_VOID
+_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+ psRecord->eAllocType = eAllocType;
+ psRecord->pvKey = pvKey;
+ psRecord->pvCpuVAddr = pvCpuVAddr;
+ psRecord->ulCpuPAddr = ulCpuPAddr;
+ psRecord->pvPrivateData = pvPrivateData;
+ psRecord->pid = current->pid;
+ psRecord->ui32Bytes = ui32Bytes;
+ psRecord->pszFileName = pszFileName;
+ psRecord->ui32Line = ui32Line;
+
+ List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+
+ g_WaterMarkData[eAllocType] += ui32Bytes;
+ if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ {
+ g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+ }
+
+ if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark += ui32Bytes;
+ if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+ {
+ g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+ }
+ }
+ else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark += ui32Bytes;
+ if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+ {
+ g_IOMemHighWaterMark = g_IOMemWaterMark;
+ }
+ }
+
+ mutex_unlock(&g_sDebugMutex);
+}
+
+
+IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+
+ eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+ pvKey = va_arg(va, IMG_VOID*);
+
+ if(psCurrentRecord->eAllocType == eAllocType
+ && psCurrentRecord->pvKey == pvKey)
+ {
+ eAllocType = psCurrentRecord->eAllocType;
+ g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+
+ if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+ else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+
+ List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ return IMG_FALSE;
+ }
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ mutex_lock(&g_sDebugMutex);
+
+
+ if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+ DebugMemAllocRecordRemove_AnyVaCb,
+ eAllocType,
+ pvKey))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+ __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ pszFileName, ui32Line));
+ }
+
+ mutex_unlock(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+ IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+ "KMALLOC",
+ "VMALLOC",
+ "ALLOC_PAGES",
+ "IOREMAP",
+ "IO",
+ "KMEM_CACHE_ALLOC"
+ };
+ return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ PGProtFlags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "VMAllocWrapper: unknown mapping flags=0x%08lx",
+ ui32AllocFlags));
+ dump_stack();
+ return NULL;
+ }
+
+
+ pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vfree(pvCpuVAddr);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_VOID *pvCpuVAddr;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ goto failed;
+ }
+
+ pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+ if(!pvCpuVAddr)
+ {
+ goto failed;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+ ReservePages(pvCpuVAddr, ui32Bytes);
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+ psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+ if(psLinuxMemArea)
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+ PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+ UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+ psLinuxMemArea->ui32ByteSize);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+ __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+ VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID
+ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+ IMG_VOID *pvPage;
+ IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+ for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
+ {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(vmalloc_to_page(pvPage));
+#else
+ mem_map_reserve(vmalloc_to_page(pvPage));
+#endif
+ }
+}
+
+
+static IMG_VOID
+UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+ IMG_VOID *pvPage;
+ IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+ for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
+ {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(vmalloc_to_page(pvPage));
+#else
+ mem_map_unreserve(vmalloc_to_page(pvPage));
+#endif
+ }
+}
+#endif
+
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvIORemapCookie;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+ return NULL;
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvIORemapCookie)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ pvIORemapCookie,
+ pvIORemapCookie,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_VOID *pvIORemapCookie;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+ if(!pvIORemapCookie)
+ {
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+ psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+ psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+ IMG_UINT32 ui32;
+ IMG_UINT32 ui32AddrChk;
+ IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+ {
+ if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+ {
+ break;
+ }
+ }
+ if (ui32 == ui32NumPages)
+ {
+ return IMG_FALSE;
+ }
+
+ if (!bPhysContig)
+ {
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+ psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+ psLinuxMemArea->uData.sExternalKV.bPhysContig = (IMG_BOOL)(bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig));
+
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+ }
+ else
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+ }
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+ psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)BasePAddr.uiAddr,
+ 0,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ "unknown",
+ 0
+ );
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32PageCount;
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ goto failed_area_alloc;
+ }
+
+ ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+ eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
+ "Array of pages");
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_page_list_alloc;
+ }
+
+ for(i=0; i<(IMG_INT32)ui32PageCount; i++)
+ {
+ pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if(!pvPageList[i])
+ {
+ goto failed_alloc_pages;
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(pvPageList[i]);
+#else
+ mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ pvPageList,
+ 0,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ "unknown",
+ 0
+ );
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+ psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
+ {
+ __free_pages(pvPageList[i], 0);
+ }
+ (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+ psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+failed_page_list_alloc:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+
+ return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 ui32PageCount;
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i;
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+ hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
+#endif
+
+ for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(pvPageList[i]);
+#else
+ mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+ __free_pages(pvPageList[i], 0);
+ }
+
+ (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+ psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32PageIndex;
+ IMG_CHAR *pui8Addr;
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+
+ case LINUX_MEM_AREA_VMALLOC:
+ pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pui8Addr += ui32ByteOffset;
+ return vmalloc_to_page(pui8Addr);
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+ __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+ return NULL;
+ }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+ size_t Size,
+ size_t Align,
+ IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+ ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+ return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ , NULL
+#endif
+ );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+ kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+ gfp_t Flags,
+#else
+ IMG_INT Flags,
+#endif
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+
+ pvRet = kmem_cache_alloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ pvRet,
+ pvRet,
+ 0,
+ psCache,
+ kmem_cache_size(psCache),
+ pszFileName,
+ ui32Line
+ );
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+ PVR_UNREFERENCED_PARAMETER(psCache);
+
+
+ return "";
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+ psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+ psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+ }
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+#if 0
+ LinuxMemArea *psLinuxMemArea;
+ psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+ printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+ dump_stack();
+ return psLinuxMemArea;
+#else
+ return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+ KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
+
+
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ FreeVMallocLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ FreeExternalKVLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IO:
+ FreeIOLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ FreeSubLinuxMemArea(psLinuxMemArea);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+ const IMG_CHAR *pi8FlagsString;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+ if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ {
+ g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+ }
+ }
+ g_LinuxMemAreaCount++;
+
+
+ psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+ if(psNewRecord)
+ {
+
+ psNewRecord->psLinuxMemArea = psLinuxMemArea;
+ psNewRecord->ui32Flags = ui32Flags;
+ psNewRecord->pid = current->pid;
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed to allocate linux memory area record.",
+ __FUNCTION__));
+ }
+
+
+ pi8FlagsString = HAPFlagsToString(ui32Flags);
+ if(strstr(pi8FlagsString, "UNKNOWN"))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unexpected flags (0x%08lx) associated with psLinuxMemArea @ 0x%08lx",
+ __FUNCTION__,
+ ui32Flags,
+ psLinuxMemArea));
+
+ }
+
+ mutex_unlock(&g_sDebugMutex);
+}
+
+
+
+IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+ va_list va)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = va_arg(va, LinuxMemArea*);
+ if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ {
+ return psCurrentRecord;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ mutex_lock(&g_sDebugMutex);
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+
+ mutex_unlock(&g_sDebugMutex);
+
+ return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+ }
+ g_LinuxMemAreaCount--;
+
+
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+ if(psCurrentRecord)
+ {
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+ __FUNCTION__, psLinuxMemArea));
+ }
+
+ mutex_unlock(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ case LINUX_MEM_AREA_IOREMAP:
+ return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ IMG_CHAR *pAddr =
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+ if(!pAddr)
+ {
+ return NULL;
+ }
+ return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = 0;
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ }
+ else
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ if (0 == CpuPAddr.uiAddr) {
+ /* FIXME: REPLACE THIS WITH A DIFFERENT FIX SOMEDAY.
+ * has only seen this code path be triggered when
+ * DestroyOffsetStruct() calls this as a parameter for a debug
+ * statement. The times its been seen has been when the user-mode
+ * program (i.e. X server) crashed when doing mode changes, or was
+ * killed after an unhealthy mode change, and the kernel was trying
+ * to clean up all of the VMA's associated with that client. For
+ * now, don't leave the address as 0 (which causes an Oops), but
+ * work-around this by setting the CpuPAddr.uiAddr to 7. As long
+ * as 7 is used for a debug statement, it's no big deal. If 7 were
+ * used as a real address, an Oops would be caused anyway.
+ */
+ printk(KERN_ERR "ERROR DESCRIPTION TO FOLLOW:\n");
+ printk(KERN_ERR " LinuxMemAreaToCpuPAddr() failed to look up a "
+ "physical\n address of a memory mapped area (i.e. got an "
+ "address\n of 0x00000000). If this occured after increasing "
+ "the\n resolution of a display, it probably indicates that "
+ "the\n client stepped past the end of the old frame buffer's\n"
+ " memory, and needed to re-initialize its connection with\n"
+ " PVR services in order to map the new frame buffer address."
+ "\n\n");
+ CpuPAddr.uiAddr = 7;
+ }
+ }
+ break;
+ }
+ case LINUX_MEM_AREA_IO:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ IMG_CHAR *pCpuVAddr;
+ pCpuVAddr =
+ (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pCpuVAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+ break;
+ }
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ struct page *page;
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ CpuPAddr.uiAddr = page_to_phys(page);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+
+ PVR_ASSERT(CpuPAddr.uiAddr);
+ return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_IO:
+ return IMG_TRUE;
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ case LINUX_MEM_AREA_VMALLOC:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return IMG_FALSE;
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+ return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+ switch(eMemAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ return "LINUX_MEM_AREA_IOREMAP";
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return "LINUX_MEM_AREA_EXTERNAL_KV";
+ case LINUX_MEM_AREA_IO:
+ return "LINUX_MEM_AREA_IO";
+ case LINUX_MEM_AREA_VMALLOC:
+ return "LINUX_MEM_AREA_VMALLOC";
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return "LINUX_MEM_AREA_SUB_ALLOC";
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return "LINUX_MEM_AREA_ALLOC_PAGES";
+ default:
+ PVR_ASSERT(0);
+ }
+
+ return "";
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
+{
+ if(start)
+ {
+ mutex_lock(&g_sDebugMutex);
+ }
+ else
+ {
+ mutex_unlock(&g_sDebugMutex);
+ }
+}
+#endif
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ seq_printf( sfile,
+ "Number of Linux Memory Areas: %lu\n"
+ "At the current water mark these areas correspond to %lu bytes (excluding SUB areas)\n"
+ "At the highest water mark these areas corresponded to %lu bytes (excluding SUB areas)\n"
+ "\nDetails for all Linux Memory Areas:\n"
+ "%s %-24s %s %s %-8s %-5s %s\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark,
+ "psLinuxMemArea",
+ "LinuxMemType",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "Pid",
+ "Flags"
+ );
+#else
+ seq_printf( sfile,
+ "<mem_areas_header>\n"
+ "\t<count>%lu</count>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%lu\"/>\n"
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%lu\"/>\n"
+ "</mem_areas_header>\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark
+ );
+#endif
+ return;
+ }
+
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%8p %-24s %8p %08lx %-8ld %-5u %08lx=(%s)\n",
+#else
+ "<linux_mem_area>\n"
+ "\t<pointer>%8p</pointer>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%u</pid>\n"
+ "\t<flags>%08lx</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</linux_mem_area>\n",
+#endif
+ psRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+ LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+ psRecord->psLinuxMemArea->ui32ByteSize,
+ psRecord->pid,
+ psRecord->ui32Flags,
+ HAPFlagsToString(psRecord->ui32Flags)
+ );
+
+}
+
+#else
+
+static off_t
+printLinuxMemAreaRecords(IMG_CHAR * buffer, size_t count, off_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ off_t Ret;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if(!off)
+ {
+ if(count < 500)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ Ret = printAppend(buffer, count, 0,
+ "Number of Linux Memory Areas: %lu\n"
+ "At the current water mark these areas correspond to %lu bytes (excluding SUB areas)\n"
+ "At the highest water mark these areas corresponded to %lu bytes (excluding SUB areas)\n"
+ "\nDetails for all Linux Memory Areas:\n"
+ "%s %-24s %s %s %-8s %-5s %s\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark,
+ "psLinuxMemArea",
+ "LinuxMemType",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "Pid",
+ "Flags"
+ );
+#else
+ Ret = printAppend(buffer, count, 0,
+ "<mem_areas_header>\n"
+ "\t<count>%lu</count>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%lu\"/>\n"
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%lu\"/>\n"
+ "</mem_areas_header>\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark
+ );
+#endif
+ goto unlock_and_return;
+ }
+
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+
+ if(!psRecord)
+ {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if(count < 500)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%8p %-24s %8p %08lx %-8ld %-5u %08lx=(%s)\n",
+#else
+ "<linux_mem_area>\n"
+ "\t<pointer>%8p</pointer>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%u</pid>\n"
+ "\t<flags>%08lx</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</linux_mem_area>\n",
+#endif
+ psRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+ LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+ psRecord->psLinuxMemArea->ui32ByteSize,
+ psRecord->pid,
+ psRecord->ui32Flags,
+ HAPFlagsToString(psRecord->ui32Flags)
+ );
+
+unlock_and_return:
+ mutex_unlock(&g_sDebugMutex);
+ return Ret;
+}
+#endif
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if(!psRecord)
+ {
+ seq_printf( sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if(!psRecord)
+ {
+ seq_printf( sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via kmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via kmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via vmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via vmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via alloc_pages",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via alloc_pages",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via ioremap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via ioremap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes reserved for \"IO\" memory areas",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via kmem_cache_alloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile, "\n");
+
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "The Current Water Mark for memory allocated from system RAM",
+ g_SysRAMWaterMark);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "The Highest Water Mark for memory allocated from system RAM",
+ g_SysRAMHighWaterMark);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "The Current Water Mark for memory allocated from IO memory",
+ g_IOMemWaterMark);
+ seq_printf( sfile, "%-60s: %ld bytes\n",
+ "The Highest Water Mark for memory allocated from IO memory",
+ g_IOMemHighWaterMark);
+
+ seq_printf( sfile, "\n");
+
+ seq_printf( sfile, "Details for all known allocations:\n"
+ "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+ "Type",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "PID",
+ "PrivateData",
+ "Filename:Line");
+
+#else
+
+
+ seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
+ seq_printf( sfile,
+ "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile,
+ "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile,
+ "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile,
+ "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile,
+ "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile,
+ "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile,
+ "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile,
+ "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile,"\n" );
+
+ seq_printf( sfile,
+ "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%ld\"/>\n",
+ g_SysRAMWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%ld\"/>\n",
+ g_SysRAMHighWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%ld\"/>\n",
+ g_IOMemWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%ld\"/>\n",
+ g_IOMemHighWaterMark);
+
+ seq_printf( sfile, "</meminfo_header>\n");
+
+#endif
+ return;
+ }
+
+ if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%ld</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ "NULL",
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+ else
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%ld</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ KMemCacheNameWrapper(psRecord->pvPrivateData),
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+}
+
+
+
+#else
+
+static off_t
+printMemoryRecords(IMG_CHAR * buffer, size_t count, off_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ off_t Ret;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if(!off)
+ {
+ if(count < 1000)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+ Ret = printAppend(buffer, count, 0, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via kmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via kmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via vmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via vmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via alloc_pages",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via alloc_pages",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via ioremap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via ioremap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes reserved for \"IO\" memory areas",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Current Water Mark of bytes allocated via kmem_cache_alloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret, "\n");
+
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "The Current Water Mark for memory allocated from system RAM",
+ g_SysRAMWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "The Highest Water Mark for memory allocated from system RAM",
+ g_SysRAMHighWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "The Current Water Mark for memory allocated from IO memory",
+ g_IOMemWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+ "The Highest Water Mark for memory allocated from IO memory",
+ g_IOMemHighWaterMark);
+
+ Ret = printAppend(buffer, count, Ret, "\n");
+
+ Ret = printAppend(buffer, count, Ret, "Details for all known allocations:\n"
+ "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+ "Type",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "PID",
+ "PrivateData",
+ "Filename:Line");
+
+#else
+
+
+ Ret = printAppend(buffer, count, 0, "<meminfo>\n<meminfo_header>\n");
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%ld\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%ld\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret, "\n");
+
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%ld\"/>\n",
+ g_SysRAMWaterMark);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%ld\"/>\n",
+ g_SysRAMHighWaterMark);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%ld\"/>\n",
+ g_IOMemWaterMark);
+ Ret = printAppend(buffer, count, Ret,
+ "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%ld\"/>\n",
+ g_IOMemHighWaterMark);
+
+ Ret = printAppend(buffer, count, Ret, "</meminfo_header>\n");
+
+#endif
+
+ goto unlock_and_return;
+ }
+
+ if(count < 1000)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+ if(!psRecord)
+ {
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if(off == 0)
+ {
+ Ret = printAppend(buffer, count, 0, "</meminfo>\n");
+ goto unlock_and_return;
+ }
+#endif
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%ld</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ "NULL",
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+ else
+ {
+ Ret = printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%ld</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ KMemCacheNameWrapper(psRecord->pvPrivateData),
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+
+unlock_and_return:
+ mutex_unlock(&g_sDebugMutex);
+ return Ret;
+}
+#endif
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+ static IMG_CHAR szFlags[50];
+ IMG_INT32 i32Pos = 0;
+ IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+ IMG_CHAR *apszCacheTypes[] = {
+ "UNCACHED",
+ "CACHED",
+ "WRITECOMBINE",
+ "UNKNOWN"
+ };
+ IMG_CHAR *apszMapType[] = {
+ "KERNEL_ONLY",
+ "SINGLE_PROCESS",
+ "MULTI_PROCESS",
+ "FROM_EXISTING_PROCESS",
+ "NO_CPU_VIRTUAL",
+ "UNKNOWN"
+ };
+
+
+ if(ui32Flags & PVRSRV_HAP_UNCACHED){
+ ui32CacheTypeIndex=0;
+ }else if(ui32Flags & PVRSRV_HAP_CACHED){
+ ui32CacheTypeIndex=1;
+ }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
+ ui32CacheTypeIndex=2;
+ }else{
+ ui32CacheTypeIndex=3;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+ }
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+ ui32MapTypeIndex = 0;
+ }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+ ui32MapTypeIndex = 1;
+ }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+ ui32MapTypeIndex = 2;
+ }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+ ui32MapTypeIndex = 3;
+ }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+ ui32MapTypeIndex = 4;
+ }else{
+ ui32MapTypeIndex = 5;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+ }
+
+ i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+ if (i32Pos <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+ __FUNCTION__, ui32CacheTypeIndex, i32Pos));
+ szFlags[0] = 0;
+ }
+ else
+ {
+ sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+ }
+
+ return szFlags;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
new file mode 100644
index 0000000..78f3d14
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
@@ -0,0 +1,323 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+ return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+
+}
+
+typedef enum {
+ LINUX_MEM_AREA_IOREMAP,
+ LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_IO,
+ LINUX_MEM_AREA_VMALLOC,
+ LINUX_MEM_AREA_ALLOC_PAGES,
+ LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+ LINUX_MEM_AREA_TYPE eAreaType;
+ union _uData
+ {
+ struct _sIORemap
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_VOID *pvIORemapCookie;
+ }sIORemap;
+ struct _sExternalKV
+ {
+
+ IMG_BOOL bPhysContig;
+ union {
+
+ IMG_SYS_PHYADDR SysPhysAddr;
+ IMG_SYS_PHYADDR *pSysPhysAddr;
+ } uPhysAddr;
+ IMG_VOID *pvExternalKV;
+ }sExternalKV;
+ struct _sIO
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ }sIO;
+ struct _sVmalloc
+ {
+
+ IMG_VOID *pvVmallocAddress;
+ }sVmalloc;
+ struct _sPageList
+ {
+
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ }sPageList;
+ struct _sSubAlloc
+ {
+
+ LinuxMemArea *psParentLinuxMemArea;
+ IMG_UINT32 ui32ByteOffset;
+ }sSubAlloc;
+ }uData;
+
+ IMG_UINT32 ui32ByteSize;
+
+ IMG_UINT32 ui32AreaFlags;
+
+ IMG_BOOL bMMapRegistered;
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, NULL, 0)
+#endif
+IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes);
+
+
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+ else
+ {
+ return psLinuxMemArea;
+ }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
new file mode 100644
index 0000000..a273689
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
@@ -0,0 +1,1149 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static struct mutex g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+
+#if defined(PVR_PROC_USE_SEQ_FILE) && defined(DEBUG_LINUX_MMAP_AREAS)
+static struct proc_dir_entry *g_ProcMMap;
+#endif
+
+#define FIRST_PHYSICAL_PFN 0
+#define LAST_PHYSICAL_PFN 0x7fffffffUL
+#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
+#define LAST_SPECIAL_PFN 0xffffffffUL
+
+#define MAX_MMAP_HANDLE 0x7fffffffUL
+
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+ if (PFNIsPhysical(pfn))
+ {
+ PVR_ASSERT(PFNIsPhysical(pfn));
+ return IMG_NULL;
+ }
+
+ return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+ IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+ if (PFNIsSpecial(ulHandle))
+ {
+ PVR_ASSERT(PFNIsSpecial(ulHandle));
+ return 0;
+ }
+
+ return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+
+ return (IMG_UINT32)current->pid;
+}
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+ if(psOffsetStruct == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+ return IMG_NULL;
+ }
+
+ psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+ psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+ psOffsetStruct->ui32Mapped = 0;
+
+ psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+ psOffsetStruct->ui32TID = GetCurrentThreadID();
+
+ psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+ psOffsetStruct->ui32RefCount = 0;
+
+ psOffsetStruct->ui32UserVAddr = 0;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ psOffsetStruct->pszName = pszName;
+#endif
+
+ list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+ return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ list_del(&psOffsetStruct->sAreaItem);
+
+ if (psOffsetStruct->bOnMMapList)
+ {
+ list_del(&psOffsetStruct->sMMapItem);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+ "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
+
+ KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32ByteOffset)
+{
+ IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+ *pui32ByteOffset = ui32PageAlignmentOffset;
+
+ *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+ {
+
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+ *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+ *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ *pui32UserVAddr = 0;
+
+ if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+ {
+ *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ }
+ else
+ {
+ *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+ PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+ }
+
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exit_unlock;
+ }
+
+
+ list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+ psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (psOffsetStruct->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ }
+
+ psOffsetStruct->ui32RefCount--;
+
+ *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+ *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+ *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+ eError = PVRSRV_ERROR_GENERIC;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_UINT32 ui32TID = GetCurrentThreadID();
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+ {
+
+ if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+ {
+ return psOffsetStruct;
+ }
+ }
+ }
+
+ return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+ struct vm_area_struct* ps_vma,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32ByteSize;
+
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ ps_vma,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+ }
+
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+ if (PFNIsPhysical(ps_vma->vm_pgoff))
+ {
+ IMG_INT result;
+
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+
+ result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+ if(result == 0)
+ {
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+ }
+
+ {
+
+ IMG_UINT32 ulVMAPos;
+ IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+ IMG_UINT32 ui32PA;
+
+
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+ if (!pfn_valid(pfn))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
+ return IMG_FALSE;
+ }
+ }
+
+
+ ulVMAPos = ps_vma->vm_start;
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn;
+ struct page *psPage;
+ IMG_INT result;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+ psOffsetStruct->ui32Mapped++;
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+ if (psOffsetStruct->ui32Mapped > 1)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+ PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+
+ MMapVOpenNoLock(ps_vma);
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea 0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ psOffsetStruct->ui32Mapped--;
+ if (psOffsetStruct->ui32Mapped == 0)
+ {
+ if (psOffsetStruct->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+ }
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ ps_vma->vm_private_data = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+
+ MMapVCloseNoLock(ps_vma);
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+ .open=MMapVOpen,
+ .close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ IMG_UINT32 ui32ByteSize;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ int iRetVal = 0;
+
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ mutex_lock(&g_sMMapMutex);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+ " and ui32ByteSize %ld(0x%08lx)",
+ __FUNCTION__,
+ ps_vma->vm_pgoff,
+ ui32ByteSize, ui32ByteSize));
+
+ psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+#if defined(SUPPORT_DRI_DRM)
+ mutex_unlock(&g_sMMapMutex);
+
+
+ return drm_mmap(pFile, ps_vma);
+#else
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+#if 0 /* FIXME: crash when call to print debug messages */
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
+ __FUNCTION__, ps_vma->vm_pgoff));
+#endif
+ iRetVal = -EINVAL;
+#endif
+ goto unlock_and_return;
+ }
+ list_del(&psOffsetStruct->sMMapItem);
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+ if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+ ((ps_vma->vm_flags & VM_SHARED) == 0))
+ {
+#if 0 /* FIXME: crash when call to print debug messages */
+ PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+#endif
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+
+#if 0 /* FIXME: crash when call to print debug messages */
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+ __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+#endif
+ ps_vma->vm_flags |= VM_RESERVED;
+ ps_vma->vm_flags |= VM_IO;
+
+
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+ ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+ switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+ {
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+ psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+ MMapVOpenNoLock(ps_vma);
+
+#if 0 /* FIXME: crash when call to print debug messages */
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+ __FUNCTION__, ps_vma->vm_pgoff));
+#endif
+
+unlock_and_return:
+ if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+ {
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ mutex_unlock(&g_sMMapMutex);
+
+ return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ mutex_lock(&g_sMMapMutex);
+ }
+ else
+ {
+ mutex_unlock(&g_sMMapMutex);
+ }
+}
+
+
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+ LinuxMemArea *psLinuxMemArea;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ PKV_OFFSET_STRUCT psOffsetStruct;
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ off--;
+ if (off == 0)
+ {
+ PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+ return (void*)psOffsetStruct;
+ }
+ }
+ }
+ return (void*)0;
+}
+
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile,void* el)
+{
+ KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32RealByteSize;
+ IMG_UINT32 ui32ByteOffset;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "Allocations registered for mmap: %lu\n"
+ "In total these areas correspond to %lu bytes\n"
+ "psLinuxMemArea "
+ "UserVAddr "
+ "KernelVAddr "
+ "CpuPAddr "
+ "MMapOffset "
+ "ByteLength "
+ "LinuxMemType "
+ "Pid Name Flags\n",
+#else
+ "<mmap_header>\n"
+ "\t<count>%lu</count>\n"
+ "\t<bytes>%lu</bytes>\n"
+ "</mmap_header>\n",
+#endif
+ g_ui32RegisteredAreas,
+ g_ui32TotalByteSize
+ );
+ return;
+ }
+
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n",
+#else
+ "<mmap_record>\n"
+ "\t<pointer>%-8p</pointer>\n"
+ "\t<user_virtual>%-8lx</user_virtual>\n"
+ "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<mmap_offset>%08lx</mmap_offset>\n"
+ "\t<bytes>%-8ld</bytes>\n"
+ "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+ "\t<pid>%-5lu</pid>\n"
+ "\t<name>%-8s</name>\n"
+ "\t<flags>%08lx</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</mmap_record>\n",
+#endif
+ psLinuxMemArea,
+ psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+ psOffsetStruct->ui32MMapOffset,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+ psOffsetStruct->ui32PID,
+ psOffsetStruct->pszName,
+ psLinuxMemArea->ui32AreaFlags,
+ HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#else
+
+static off_t
+PrintMMapRegistrations(IMG_CHAR *buffer, size_t size, off_t off)
+{
+ LinuxMemArea *psLinuxMemArea;
+ off_t Ret;
+
+ mutex_lock(&g_sMMapMutex);
+
+ if(!off)
+ {
+ Ret = printAppend(buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "Allocations registered for mmap: %lu\n"
+ "In total these areas correspond to %lu bytes\n"
+ "psLinuxMemArea "
+ "UserVAddr "
+ "KernelVAddr "
+ "CpuPAddr "
+ "MMapOffset "
+ "ByteLength "
+ "LinuxMemType "
+ "Pid Name Flags\n",
+#else
+ "<mmap_header>\n"
+ "\t<count>%lu</count>\n"
+ "\t<bytes>%lu</bytes>\n"
+ "</mmap_header>\n",
+#endif
+ g_ui32RegisteredAreas,
+ g_ui32TotalByteSize
+ );
+
+ goto unlock_and_return;
+ }
+
+ if (size < 135)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(off != 0);
+ list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ PKV_OFFSET_STRUCT psOffsetStruct;
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ off--;
+ if (off == 0)
+ {
+ IMG_UINT32 ui32RealByteSize;
+ IMG_UINT32 ui32ByteOffset;
+
+ PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ Ret = printAppend (buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n",
+#else
+ "<mmap_record>\n"
+ "\t<pointer>%-8p</pointer>\n"
+ "\t<user_virtual>%-8lx</user_virtual>\n"
+ "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+ "\t<cpu_physical>%08lx</cpu_physical>\n"
+ "\t<mmap_offset>%08lx</mmap_offset>\n"
+ "\t<bytes>%-8ld</bytes>\n"
+ "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+ "\t<pid>%-5lu</pid>\n"
+ "\t<name>%-8s</name>\n"
+ "\t<flags>%08lx</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</mmap_record>\n",
+#endif
+ psLinuxMemArea,
+ psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+ psOffsetStruct->ui32MMapOffset,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+ psOffsetStruct->ui32PID,
+ psOffsetStruct->pszName,
+ psLinuxMemArea->ui32AreaFlags,
+ HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+ goto unlock_and_return;
+ }
+ }
+ }
+ Ret = END_OF_FILE;
+
+unlock_and_return:
+ mutex_unlock(&g_sMMapMutex);
+ return Ret;
+}
+#endif
+#endif
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ mutex_lock(&g_sMMapMutex);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+ if(psLinuxMemArea->bMMapRegistered)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+ __FUNCTION__, psLinuxMemArea));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+ psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas++;
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32Mapped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
+ }
+
+ PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ list_del(&psLinuxMemArea->sMMapItem);
+
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas--;
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+ IMG_BOOL bWarn = IMG_FALSE;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ mutex_lock(&g_sMMapMutex);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (!bWarn)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+ bWarn = IMG_TRUE;
+ }
+ PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+ PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ }
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+ mutex_init(&g_sMMapMutex);
+
+ g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+ if (!g_psMemmapCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ goto error;
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL,
+ ProcSeqNextMMapRegistrations,
+ ProcSeqShowMMapRegistrations,
+ ProcSeqOff2ElementMMapRegistrations,
+ ProcSeqStartstopMMapRegistations
+ );
+#else
+ CreateProcReadEntry("mmap", PrintMMapRegistrations);
+#endif
+#endif
+ return;
+
+error:
+ PVRMMapCleanup();
+ return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ if (!list_empty(&g_sMMapAreaList))
+ {
+ LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+ PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+ list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ }
+ }
+ PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq(g_ProcMMap);
+#else
+ RemoveProcEntry("mmap");
+#endif
+#endif
+
+ if(g_psMemmapCache)
+ {
+ KMemCacheDestroyWrapper(g_psMemmapCache);
+ g_psMemmapCache = NULL;
+ }
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
new file mode 100644
index 0000000..afc7c94
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
@@ -0,0 +1,103 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+
+ IMG_UINT32 ui32Mapped;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ LinuxMemArea *psLinuxMemArea;
+
+
+ IMG_UINT32 ui32TID;
+
+
+ IMG_UINT32 ui32PID;
+
+
+ IMG_BOOL bOnMMapList;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName;
+#endif
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize, IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
new file mode 100644
index 0000000..0fd336b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
@@ -0,0 +1,756 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+
+ #if defined(LDM_PLATFORM)
+ #define PVR_LDM_PLATFORM_MODULE
+ #define PVR_LDM_MODULE
+ #else
+ #if defined(LDM_PCI)
+ #define PVR_LDM_PCI_MODULE
+ #define PVR_LDM_MODULE
+ #endif
+ #endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "sysconfig.h"
+#include "sysplb.h"
+#include "systnc.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#define DRVNAME "pvrsrvkm"
+#define DEVNAME "pvrsrvkm"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+#ifdef DEBUG
+static IMG_INT debug = DBGPRIV_WARNING;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#else
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Sets the level of debug output (default=0x4)");
+#endif
+#endif
+
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+extern IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+
+
+#if defined(PVR_LDM_MODULE)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static IMG_INT AssignedMajorNumber;
+
+static IMG_INT PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static IMG_INT PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops = {
+ .owner=THIS_MODULE,
+ .unlocked_ioctl=PVRSRV_BridgeDispatchKM,
+ .open=PVRSRVOpen,
+ .release=PVRSRVRelease,
+ .mmap=PVRMMap,
+};
+#endif
+
+struct mutex gPVRSRVLock;
+
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define LDM_DEV struct platform_device
+#define LDM_DRV struct platform_driver
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define LDM_DEV struct pci_dev
+#define LDM_DRV struct pci_driver
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *device);
+static IMG_INT PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+/* all supported platform ids */
+struct pci_device_id powervr_id_table[] __devinitdata = {
+ { PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID_PLB) },
+ { PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID_TNC) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .driver = {
+ .name = DRVNAME,
+ },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .name = DRVNAME,
+ .id_table = powervr_id_table,
+#endif
+ .probe = PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .remove = PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .remove = __devexit_p(PVRSRVDriverRemove),
+#endif
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .shutdown = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE)
+
+static IMG_VOID PVRSRVDeviceRelease(struct device *pDevice)
+{
+ PVR_UNREFERENCED_PARAMETER(pDevice);
+}
+
+static struct platform_device powervr_device = {
+ .name = DEVNAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};
+
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_INT __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0
+
+ if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ {
+ gpsPVRLDMDev = pDevice;
+
+ if (SysInitialise() != PVRSRV_OK)
+ {
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+ if (SysAcquireData(&psSysData) == PVRSRV_OK)
+ {
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+ if (gPVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ gPVRPowerLevel = 0;
+ }
+ }
+#endif
+ SysDeinitialise(psSysData);
+
+ gpsPVRLDMDev = IMG_NULL;
+ }
+
+#if 0
+ if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+ return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+ return;
+#endif
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+ PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+ (IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+ PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+static IMG_INT PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+ PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+#endif
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+ IMG_CHAR data_buffer[2];
+ IMG_UINT32 PVRPowerLevel;
+
+ if (count != sizeof(data_buffer))
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ PVRPowerLevel = data_buffer[0] - '0';
+ if (PVRPowerLevel != gPVRPowerLevel)
+ {
+ if (PVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+ }
+
+ gPVRPowerLevel = PVRPowerLevel;
+ }
+ }
+ return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ if (off == 0) {
+ *start = (IMG_CHAR *)1;
+ return printAppend(page, count, 0, "%lu\n", gPVRPowerLevel);
+ }
+ *eof = 1;
+ return 0;
+}
+#endif
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_HANDLE hBlockAlloc;
+ IMG_INT iRet = -ENOMEM;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+#else
+ PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+ mutex_lock(&gPVRSRVLock);
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ if (PVRSRVProcessConnect(ui32PID) != PVRSRV_OK)
+ goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+ goto err_unlock;
+ }
+#endif
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_FILE_PRIVATE_DATA),
+ (IMG_PVOID *)&psPrivateData,
+ &hBlockAlloc,
+ "File Private Data");
+
+ if(eError != PVRSRV_OK)
+ goto err_unlock;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+ psPrivateData->hKernelMemInfo = NULL;
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ psPrivateData->psDRMFile = pFile;
+
+ list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif
+ psPrivateData->ui32OpenPID = ui32PID;
+ psPrivateData->hBlockAlloc = hBlockAlloc;
+ PRIVATE_DATA(pFile) = psPrivateData;
+ iRet = 0;
+err_unlock:
+ mutex_unlock(&gPVRSRVLock);
+ return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVRelease(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+#else
+ PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+ mutex_lock(&gPVRSRVLock);
+
+ psPrivateData = PRIVATE_DATA(pFile);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+
+ gui32ReleasePID = psPrivateData->ui32OpenPID;
+ PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+ gui32ReleasePID = 0;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_FILE_PRIVATE_DATA),
+ psPrivateData, psPrivateData->hBlockAlloc);
+
+ PRIVATE_DATA(pFile) = NULL;
+
+ mutex_unlock(&gPVRSRVLock);
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID)
+#else
+static IMG_INT __init PVRCore_Init(IMG_VOID)
+#endif
+{
+ IMG_INT error;
+#if !defined(PVR_LDM_MODULE)
+ PVRSRV_ERROR eError;
+#else
+ struct device *psDev;
+#endif
+
+ PVRDPFInit();
+ PVR_TRACE(("PVRCore_Init"));
+
+ mutex_init(&gPVRSRVLock);
+
+#ifdef DEBUG
+ PVRDebugSetLevel(debug);
+#endif
+
+ if (CreateProcEntries ())
+ {
+ error = -ENOMEM;
+ return error;
+ }
+
+ if (PVROSFuncInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ PVRLinuxMUtilsInit();
+
+ if(LinuxMMInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ LinuxBridgeInit();
+
+ PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ if ((error = platform_driver_register(&powervr_driver)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+ goto init_failed;
+ }
+
+#if defined(MODULE)
+ if ((error = platform_device_register(&powervr_device)) != 0)
+ {
+ platform_driver_unregister(&powervr_driver);
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+ goto init_failed;
+ }
+#endif
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+ if ((error = pci_register_driver(&powervr_driver)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+ goto init_failed;
+ }
+#endif
+
+#else
+
+ if ((eError = SysInitialise()) != PVRSRV_OK)
+ {
+ error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+ if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+ {
+ printk("\nAtlas wrapper (FPGA image) version mismatch");
+ error = -ENODEV;
+ }
+#endif
+ goto init_failed;
+ }
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+ error = -EBUSY;
+ goto sys_deinit;
+ }
+
+ PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+ psPvrClass = class_create(THIS_MODULE, "pvr");
+
+ if (IS_ERR(psPvrClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+ error = -EBUSY;
+ goto unregister_device;
+ }
+
+ psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DEVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+ error = -EBUSY;
+ goto destroy_class;
+ }
+#endif
+
+ return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+ class_destroy(psPvrClass);
+unregister_device:
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+ pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+
+ {
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+ if (psSysData != IMG_NULL)
+ {
+ SysDeinitialise(psSysData);
+ }
+ }
+#endif
+init_failed:
+ PVRMMapCleanup();
+ LinuxMMCleanup();
+ LinuxBridgeDeInit();
+ PVROSFuncDeInit();
+ RemoveProcEntries();
+
+ return error;
+
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_VOID PVRCore_Cleanup(IMG_VOID)
+#else
+static IMG_VOID __exit PVRCore_Cleanup(IMG_VOID)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRCore_Cleanup"));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ if (
+#endif
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
+#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ ;
+#else
+ )
+ {
+ PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
+ }
+#endif
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+ pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+ if (gPVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ gPVRPowerLevel = 0;
+ }
+ }
+#endif
+
+ SysDeinitialise(psSysData);
+#endif
+
+ PVRMMapCleanup();
+
+ LinuxMMCleanup();
+
+ LinuxBridgeDeInit();
+
+ PVROSFuncDeInit();
+
+ RemoveProcEntries();
+
+ PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
new file mode 100644
index 0000000..652955a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+/*
+ * PVR's mutex wrapping code has been removed and we're just calling
+ * mutex_lock, mutex_unlock, etc. directly now. Most of the wrappers
+ * here were unused, and the couple that were used simply confused
+ * the compiler about potential recursive locking.
+ */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
new file mode 100644
index 0000000..894c1c9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#include <linux/mutex.h>
+
+/*
+ * PVR's mutex wrapping code has been removed and we're just calling
+ * mutex_lock, mutex_unlock, etc. directly now. Most of the wrappers
+ * here were unused, and the couple that were used simply confused
+ * the compiler about potential recursive locking.
+ */
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
new file mode 100644
index 0000000..ce010bf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
@@ -0,0 +1,126 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define PAT_LINUX_X86_WC 1
+
+#define PAT_X86_ENTRY_BITS 8
+
+#define PAT_X86_BIT_PWT 1U
+#define PAT_X86_BIT_PCD 2U
+#define PAT_X86_BIT_PAT 4U
+#define PAT_X86_BIT_MASK (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+ IMG_UINT ret = 0;
+ pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+ ret |= PROT_TO_PAT_INDEX(val, PAT);
+ ret |= PROT_TO_PAT_INDEX(val, PCD);
+ ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+ return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+ return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+
+ if (cpu_has_pat)
+ {
+ u64 pat;
+ IMG_UINT pat_index;
+ IMG_UINT pat_entry;
+
+ PVR_TRACE(("%s: PAT available", __FUNCTION__));
+
+ rdmsrl(MSR_IA32_CR_PAT, pat);
+ PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+ PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+ pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+ PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+ pat_entry = pvr_pat_entry(pat, pat_index);
+ PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+ }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ if (g_write_combining_available)
+ {
+ PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+ }
+#else
+ PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif
+#endif
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+
+
+ return (g_write_combining_available) ?
+ __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+ PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
new file mode 100644
index 0000000..625041b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
@@ -0,0 +1,93 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+ #define PGPROT_WC(pv) pvr_pgprot_writecombine(pv)
+#else
+ #if defined(__arm__) || defined(__sh__)
+ #define PGPROT_WC(pv) pgprot_writecombine(pv)
+ #else
+ #if defined(__i386__)
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #else
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #error Unsupported architecture!
+ #endif
+ #endif
+#endif
+
+#define PGPROT_UC(pv) pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ #define IOREMAP(pa, bytes) ioremap_cache(pa, bytes)
+#else
+ #if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ #define IOREMAP(pa, bytes) ioremap_cached(pa, bytes)
+ #else
+ #define IOREMAP(pa, bytes) ioremap(pa, bytes)
+ #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#else
+ #if defined(__arm__)
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, L_PTE_BUFFERABLE)
+ #else
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+ #endif
+ #endif
+ #endif
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#endif
+
+#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
new file mode 100644
index 0000000..ba666a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
@@ -0,0 +1,2534 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+#include <asm/exec.h>
+#include <asm/cmpxchg.h>
+#include <asm/auxvec.h>
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+#include <asm/cacheflush.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+ defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+ defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+ defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "event.h"
+#include "linkage.h"
+
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS) || \
+ defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+
+#if defined(__i386__)
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ wbinvd();
+}
+#endif
+
+#if !defined(SUPPORT_CPU_CACHED_BUFFERS)
+static
+#endif
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+#if defined(__arm__)
+ flush_cache_all();
+#elif defined(__i386__)
+
+ on_each_cpu(per_cpu_cache_flush, NULL, 1);
+#else
+#error "Implement full CPU cache flush for this CPU!"
+#endif
+}
+
+#endif
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_VOID *pvRangeAddrStart,
+ IMG_VOID *pvRangeAddrEnd)
+{
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrEnd);
+
+
+ OSFlushCPUCacheKM();
+}
+
+#endif
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+#else
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = KMallocWrapper(ui32Size);
+#endif
+ if(*ppvCpuVAddr)
+ {
+ if (phBlockAlloc)
+ {
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+ }
+ }
+ else
+ {
+ if (!phBlockAlloc)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+#endif
+ if (!*ppvCpuVAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC)
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ VFreeWrapper(pvCpuVAddr);
+#endif
+ }
+ else
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ KFreeWrapper(pvCpuVAddr);
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PageSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+
+ if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+
+ psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+
+ if(ui32AllocFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+ {
+ OSFlushCPUCacheKM();
+ }
+#endif
+
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ *phOSMemHandle = psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
+ "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+ ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+ __FUNCTION__, ui32AllocFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ if(!psLinuxMemArea)
+ {
+ *phOSMemHandleRet = NULL;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *phOSMemHandleRet = psLinuxMemArea;
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = PVRMMapRegisterArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_register_area;
+ }
+
+ return PVRSRV_OK;
+
+failed_register_area:
+ *phOSMemHandleRet = NULL;
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+ if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+ PVR_ASSERT(hOSMemHandle);
+
+ return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+}
+
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ IMG_UINT8 *Src,*Dst;
+ IMG_INT i;
+
+ Src=(IMG_UINT8 *)pvSrc;
+ Dst=(IMG_UINT8 *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ Dst[i]=Src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+ IMG_UINT8 *Buff;
+ IMG_INT i;
+
+ Buff=(IMG_UINT8 *)pvDest;
+ for(i=0;i<ui32Size;i++)
+ {
+ Buff[i]=ui8Value;
+ }
+#else
+ memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+ return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+ va_list argList;
+ IMG_INT32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process."));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+ }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+ psResource->ui32ID = 0;
+ psResource->ui32Lock = 0;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+ OSBreakResourceLock (psResource, psResource->ui32ID);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+ ENV_DATA *psEnvData;
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+ "Environment Data") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ &psEnvData->pvBridgeData, IMG_NULL,
+ "Bridge Data") != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+
+ *ppvEnvSpecificData = psEnvData;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+ ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+ PVR_ASSERT(!psEnvData->bMISRInstalled);
+ PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+ psEnvData->pvBridgeData = IMG_NULL;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+ schedule();
+}
+
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+ IMG_UINT32 time, j = jiffies;
+
+ time = j * (1000000 / HZ);
+
+ return time;
+}
+
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ return (IMG_UINT32)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ return (IMG_UINT32)task_tgid_nr(current);
+#else
+ return (IMG_UINT32)current->tgid;
+#endif
+#endif
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+ IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+ return (ui32ReturnValue);
+#else
+ return PAGE_SIZE;
+#endif
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psSysData = (SYS_DATA *)dev_id;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVSystemLISR(psSysData);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %x", pszISRName, ui32Irq, pvDeviceNode));
+
+ if(request_irq(ui32Irq, DeviceISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , pszISRName, pvDeviceNode))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvDeviceNode;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing system LISR on IRQ %d with cookie %x", ui32Irq, pvSysData));
+
+ if(request_irq(ui32Irq, SystemISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , "PowerVR", pvSysData))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvSysData;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+ if (psEnvData->psWorkQueue == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ destroy_workqueue(psEnvData->psWorkQueue);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+#else
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ flush_scheduled_work();
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ schedule_work(&psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+
+
+static void MISRWrapper(unsigned long data)
+{
+ SYS_DATA *psSysData;
+
+ psSysData = (SYS_DATA *)data;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+ tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ tasklet_kill(&psEnvData->sMISRTasklet);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ tasklet_schedule(&psEnvData->sMISRTasklet);
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+#endif
+
+#endif
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+ BUG();
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#define OS_TAS(p) xchg((p), 1)
+#else
+#define OS_TAS(p) tas(p)
+#endif
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
+ IMG_UINT32 ui32ID)
+
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!OS_TAS(&psResource->ui32Lock))
+ psResource->ui32ID = ui32ID;
+ else
+ eError = PVRSRV_ERROR_GENERIC;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource));
+ PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+}
+
+
+IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ return (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+ ? IMG_TRUE
+ : IMG_FALSE;
+}
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID *pvLinAddr)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = (IMG_UINTPTR_T)VMallocToPhys(pvLinAddr);
+
+ return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ if(phOSMemHandle)
+ {
+ *phOSMemHandle = (IMG_HANDLE)0;
+ }
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ IMG_VOID *pvIORemapCookie;
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(pvIORemapCookie == IMG_NULL)
+ {
+ return NULL;
+ }
+ return pvIORemapCookie;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSReservePhys otherwise)"));
+ return NULL;
+ }
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hPageAlloc)
+{
+ PVR_TRACE(("%s: unmapping %d bytes from 0x%08x", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+ PVR_UNREFERENCED_PARAMETER(hPageAlloc);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ IOUnmapWrapper(pvLinAddr);
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSUnReservePhys otherwise)"));
+ return IMG_FALSE;
+ }
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_BOOL bPhysContig,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+#if 0
+
+ if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+ psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+ IMG_VOID *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
+#else
+ pvKernLinAddr = KMallocWrapper(ui32Size);
+#endif
+ if (!pvKernLinAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pvLinAddr = pvKernLinAddr;
+
+ psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+ return PVRSRV_OK;
+#endif
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ KFreeWrapper(pvLinAddr);
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+ int err;
+ IMG_UINT32 i;
+ PVR_PCI_DEV *psPVRPCI;
+
+ PVR_TRACE(("OSPCISetDev"));
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+ "PCI Device") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+ return IMG_NULL;
+ }
+
+ psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+ psPVRPCI->ePCIFlags = eFlags;
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+ return IMG_NULL;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_set_master(psPVRPCI->psPCIDev);
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+#if defined(CONFIG_PCI_MSI)
+ err = pci_enable_msi(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ }
+#else
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+ }
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+
+ return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+ struct pci_dev *psPCIDev;
+
+ psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+ if (psPCIDev == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+ return IMG_NULL;
+ }
+
+ return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+ return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+ HOST_PCI_ADDR_RANGE_FUNC_LEN,
+ HOST_PCI_ADDR_RANGE_FUNC_START,
+ HOST_PCI_ADDR_RANGE_FUNC_END,
+ HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+ HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+ PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (ui32Index >= DEVICE_COUNT_RESOURCE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+ return 0;
+
+ }
+
+ switch (eFunc)
+ {
+ case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+ return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_START:
+ return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_END:
+ return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+ {
+ int err;
+
+ err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, "PowerVR");
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+ return 0;
+ }
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+ return 1;
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+ if (psPVRPCI->abPCIResourceInUse[ui32Index])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+ }
+ return 1;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+ break;
+ }
+
+ return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+
+ PVR_TRACE(("OSPCIReleaseDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+ }
+
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+ pci_disable_msi(psPVRPCI->psPCIDev);
+ }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_clear_master(psPVRPCI->psPCIDev);
+ }
+#endif
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+
+ PVR_TRACE(("OSPCISuspendDev"));
+
+ err = pci_save_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+ break;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+
+ PVR_TRACE(("OSPCIResumeDev"));
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+ return PVRSRV_ERROR_GENERIC;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ pci_restore_state(psPVRPCI->psPCIDev);
+#else
+ err = pci_restore_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_restore_state failed (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ pci_set_master(psPVRPCI->psPCIDev);
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define OS_MAX_TIMERS 8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+ IMG_BOOL bInUse;
+ PFN_TIMER_FUNC pfnTimerFunc;
+ IMG_VOID *pvData;
+ struct timer_list sTimer;
+ IMG_UINT32 ui32Delay;
+ IMG_BOOL bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ struct work_struct sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+ if (!psTimerCBData->bActive)
+ return;
+
+
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+ OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ int res;
+
+ res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+ if (res == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+ }
+#else
+ OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData;
+ IMG_UINT32 ui32i;
+#if !defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ unsigned long ulLockFlags;
+#endif
+
+
+ if(!pfnTimerFunc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+ return IMG_NULL;
+ }
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ mutex_lock(&sTimerStructLock);
+#else
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse)
+ {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ mutex_unlock(&sTimerStructLock);
+#else
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+ if (ui32i >= OS_MAX_TIMERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+ return IMG_NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+
+
+
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1
+ : ((HZ * ui32MsTimeout) / 1000);
+
+ init_timer(&psTimerCBData->sTimer);
+
+
+ psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+ return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+ IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+ return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_TRUE;
+
+
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_FALSE;
+ smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ flush_workqueue(psTimerWorkQueue);
+#endif
+
+
+ del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+
+ flush_workqueue(psTimerWorkQueue);
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(pszName)
+ {
+
+ strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+ }
+ else
+ {
+
+ static IMG_UINT16 ui16NameIndex = 0;
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+ }
+
+ if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+
+}
+
+
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(psEventObject->hOSEventKM)
+ {
+ LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+
+}
+
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectSignal(hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+ return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+ IMG_INT linuxType;
+
+ if (eVerification == PVR_VERIFY_READ)
+ {
+ linuxType = VERIFY_READ;
+ }
+ else
+ {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+ WRAP_TYPE_CLEANUP,
+ WRAP_TYPE_GET_USER_PAGES,
+ WRAP_TYPE_FIND_VMA_PAGES,
+ WRAP_TYPE_FIND_VMA_PFN
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+ eWrapMemType eType;
+ IMG_INT iNumPages;
+ struct page **ppsPages;
+ IMG_SYS_PHYADDR *psPhysAddr;
+ IMG_INT iPageOffset;
+ IMG_INT iContiguous;
+#if defined(DEBUG)
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulBeyondEndAddr;
+ struct vm_area_struct *psVMArea;
+#endif
+ IMG_BOOL bWrapWorkaround;
+} sWrapMemInfo;
+
+static IMG_VOID CheckPagesContiguous(sWrapMemInfo *psInfo)
+{
+ IMG_INT i;
+ IMG_UINT32 ui32AddrChk;
+
+ BUG_ON(psInfo == IMG_NULL);
+
+ psInfo->iContiguous = 1;
+
+ for (i = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
+ i < psInfo->iNumPages;
+ i++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psInfo->psPhysAddr[i].uiAddr != ui32AddrChk)
+ {
+ psInfo->iContiguous = 0;
+ break;
+ }
+ }
+}
+
+static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ struct mm_struct *psMM = psVMArea->vm_mm;
+ IMG_UINT32 ulPFN;
+ spinlock_t *psPTLock;
+ struct page *psPage;
+
+ psPGD = pgd_offset(psMM, ulCPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ return NULL;
+
+ psPUD = pud_offset(psPGD, ulCPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ return NULL;
+
+ psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ return NULL;
+
+ psPage = NULL;
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+ if ((pte_none(*psPTE) != 0) || (pte_present(*psPTE) == 0) || (pte_write(*psPTE) == 0))
+ goto exit_unlock;
+
+ ulPFN = pte_pfn(*psPTE);
+ if (!pfn_valid(ulPFN))
+ goto exit_unlock;
+
+ psPage = pfn_to_page(ulPFN);
+
+ get_page(psPage);
+
+exit_unlock:
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ return psPage;
+#else
+ return NULL;
+#endif
+}
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+ IMG_INT i;
+
+ BUG_ON(psInfo == IMG_NULL);
+
+ switch (psInfo->eType)
+ {
+ case WRAP_TYPE_CLEANUP:
+ break;
+ case WRAP_TYPE_FIND_VMA_PFN:
+ break;
+ case WRAP_TYPE_GET_USER_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+
+
+ if (!PageReserved(psPage))
+ {
+ SetPageDirty(psPage);
+ }
+ page_cache_release(psPage);
+ }
+ break;
+ }
+ case WRAP_TYPE_FIND_VMA_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ if(psInfo->bWrapWorkaround)
+ put_page(psInfo->ppsPages[i]);
+ else
+ put_page_testzero(psInfo->ppsPages[i]);
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ if (psInfo->ppsPages != IMG_NULL)
+ {
+ kfree(psInfo->ppsPages);
+ }
+
+ if (psInfo->psPhysAddr != IMG_NULL)
+ {
+ kfree(psInfo->psPhysAddr);
+ }
+
+ kfree(psInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem,
+ IMG_BOOL bWrapWorkaround)
+{
+ IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+ IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+ IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulAddrRange;
+ IMG_UINT32 ulBeyondEndAddr;
+ IMG_UINT32 ulAddr;
+ IMG_INT iNumPagesMapped;
+ IMG_INT i;
+ struct vm_area_struct *psVMArea;
+ sWrapMemInfo *psInfo;
+
+
+ ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+ ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+ ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+
+ psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+ if (psInfo == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psInfo, 0, sizeof(*psInfo));
+ psInfo->bWrapWorkaround = bWrapWorkaround;
+
+#if defined(DEBUG)
+ psInfo->ulStartAddr = ulStartAddrOrig;
+ psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+ psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+
+ psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+ if (psInfo->psPhysAddr == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error_free;
+ }
+
+
+ psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
+ if (psInfo->ppsPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error_free;
+ }
+
+
+ down_read(¤t->mm->mmap_sem);
+ iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (iNumPagesMapped >= 0)
+ {
+
+ if (iNumPagesMapped != psInfo->iNumPages)
+ {
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, iNumPagesMapped));
+
+
+ for (i = 0; i < iNumPagesMapped; i++)
+ {
+ page_cache_release(psInfo->ppsPages[i]);
+
+ }
+ goto error_free;
+ }
+
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = page_to_pfn(psInfo->ppsPages[i]) << PAGE_SHIFT;
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+ }
+
+ psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+ goto exit_check;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), trying something else", iNumPagesMapped));
+
+
+ down_read(¤t->mm->mmap_sem);
+
+ psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ if (psVMArea == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %lx", ulStartAddrOrig));
+
+ goto error_release_mmap_sem;
+ }
+#if defined(DEBUG)
+ psInfo->psVMArea = psVMArea;
+#endif
+
+
+ if (ulStartAddrOrig < psVMArea->vm_start)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Start address %lx is outside of the region returned by find_vma", ulStartAddrOrig));
+ goto error_release_mmap_sem;
+ }
+
+
+ if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: End address %lx is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+ goto error_release_mmap_sem;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error_release_mmap_sem;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error_release_mmap_sem;
+ }
+
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ struct page *psPage;
+
+ BUG_ON(i >= psInfo->iNumPages);
+
+ psPage = CPUVAddrToPage(psVMArea, ulAddr);
+ if (psPage == NULL)
+ {
+ IMG_INT j;
+
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't lookup page structure for address 0x%lx, trying something else", ulAddr));
+
+
+ for (j = 0; j < i; j++)
+ {
+ if(psInfo->bWrapWorkaround)
+ put_page(psInfo->ppsPages[j]);
+ else
+ put_page_testzero(psInfo->ppsPages[j]);
+ }
+ break;
+ }
+
+ psInfo->ppsPages[i] = psPage;
+ }
+
+ BUG_ON(i > psInfo->iNumPages);
+ if (i == psInfo->iNumPages)
+ {
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+
+ CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
+ }
+ else
+ {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) && defined(PVR_SECURE_HANDLES)
+
+
+
+ if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Region isn't a raw PFN mapping. Giving up."));
+ goto error_release_mmap_sem;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = ((ulAddr - psVMArea->vm_start) + (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+ BUG_ON(i != psInfo->iNumPages);
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
+
+
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Region can't be locked down"));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Raw PFN mappings not supported. Giving up."));
+ goto error_release_mmap_sem;
+#endif
+ }
+
+ up_read(¤t->mm->mmap_sem);
+
+exit_check:
+ CheckPagesContiguous(psInfo);
+
+
+
+ *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+ return PVRSRV_OK;
+
+error_release_mmap_sem:
+ up_read(¤t->mm->mmap_sem);
+error_free:
+ psInfo->eType = WRAP_TYPE_CLEANUP;
+ OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ {
+ IMG_UINT32 ui32i;
+
+ psTimerWorkQueue = create_workqueue("pvr_timer");
+ if (psTimerWorkQueue == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+ return PVRSRV_ERROR_GENERIC;
+
+ }
+
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+ INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ if (psTimerWorkQueue != NULL)
+ {
+ destroy_workqueue(psTimerWorkQueue);
+ }
+#endif
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
new file mode 100644
index 0000000..6126ffd
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
@@ -0,0 +1,109 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ phOsPrivateData,
+ &hBlockAlloc,
+ "Environment per Process Data");
+
+ if (eError != PVRSRV_OK)
+ {
+ *phOsPrivateData = IMG_NULL;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+ psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+
+ LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (hOsPrivateData == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+
+ LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+
+ RemovePerProcessProcDir(psEnvPerProc);
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ hOsPrivateData,
+ psEnvPerProc->hBlockAlloc);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+ if(!gui32ReleasePID)
+ return NULL;
+ return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
new file mode 100644
index 0000000..70a8892
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
@@ -0,0 +1,658 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "sgxmmu.h"
+#include "mm.h"
+#include "pdump_km.h"
+
+#include <linux/tty.h>
+
+static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_UINT32 DbgGetFrame (PDBG_STREAM psStream);
+static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+static IMG_UINT32 DbgWrite (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MIN(a,b) (a > b ? b : a)
+
+#define MAX_FILE_SIZE 0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+ "ScriptStream2",
+ "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+ PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+ IMG_UINT32 ui32ParamFileNum;
+
+ IMG_CHAR *pszMsg;
+ IMG_CHAR *pszScript;
+ IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+ return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+ *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+ if ((!*phScript) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phMsg = (IMG_HANDLE)gsDBGPdumpState.pszMsg;
+ *pui32MaxLen = SZ_MSG_SIZE_MAX;
+ if ((!*phMsg) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszFile = gsDBGPdumpState.pszFile;
+ *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+ if ((!*ppszFile) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+ IMG_CHAR* pszBuf = hBuf;
+ IMG_UINT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+ IMG_UINT32 n;
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+ IMG_UINT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_CHAR* pszBuf = hBuffer;
+ IMG_UINT32 ui32Count = 0;
+
+ while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+ {
+ ui32Count++;
+ }
+ return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_UINT32 ui32Count = 0;
+ IMG_CHAR* pszBuf = hBuffer;
+
+
+ ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+
+ if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+ if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count-1] = '\r';
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+ return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+ PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+ return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+ return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+ return PDumpWriteILock(psStream,
+ psui8Data,
+ ui32Size,
+ ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+
+ PVR_UNREFERENCED_PARAMETER(hStream);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+ if(gpfnDbgDrv)
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+ return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ }
+ else
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ }
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 *pui32PageOffset)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ *pui32PageOffset = sCpuPAddr.uiAddr & (HOST_PAGESIZE() -1);
+ }
+ else
+ {
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ *pui32PageOffset = (IMG_UINT32)pui8LinAddr & (HOST_PAGESIZE() - 1);
+ }
+}
+
+
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+
+ if (!gpfnDbgDrv)
+ {
+ DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+
+ if (gpfnDbgDrv == IMG_NULL)
+ {
+ return;
+ }
+
+ if(!gsDBGPdumpState.pszFile)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+ "Filename string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszMsg)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+ "Message string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszScript)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+ "Script string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+ DEBUG_CAPMODE_FRAMED,
+ DEBUG_OUTMODE_STREAMENABLE,
+ 0,
+ 10);
+
+ gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+ gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+ }
+
+ PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+ PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+ PDUMPCOMMENT("Start of Init Phase");
+ }
+
+ return;
+
+init_failed:
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+ }
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Start Init Phase");
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Stop Init Phase");
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+ if (PDumpSuspended())
+ {
+ return IMG_FALSE;
+ }
+ return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+ IMG_UINT32 ui32Stream;
+
+ for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+ {
+ if (gsDBGPdumpState.psStream[ui32Stream])
+ {
+ DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpGetFrameKM(IMG_PUINT32 pui32Frame)
+{
+ *pui32Frame = DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+
+ return PVRSRV_OK;
+}
+
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Written = 0;
+ IMG_UINT32 ui32Off = 0;
+
+ if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+ {
+ return IMG_TRUE;
+ }
+
+
+
+
+ if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+ {
+ IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+ if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+ {
+ if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+ {
+ DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+ gsDBGPdumpState.ui32ParamFileNum++;
+ }
+ }
+ }
+
+
+ while (((IMG_UINT32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF))
+ {
+ ui32Written = DbgWrite(psStream, &pui8Data[ui32Off], ui32Count, ui32Flags);
+
+
+
+
+ if (ui32Written == 0)
+ {
+ OSReleaseThreadQuanta();
+ }
+
+ if (ui32Written != 0xFFFFFFFF)
+ {
+ ui32Off += ui32Written;
+ ui32Count -= ui32Written;
+ }
+ }
+
+ if (ui32Written == 0xFFFFFFFF)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+
+static IMG_UINT32 DbgGetFrame(PDBG_STREAM psStream)
+{
+ return gpfnDbgDrv->pfnGetFrame(psStream);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+static IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32BytesWritten;
+
+ if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+ {
+
+
+ if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ (psStream->ui32Start == 0xFFFFFFFFUL) &&
+ (psStream->ui32End == 0xFFFFFFFFUL) &&
+ psStream->bInitPhaseComplete)
+ {
+ ui32BytesWritten = ui32BCount;
+ }
+ else
+ {
+ ui32BytesWritten = gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, 1);
+ }
+ }
+ else
+ {
+ if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+ {
+ IMG_UINT32 ui32DbgFlags;
+
+ ui32DbgFlags = 0;
+ if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+ {
+ ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+ }
+
+ ui32BytesWritten = gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, 1, ui32DbgFlags);
+ }
+ else
+ {
+ ui32BytesWritten = gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, 1);
+ }
+ }
+
+ return ui32BytesWritten;
+}
+
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+ atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+ atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
new file mode 100644
index 0000000..10a0201
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
@@ -0,0 +1,63 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+typedef struct
+{
+
+ IMG_UINT32 ui32OpenPID;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+
+ IMG_HANDLE hKernelMemInfo;
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ struct list_head sDRMAuthListItem;
+
+ struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+
+ IMG_UINT64 ui64Stamp;
+#endif
+
+
+ IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ IMG_PVOID pPriv;
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
new file mode 100644
index 0000000..50245a1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
@@ -0,0 +1,962 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+
+
+static struct proc_dir_entry * dir;
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+static off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off);
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off);
+#endif
+
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+ .open = pvr_proc_open,
+ .read = seq_read,
+ .write = pvr_proc_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+ .start = pvr_proc_seq_start,
+ .next = pvr_proc_seq_next,
+ .stop = pvr_proc_seq_stop,
+ .show = pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+ IMG_INT n;
+ size_t space = size - (size_t)off;
+ va_list ap;
+
+ PVR_ASSERT(space >= 0);
+
+ va_start (ap, format);
+
+ n = vsnprintf (buffer+off, space, format, ap);
+
+ va_end (ap);
+
+ if (n >= (IMG_INT)space || n < 0)
+ {
+
+ buffer[size - 1] = 0;
+ return (off_t)(size - 1);
+ }
+ else
+ {
+ return (off + (off_t)n);
+ }
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+
+ if(!off)
+ return (void*)2;
+ return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ if(off == 1)
+ return (void*)2;
+
+ return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+ IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+ struct seq_file *seq = (struct seq_file*)file->private_data;
+ struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+
+ seq->private = pvr_proc_entry->data;
+ return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct proc_dir_entry * dp;
+
+ dp = PDE(inode);
+
+ if (!dp->write_proc)
+ return -EIO;
+
+ return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_TRUE);
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ (*pos)++;
+ if( handlers->next != NULL)
+ return handlers->next( proc_seq_file, v, *pos );
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ handlers->show( proc_seq_file,v );
+ return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+ struct proc_dir_entry *pdir,
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+ return NULL;
+ }
+
+ mode = S_IFREG;
+
+ if (show_handler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file=create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+ PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+
+ file->proc_fops = &pvr_proc_operations;
+ file->write_proc = whandler;
+
+
+ file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+ if(file->data)
+ {
+ seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+ seq_handlers->next = next_handler;
+ seq_handlers->show = show_handler;
+ seq_handlers->off2element = off2element_handler;
+ seq_handlers->startstop = startstop_handler;
+ seq_handlers->data = data;
+
+ return file;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+ return 0;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ )
+{
+ return CreateProcEntrySeq(name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ return CreateProcEntryInDirSeq(
+ dir,
+ name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL
+ );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+ return NULL;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+ return NULL;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+ return NULL;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+ PVRProcDirRoot, ui32PID));
+ return NULL;
+ }
+ }
+ }
+
+ return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+ show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+ if (dir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+ remove_proc_entry(proc_entry->name, dir);
+ if( data)
+ kfree( data );
+
+ }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", proc_entry->name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+ remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+ if(data)
+ kfree( data );
+ }
+}
+
+#endif
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+ IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+ off_t len = pprn (page, (size_t)count, off);
+
+ if (len == END_OF_FILE)
+ {
+ len = 0;
+ *eof = 1;
+ }
+ else if (!len)
+ {
+ *start = (IMG_CHAR *) 0;
+ }
+ else
+ {
+ *start = (IMG_CHAR *) 1;
+ }
+
+ return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!pdir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+ return -ENOMEM;
+ }
+
+ mode = S_IFREG;
+
+ if (rhandler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file = create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ file->read_proc = rhandler;
+ file->write_proc = whandler;
+ file->data = data;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+ return -ENOMEM;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+ return -ENOMEM;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+ struct proc_dir_entry * file;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+ }
+
+ file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+ dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+ g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+ g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+ if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+#else
+ if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+ CreateProcReadEntry("version", procDumpVersion) ||
+ CreateProcReadEntry("nodes", procDumpSysNodes))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+ ProcSeqShowDebugLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRDebugProcSetLevel);
+ if(!g_pProcDebugLevel)
+#else
+ if (CreateProcEntry ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, 0))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+ ProcSeqShowPowerLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRProcSetPowerLevel);
+ if(!g_pProcPowerLevel)
+#else
+ if (CreateProcEntry("power_control", PVRProcGetPowerLevel, PVRProcSetPowerLevel, 0))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+#endif
+#endif
+
+ return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+ if (dir)
+ {
+ remove_proc_entry(name, dir);
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ remove_proc_entry(name, psPerProc->psProcDir);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->psProcDir)
+ {
+ while (psPerProc->psProcDir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+ RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+ }
+ RemoveProcEntry(psPerProc->psProcDir->name);
+ }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_pProcDebugLevel );
+#else
+ RemoveProcEntry("debug_level");
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_pProcPowerLevel );
+#else
+ RemoveProcEntry("power_control");
+#endif
+#endif
+
+#endif
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq(g_pProcQueue);
+ RemoveProcEntrySeq(g_pProcVersion);
+ RemoveProcEntrySeq(g_pProcSysNodes);
+#else
+ RemoveProcEntry("queue");
+ RemoveProcEntry("version");
+ RemoveProcEntry("nodes");
+#endif
+
+ while (dir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+ RemoveProcEntry(dir->subdir->name);
+ }
+
+ remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+ SYS_DATA * psSysData;
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ if(psSysData->pszVersionString)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+#else
+
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off)
+{
+ SYS_DATA *psSysData;
+
+ if (off == 0)
+ {
+ return printAppend(buf, size, 0,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ }
+
+ SysAcquireData(&psSysData)
+
+ if (off == 1)
+ {
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(psSysData->pszVersionString)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ if(strlen(pszSystemVersionString)
+ + strlen("System Version String: \n")
+ + 1 > size)
+ {
+ return 0;
+ }
+ return printAppend(buf, size, 0,
+ "System Version String: %s\n",
+ pszSystemVersionString);
+ }
+
+ return END_OF_FILE;
+}
+
+#endif
+
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+ switch (deviceType)
+ {
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+ return text;
+ }
+ }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+ switch (deviceClass)
+ {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceClass);
+ return text;
+ }
+ }
+}
+
+IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+ SYS_DATA * psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ seq_printf( sfile,
+ "%p %-8s %-8s %4d %2lu %p %3lu %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+
+
+ return (void*)psDevNode;
+}
+
+#else
+
+static
+off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ off_t len;
+
+
+ if (size < 80)
+ {
+ return 0;
+ }
+
+ if (off == 0)
+ {
+ return printAppend(buf, size, 0,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+
+ if (!psDevNode)
+ {
+ return END_OF_FILE;
+ }
+
+ len = printAppend(buf, size, 0,
+ "%p %-8s %-8s %4d %2lu %p %3lu %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+ return (len);
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
new file mode 100644
index 0000000..37849c2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
@@ -0,0 +1,119 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+#include <asm/exec.h>
+#include <asm/cmpxchg.h>
+#include <asm/auxvec.h>
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+ pvr_next_proc_seq_t *next;
+ pvr_show_proc_seq_t *show;
+ pvr_off2element_proc_seq_t *off2element;
+ pvr_startstop_proc_seq_t *startstop;
+ IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+ __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
new file mode 100644
index 0000000..8342891
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
@@ -0,0 +1,647 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#else
+static off_t printLinuxBridgeStats(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+extern struct mutex gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ {
+ IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_ProcBridgeStats = CreateProcReadEntrySeq(
+ "bridge_stats",
+ NULL,
+ ProcSeqNextBridgeStats,
+ ProcSeqShowBridgeStats,
+ ProcSeqOff2ElementBridgeStats,
+ ProcSeqStartstopBridgeStats
+ );
+ iStatus = !g_ProcBridgeStats ? -1 : 0;
+#else
+ iStatus = CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+#endif
+
+ if(iStatus!=0)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq(g_ProcBridgeStats);
+#else
+ RemoveProcEntry("bridge_stats");
+#endif
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ mutex_lock(&gPVRSRVLock);
+ }
+ else
+ {
+ mutex_unlock(&gPVRSRVLock);
+ }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return (void*)0;
+ }
+
+
+ return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Total ioctl call count = %lu\n"
+ "Total number of bytes copied via copy_from_user = %lu\n"
+ "Total number of bytes copied via copy_to_user = %lu\n"
+ "Total number of bytes copied via copy_*_user = %lu\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ return;
+ }
+
+ seq_printf(sfile,
+ "%-45s %-40s %-10lu %-20lu %-10lu\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+}
+
+#else
+
+static off_t
+printLinuxBridgeStats(IMG_CHAR * buffer, size_t count, off_t off)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+ off_t Ret;
+
+ mutex_lock(&gPVRSRVLock);
+
+ if(!off)
+ {
+ if(count < 500)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+ Ret = printAppend(buffer, count, 0,
+ "Total ioctl call count = %lu\n"
+ "Total number of bytes copied via copy_from_user = %lu\n"
+ "Total number of bytes copied via copy_to_user = %lu\n"
+ "Total number of bytes copied via copy_*_user = %lu\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ goto unlock_and_return;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if(count < 300)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ psEntry = &g_BridgeDispatchTable[off-1];
+ Ret = printAppend(buffer, count, 0,
+ "%-45s %-40s %-10lu %-20lu %-10lu\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+
+unlock_and_return:
+ mutex_unlock(&gPVRSRVLock);
+ return Ret;
+}
+#endif
+#endif
+
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+ IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_INT err = -EFAULT;
+
+ mutex_lock(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+ PVR_UNREFERENCED_PARAMETER(ioctlCmd);
+
+ psBridgePackageKM = &sBridgePackageKM;
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+
+ if(OSCopyFromUser(IMG_NULL,
+ psBridgePackageKM,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+#endif
+
+ cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+ switch (cmd)
+ {
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+ {
+ PVRSRV_ERROR eError = MemTest1();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+ {
+ PVRSRV_ERROR eError = MemTest2();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+ {
+ PVRSRV_ERROR eError = ResourceTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+ {
+ PVRSRV_ERROR eError = EventObjectTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+ {
+ PVRSRV_ERROR eError = MemMappingTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+ {
+ PVRSRV_ERROR eError = ProcessIDTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+ {
+ PVRSRV_ERROR eError = ClockusWaitusTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+ {
+ PVRSRV_ERROR eError = TimerTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+ {
+ PVRSRV_ERROR eError = PrivSrvTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+ {
+ IMG_UINT32 ui32PID;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_ERROR eError;
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+
+ eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+
+ *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+ err = 0;
+ goto unlock_and_return;
+ }
+
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+ {
+ PVRSRV_ERROR eError = PowerMgmtTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ }
+#endif
+
+ if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psPerProc,
+ psBridgePackageKM->hKernelServices,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+ __FUNCTION__, eError));
+ goto unlock_and_return;
+ }
+
+ if(psPerProc->ui32PID != ui32PID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+ "belonging to process %d", __FUNCTION__, ui32PID,
+ psPerProc->ui32PID));
+ goto unlock_and_return;
+ }
+ }
+ else
+ {
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if(psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+ "Couldn't create per-process data area"));
+ goto unlock_and_return;
+ }
+ }
+
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+#if defined(PVR_SECURE_FD_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+ "per file descriptor", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+ (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(!psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+ "associated MemInfo handle", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo;
+ break;
+ }
+
+ default:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+ "to use privileged service", __FUNCTION__));
+ goto unlock_and_return;
+ }
+ break;
+ }
+ }
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int authenticated = pFile->authenticated;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (authenticated)
+ {
+ break;
+ }
+
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+ {
+ struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+ if (pFile->master == psDRMFile->master)
+ {
+ authenticated |= psDRMFile->authenticated;
+ if (authenticated)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!authenticated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+ err = -EPERM;
+ goto unlock_and_return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+
+ err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+ if(err != PVRSRV_OK)
+ goto unlock_and_return;
+
+ switch(cmd)
+ {
+#if defined(PVR_SECURE_FD_EXPORT)
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ {
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+ (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+ psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp;
+#endif
+ break;
+ }
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp;
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+ psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+
+unlock_and_return:
+ mutex_unlock(&gPVRSRVLock);
+ return err;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
new file mode 100644
index 0000000..56d1046
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
@@ -0,0 +1,418 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "linkage.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_UINT32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#endif
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static struct mutex gsDebugMutexNonIRQ;
+
+DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ }
+ else
+ {
+ mutex_lock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ }
+ else
+ {
+ mutex_unlock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+ if (USE_SPIN_LOCK)
+ {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ }
+ else
+ {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+ IMG_UINT32 ui32Used;
+ IMG_UINT32 ui32Space;
+ IMG_INT32 i32Len;
+
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+
+
+ return (i32Len < 0 || i32Len >= ui32Space);
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+ mutex_init(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+ BUG();
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end(VArgs);
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start (VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end (VArgs);
+
+ return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFullFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace, bDebug;
+ const IMG_CHAR *pszFileName = pszFullFileName;
+ IMG_CHAR *pszLeafName;
+
+ bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+ bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+ if (bTrace || bDebug)
+ {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+
+ if (bDebug)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+ break;
+ }
+ default:
+ {
+ strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+ break;
+ }
+ }
+ }
+ else
+ {
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+ }
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+
+ if (!bTrace)
+ {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+
+ static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+ IMG_CHAR* pszTruncIter;
+ IMG_CHAR* pszTruncBackInter;
+
+
+ pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+
+ strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+ if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+ IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+ strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+ }
+
+ pszTruncIter = szFileNameRewrite;
+ while(*pszTruncIter++ != 0)
+ {
+ IMG_CHAR* pszNextStartPoint;
+
+ if(
+ !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+ ( *(pszTruncIter-1) == '.') &&
+ ( *(pszTruncIter-2) == '.') &&
+ ( *(pszTruncIter-3) == '/') )
+ ) continue;
+
+
+ pszTruncBackInter = pszTruncIter - 3;
+ while(*(--pszTruncBackInter) != '/')
+ {
+ if(pszTruncBackInter <= szFileNameRewrite) break;
+ }
+ pszNextStartPoint = pszTruncBackInter;
+
+
+ while(*pszTruncIter != 0)
+ {
+ *pszTruncBackInter++ = *pszTruncIter++;
+ }
+ *pszTruncBackInter = 0;
+
+
+ pszTruncIter = pszNextStartPoint;
+ }
+
+ pszFileName = szFileNameRewrite;
+
+ if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+ pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ if (BAppend(pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line, pszFileName))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end (vaArgs);
+ }
+}
+
+#endif
+
+#if defined(DEBUG)
+
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel)
+{
+ printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",(IMG_UINT)uDebugLevel);
+
+ gPVRDebugLevel = uDebugLevel;
+}
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define _PROC_SET_BUFFER_SZ 2
+ IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+ if (count != _PROC_SET_BUFFER_SZ)
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ PVRDebugSetLevel(data_buffer[0] - '0');
+ }
+ return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%lu\n", gPVRDebugLevel);
+}
+
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ if (off == 0) {
+ *start = (IMG_CHAR *)1;
+ return printAppend(page, count, 0, "%lu\n", gPVRDebugLevel);
+ }
+ *eof = 1;
+ return 0;
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100644
index 0000000..f31f989
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
@@ -0,0 +1,301 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "sysconfig.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "proc.h"
+#include "pvrversion.h"
+#include "linkage.h"
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#define MAKENAME_HELPER(x, y) x ## y
+#define MAKENAME(x, y) MAKENAME_HELPER(x, y)
+
+#define PVR_DRM_NAME "pvrsrvkm"
+#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
+
+#define PVR_PCI_IDS \
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0, 0, 0}
+
+struct pci_dev *gpsPVRLDMDev;
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if defined(DISPLAY_CONTROLLER)
+extern int MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+#endif
+
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+ PVR_PCI_IDS
+};
+#endif
+
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+ IMG_INT iRes;
+
+ PVR_TRACE(("PVRSRVDrmLoad"));
+
+ gpsPVRDRMDev = dev;
+ gpsPVRLDMDev = dev->pdev;
+
+#if defined(PDUMP)
+ iRes = dbgdrv_init();
+ if (iRes != 0)
+ {
+ return iRes;
+ }
+#endif
+
+ iRes = PVRCore_Init();
+ if (iRes != 0)
+ {
+ goto exit_dbgdrv_cleanup;
+ }
+
+#if defined(DISPLAY_CONTROLLER)
+ iRes = MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+ if (iRes != 0)
+ {
+ goto exit_pvrcore_cleanup;
+ }
+#endif
+ return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+ PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+ return iRes;
+}
+
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev)
+{
+ PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+ MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+ PVRCore_Cleanup();
+
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+
+ return 0;
+}
+
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+ return PVRSRVOpen(dev, file);
+}
+
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+ PVRSRVRelease(dev, file);
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRDRMPCIBusIDField(struct drm_device *dev, IMG_UINT32 *pui32Field, IMG_UINT32 ui32FieldType)
+{
+ struct pci_dev *psPCIDev = (struct pci_dev *)dev->pdev;
+
+ switch (ui32FieldType)
+ {
+ case PVR_DRM_PCI_DOMAIN:
+ *pui32Field = pci_domain_nr(psPCIDev->bus);
+ break;
+
+ case PVR_DRM_PCI_BUS:
+ *pui32Field = psPCIDev->bus->number;
+ break;
+
+ case PVR_DRM_PCI_DEV:
+ *pui32Field = PCI_SLOT(psPCIDev->devfn);
+ break;
+
+ case PVR_DRM_PCI_FUNC:
+ *pui32Field = PCI_FUNC(psPCIDev->devfn);
+ break;
+
+ default:
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+ IMG_UINT32 ui32Cmd = pui32Args[0];
+ IMG_UINT32 ui32Arg1 = pui32Args[1];
+ IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+
+ switch (ui32Cmd)
+ {
+ case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+ *pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+ break;
+
+ case PVR_DRM_UNPRIV_BUSID_TYPE:
+ *pui32OutArg = PVR_DRM_BUS_TYPE_PCI;
+ break;
+
+ case PVR_DRM_UNPRIV_BUSID_FIELD:
+ return PVRDRMPCIBusIDField(dev, pui32OutArg, ui32Arg1);
+
+ default:
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+ DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+ DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+ DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+#if defined(PDUMP)
+ DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, 0),
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver =
+{
+ .driver_features = 0,
+ .dev_priv_size = 0,
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+ .open = PVRSRVDrmOpen,
+ .postclose = PVRSRVDrmPostClose,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .ioctls = sPVRDrmIoctls,
+ .fops =
+ {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = PVRMMap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+ .pci_driver =
+ {
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+ },
+
+ .name = PVR_DRM_NAME,
+ .desc = PVR_DRM_DESC,
+ .date = PVR_BUILD_DATE,
+ .major = PVRVERSION_MAJ,
+ .minor = PVRVERSION_MIN,
+ .patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(IMG_VOID)
+{
+ IMG_INT iRes;
+ sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+
+ PVRDPFInit();
+
+ iRes = drm_init(&sPVRDrmDriver);
+
+ return iRes;
+}
+
+static IMG_VOID __exit PVRSRVDrmExit(IMG_VOID)
+{
+ drm_exit(&sPVRDrmDriver);
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100644
index 0000000..9f5e931
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
@@ -0,0 +1,65 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVRelease(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define DRI_DRM_STATIC static
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_IOCTL _IO(0, PVR_DRM_SRVKM_CMD)
+#define PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define PVR_DRM_UNPRIV_IOCTL _IO(0, PVR_DRM_UNPRIV_CMD)
+#define PVR_DRM_DBGDRV_IOCTL _IO(0, PVR_DRM_DBGDRV_CMD)
+#endif
+
+#endif
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
new file mode 100644
index 0000000..4e1c97f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
@@ -0,0 +1,633 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK 0x00300000UL
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS 0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001UL
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000010UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000100UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00001000UL
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00010000UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000UL
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000UL
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID 0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK 0x00000002UL
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000008UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000010UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS 0x0ABC
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_MASK 0x00000040UL
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_SHIFT 6
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_PDS_INV2 0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFUL
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000UL
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_TILE0 0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE1 0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE2 0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE3 0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE4 0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE5 0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE6 0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE7 0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE8 0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE9 0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
+#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8 0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9 0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10 0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11 0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12 0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13 0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14 0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15 0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK 0x000003FFUL
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT 0
+#define EUR_CR_BIF_BANK0 0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FUL
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK 0x000000F0UL
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK 0x00000F00UL
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK 0x0000F000UL
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK 0x000F0000UL
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_BANK1 0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FUL
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK 0x000000F0UL
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK 0x00000F00UL
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000UL
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK 0x000F0000UL
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_ADT_TTE 0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK 0x000000FFUL
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT 0
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1 0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2 0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_CONFIG 0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FUL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0UL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000UL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_BANK_STATUS 0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001UL
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002UL
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFUL
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000UL
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EUL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFUL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_SOCIF 0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK 0x000000FFUL
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT 0
+#define EUR_CR_2D_ALPHA 0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK 0x0000FF00UL
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFUL
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x01FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x06000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#define EUR_CR_MNE_CR_CTRL 0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK 0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
new file mode 100755
index 0000000..92a19f9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
@@ -0,0 +1,586 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x000C0000UL
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000UL
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2 0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK 0x000C0000UL
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000UL
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS 0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002UL
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000004UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK 0x00000008UL
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT 3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK 0x00000010UL
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00000020UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK 0x00000040UL
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK 0x00000080UL
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK 0x00000100UL
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200UL
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400UL
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800UL
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000UL
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000UL
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000UL
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000UL
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000UL
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000UL
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000UL
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000UL
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000UL
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT 6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000UL
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+#define EUR_CR_POWER 0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001UL
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
+#define EUR_CR_CORE_ID 0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK 0x00000002UL
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK 0x00000008UL
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK 0x00000010UL
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK 0x00000040UL
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT 6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000080UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK 0x00000100UL
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT 8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK 0x00000200UL
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT 9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400UL
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800UL
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK 0x00001000UL
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT 12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK 0x00002000UL
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT 13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK 0x00004000UL
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT 14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00008000UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000UL
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER 0x0144
+#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFUL
+#define EUR_CR_TIMER_VALUE_SHIFT 0
+#define EUR_CR_EVENT_KICK1 0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFUL
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICK2 0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_EVENT_KICK3 0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFUL
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000UL
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000UL
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0UL
+#define EUR_CR_BIF_FAULT_SB_SHIFT 4
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFUL
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000UL
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EUL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFUL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL 0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK 0x00010000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT 16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK 0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT 15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK 0x00007800UL
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT 11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK 0x00000400UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT 10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK 0x000003E0UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT 5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK 0x00000010UL
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT 4
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK 0x0000000EUL
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT 1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT 0
+#define EUR_CR_MNE_CR_USE_INVAL 0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK 0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT 0
+#define EUR_CR_MNE_CR_STAT 0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK 0x00000400UL
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT 10
+#define EUR_CR_MNE_CR_STAT_READS_MASK 0x000003FFUL
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS 0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK 0x000FFFF0UL
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT 4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK 0x0000000FUL
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT 0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK 0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_STATUS 0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_CLEAR 0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
new file mode 100755
index 0000000..cad51f5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
@@ -0,0 +1,828 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX545DEFS_KM_H_
+#define _SGX545DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL2 0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK 0x000C0000UL
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000UL
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_MASK 0x00C00000UL
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_SHIFT 22
+#define EUR_CR_CLKGATESTATUS 0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002UL
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000004UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK 0x00000008UL
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT 3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK 0x00000010UL
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00000020UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK 0x00000040UL
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_MASK 0x00000080UL
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK 0x00000100UL
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200UL
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400UL
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800UL
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000UL
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000UL
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000UL
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000UL
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000UL
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000UL
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000UL
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_MASK 0x00080000UL
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_SHIFT 19
+#define EUR_CR_CLKGATECTLOVR 0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK 0x000000C0UL
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT 6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK 0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00000C00UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK 0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_SHIFT 14
+#define EUR_CR_CORE_ID 0x001C
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0020
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0024
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000002UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000004UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000008UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000010UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000020UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0AD8
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_EVENT_KICK1 0x0AE4
+#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFUL
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICK2 0x0AE8
+#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICK3 0x0AEC
+#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001UL
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00000800UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK 0x0000FFFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000UL
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000UL
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK 0x0000000FUL
+#define EUR_CR_BIF_FAULT_CID_SHIFT 0
+#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0UL
+#define EUR_CR_BIF_FAULT_SB_SHIFT 4
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+#define EUR_CR_BIF_TILE0 0x0C0C
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE1 0x0C10
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE2 0x0C14
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE3 0x0C18
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE4 0x0C1C
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE5 0x0C20
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE6 0x0C24
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE7 0x0C28
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE8 0x0C2C
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE9 0x0C30
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
+
+#else
+
+#define EUR_CR_BIF_TILE0 0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE1 0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE2 0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE3 0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE4 0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE5 0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE6 0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE7 0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE8 0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE9 0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK 0x00FFF000UL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
+#endif
+
+#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8 0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9 0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10 0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11 0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12 0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13 0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14 0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15 0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK 0x00000001UL
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK 0x0000000CUL
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010UL
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK 0x000000C0UL
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100UL
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200UL
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK0 0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FUL
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK 0x000000F0UL
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK 0x00000F00UL
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK 0x0000F000UL
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK 0x000F0000UL
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_BANK1 0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FUL
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK 0x000000F0UL
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK 0x00000F00UL
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000UL
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK 0x000F0000UL
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_BANK_STATUS 0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001UL
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002UL
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+
+#define EUR_CR_BIF_36BIT_ADDRESSING 0x0CCC
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK 0x00000001UL
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_SHIFT 0
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+#define EUR_CR_BIF_TILE0_MIN 0x0CD0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE1_MIN 0x0CD4
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE2_MIN 0x0CD8
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE3_MIN 0x0CDC
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE4_MIN 0x0CE0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE5_MIN 0x0CE4
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE6_MIN 0x0CE8
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE7_MIN 0x0CEC
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE8_MIN 0x0CF0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_TILE9_MIN 0x0CF4
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x000FFFFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
+#endif
+
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x01FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x06000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL 0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK 0x00010000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT 16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK 0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT 15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK 0x00007800UL
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT 11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK 0x00000400UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT 10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK 0x000003E0UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT 5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK 0x00000010UL
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT 4
+
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK 0x0000000EUL
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT 1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT 0
+#define EUR_CR_MNE_CR_USE_INVAL 0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK 0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT 0
+#define EUR_CR_MNE_CR_STAT 0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK 0x00000400UL
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT 10
+#define EUR_CR_MNE_CR_STAT_READS_MASK 0x000003FFUL
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS 0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK 0x000FFFF0UL
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT 4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK 0x0000000FUL
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT 0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK 0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_STATUS 0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_CLEAR 0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK 0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
new file mode 100644
index 0000000..c496765
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define _SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX541)
+#include "sgx541defs.h"
+#else
+#if defined(SGX543)
+#include "sgx543defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX541)
+#if SGX_CORE_REV == 100
+#include "sgx541_100mpdefs.h"
+#else
+#include "sgx541mpdefs.h"
+#endif
+#else
+#include "sgxmpdefs.h"
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
new file mode 100644
index 0000000..dee5b43
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
@@ -0,0 +1,310 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX520 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 103
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 111
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 125
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX530 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX531 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 111
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22693
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22997
+ #define FIX_HW_BRN_23030
+ #else
+ #if SGX_CORE_REV == 1111
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22693
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22997
+ #define FIX_HW_BRN_23030
+ #else
+ #if SGX_CORE_REV == 112
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22693
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22997
+ #define FIX_HW_BRN_23030
+ #else
+ #if SGX_CORE_REV == 113
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 126
+ #define FIX_HW_BRN_22934
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_25499
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX540 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
+ #if defined(SGX_FEATURE_MP)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_27270
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_27510
+
+ #else
+ #if SGX_CORE_REV == 101
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX541 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+ #else
+ #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
+ #endif
+#endif
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+ #if defined(SGX_FEATURE_MP)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX543 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+ #else
+ #error "sgxerrata.h: SGX543 only supports MP configs (SGX_FEATURE_MP)"
+ #endif
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_27266
+ #define FIX_HW_BRN_27456
+ #else
+ #if SGX_CORE_REV == 109
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX545 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+ #warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+ #pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
new file mode 100644
index 0000000..0672ad6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
@@ -0,0 +1,159 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(SGX520)
+ #define SGX_CORE_FRIENDLY_NAME "SGX520"
+ #define SGX_CORE_ID SGX_CORE_ID_520
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX530)
+ #define SGX_CORE_FRIENDLY_NAME "SGX530"
+ #define SGX_CORE_ID SGX_CORE_ID_530
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX535)
+ #define SGX_CORE_FRIENDLY_NAME "SGX535"
+ #define SGX_CORE_ID SGX_CORE_ID_535
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+ #define SUPPORT_SGX_VIDEO_HEAP
+#else
+#if defined(SGX540)
+ #define SGX_CORE_FRIENDLY_NAME "SGX540"
+ #define SGX_CORE_ID SGX_CORE_ID_540
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX541)
+ #define SGX_CORE_FRIENDLY_NAME "SGX541"
+ #define SGX_CORE_ID SGX_CORE_ID_541
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX543)
+ #define SGX_CORE_FRIENDLY_NAME "SGX543"
+ #define SGX_CORE_ID SGX_CORE_ID_543
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_DATA_BREAKPOINTS
+#else
+#if defined(SGX531)
+ #define SGX_CORE_FRIENDLY_NAME "SGX531"
+ #define SGX_CORE_ID SGX_CORE_ID_531
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX545)
+ #define SGX_CORE_FRIENDLY_NAME "SGX545"
+ #define SGX_CORE_ID SGX_CORE_ID_545
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_VOLUME_TEXTURES
+ #define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+ #define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_ZLS_EXTERNALZ
+ #define SGX_FEATURE_VDM_CONTEXT_SWITCH_REV_2
+ #define SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2
+ #define SGX_FEATURE_NUM_PDS_PIPES (2)
+ #define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+ #define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512)
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+ #define SGX_FEATURE_DCU
+
+
+ #define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_27456)
+#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+#endif
+
+#if defined(FIX_HW_BRN_22934) \
+ || defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(SGX_FEATURE_36BIT_MMU)
+ #error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+ #endif
+ #if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ #define SGX_BYPASS_SYSTEM_CACHE
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if !defined(SGX_FEATURE_MP_CORE_COUNT)
+#error SGX_FEATURE_MP_CORE_COUNT must be defined when SGX_FEATURE_MP is defined
+#endif
+#else
+#define SGX_FEATURE_MP_CORE_COUNT (1)
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
new file mode 100644
index 0000000..c6b4c0d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
@@ -0,0 +1,75 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT (12)
+#define SGX_MMU_PAGE_SIZE (1UL<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1UL)
+
+#define SGX_MMU_PD_SHIFT (10)
+#define SGX_MMU_PD_SIZE (1UL<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK (0xFFC00000UL)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFFF00UL)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFF000UL)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PDE_VALID (0x00000001UL)
+#define SGX_MMU_PDE_PAGE_SIZE_4K (0x00000000UL)
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ #define SGX_MMU_PDE_PAGE_SIZE_16K (0x00000002UL)
+ #define SGX_MMU_PDE_PAGE_SIZE_64K (0x00000004UL)
+ #define SGX_MMU_PDE_PAGE_SIZE_256K (0x00000006UL)
+ #define SGX_MMU_PDE_PAGE_SIZE_1M (0x00000008UL)
+ #define SGX_MMU_PDE_PAGE_SIZE_4M (0x0000000AUL)
+ #define SGX_MMU_PDE_PAGE_SIZE_MASK (0x0000000EUL)
+#else
+ #define SGX_MMU_PDE_WRITEONLY (0x00000002UL)
+ #define SGX_MMU_PDE_READONLY (0x00000004UL)
+ #define SGX_MMU_PDE_CACHECONSISTENT (0x00000008UL)
+ #define SGX_MMU_PDE_EDMPROTECT (0x00000010UL)
+#endif
+
+#define SGX_MMU_PT_SHIFT (10)
+#define SGX_MMU_PT_SIZE (1UL<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK (0x003FF000UL)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFFF00UL)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFF000UL)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PTE_VALID (0x00000001UL)
+#define SGX_MMU_PTE_WRITEONLY (0x00000002UL)
+#define SGX_MMU_PTE_READONLY (0x00000004UL)
+#define SGX_MMU_PTE_CACHECONSISTENT (0x00000008UL)
+#define SGX_MMU_PTE_EDMPROTECT (0x00000010UL)
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
new file mode 100644
index 0000000..c792292
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
@@ -0,0 +1,214 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif
+
+typedef struct _BM_HEAP_ BM_HEAP;
+
+struct _BM_MAPPING_
+{
+ enum
+ {
+ hm_wrapped = 1,
+ hm_wrapped_scatter,
+ hm_wrapped_virtaddr,
+ hm_wrapped_scatter_virtaddr,
+ hm_env,
+ hm_contiguous
+ } eCpuMemoryOrigin;
+
+ BM_HEAP *pBMHeap;
+ RA_ARENA *pArena;
+
+ IMG_CPU_VIRTADDR CpuVAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+ IMG_SYS_PHYADDR *psSysAddr;
+ IMG_SIZE_T uSize;
+ IMG_HANDLE hOSMemHandle;
+ IMG_UINT32 ui32Flags;
+};
+
+typedef struct _BM_BUF_
+{
+ IMG_CPU_VIRTADDR *CpuVAddr;
+ IMG_VOID *hOSMemHandle;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+
+ BM_MAPPING *pMapping;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+ IMG_UINT32 ui32Attribs;
+ BM_CONTEXT *pBMContext;
+ RA_ARENA *pImportArena;
+ RA_ARENA *pLocalDevMemArena;
+ RA_ARENA *pVMArena;
+ DEV_ARENA_DESCRIPTOR sDevArena;
+ MMU_HEAP *pMMUHeap;
+
+ struct _BM_HEAP_ *psNext;
+ struct _BM_HEAP_ **ppsThis;
+};
+
+struct _BM_CONTEXT_
+{
+ MMU_CONTEXT *psMMUContext;
+
+
+ BM_HEAP *psBMHeap;
+
+
+ BM_HEAP *psBMSharedHeap;
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ HASH_TABLE *pBufferHash;
+
+
+ IMG_HANDLE hResItem;
+
+ IMG_UINT32 ui32RefCount;
+
+
+
+ struct _BM_CONTEXT_ *psNext;
+ struct _BM_CONTEXT_ **ppsThis;
+};
+
+
+
+typedef IMG_VOID *BM_HANDLE;
+
+#define BP_POOL_MASK 0x7
+
+#define BP_CONTIGUOUS (1 << 3)
+#define BP_PARAMBUFFER (1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS 2
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated);
+
+
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+ IMG_BOOL *pbCreated);
+
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL
+BM_Alloc (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_HANDLE *phBuf);
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf);
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags);
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+IMG_BOOL
+BM_ContiguousStatistics (IMG_UINT32 uFlags,
+ IMG_UINT32 *pTotalBytes,
+ IMG_UINT32 *pAvailableBytes);
+
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
new file mode 100644
index 0000000..c7fa61c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
@@ -0,0 +1,274 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "ra.h"
+#include "resman.h"
+
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
+#define DEVICE_MEMORY_HEAP_KERNEL 1
+#define DEVICE_MEMORY_HEAP_SHARED 2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+
+ IMG_UINT32 ui32HeapID;
+
+
+ IMG_CHAR *pszName;
+
+
+ IMG_CHAR *pszBSName;
+
+
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+
+
+ IMG_UINT32 ui32HeapSize;
+
+
+ IMG_UINT32 ui32Attribs;
+
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_HANDLE hDevMemHeap;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+
+ IMG_UINT32 ui32AddressSpaceSizeLog2;
+
+
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_UINT32 ui32HeapCount;
+
+
+ IMG_UINT32 ui32SyncHeapID;
+
+
+ IMG_UINT32 ui32MappingHeapID;
+
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ BM_CONTEXT *pBMKernelContext;
+
+
+ BM_CONTEXT *pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+ IMG_UINT32 ui32HeapID;
+
+ IMG_CHAR *pszName;
+
+ IMG_DEV_VIRTADDR BaseDevVAddr;
+
+ IMG_UINT32 ui32Size;
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+ IMG_UINT32 ui32RefCount;
+
+
+
+
+ PVRSRV_ERROR (*pfnInitDevice) (IMG_VOID*);
+
+ PVRSRV_ERROR (*pfnDeInitDevice) (IMG_VOID*);
+
+
+ PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+
+ PVRSRV_ERROR (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+ IMG_VOID (*pfnMMUFinalise)(MMU_CONTEXT*);
+ IMG_VOID (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+ MMU_HEAP* (*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**);
+ IMG_VOID (*pfnMMUDelete)(MMU_HEAP*);
+ IMG_BOOL (*pfnMMUAlloc)(MMU_HEAP*pMMU,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+ IMG_VOID (*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+ IMG_VOID (*pfnMMUEnable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUDisable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUMapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapShadow)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR dev_vaddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID (*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_DEV_PHYADDR (*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+ IMG_DEV_PHYADDR (*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+
+
+ IMG_BOOL (*pfnDeviceISR)(IMG_VOID*);
+
+ IMG_VOID *pvISRData;
+
+ IMG_UINT32 ui32SOCInterruptBit;
+
+ IMG_VOID (*pfnDeviceMISR)(IMG_VOID*);
+
+
+ IMG_VOID (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+ IMG_BOOL bReProcessDeviceCommandComplete;
+
+
+ DEVICE_MEMORY_INFO sDevMemoryInfo;
+
+
+ IMG_VOID *pvDevice;
+ IMG_UINT32 ui32pvDeviceSize;
+
+
+ PRESMAN_CONTEXT hResManContext;
+
+
+ PSYS_DATA psSysData;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+ IMG_UINT32 ui32Flags;
+
+ struct _PVRSRV_DEVICE_NODE_ *psNext;
+ struct _PVRSRV_DEVICE_NODE_ **ppsThis;
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+#endif
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+#endif
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
new file mode 100644
index 0000000..ffa952f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
@@ -0,0 +1,378 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+ PVRSRV_HANDLE_TYPE_NONE = 0,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_TYPE_MMAP_INFO,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#ifdef PVR_SECURE_HANDLES
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(hParent);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *peType = PVRSRV_HANDLE_TYPE_NONE;
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+
+ *phParent = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ *ppsBase = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+ (IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+ (IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
new file mode 100644
index 0000000..26c8e44
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+#ifdef HASH_TRACE
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
new file mode 100644
index 0000000..70ef61d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
@@ -0,0 +1,172 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+#include <stdarg.h>
+#include "img_types.h"
+
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+ while(psHead)\
+ {\
+ pfnCallBack(psHead);\
+ psHead = psHead->psNext;\
+ }\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+ va_list ap;\
+ while(psHead)\
+ {\
+ va_start(ap, pfnCallBack);\
+ pfnCallBack(psHead, ap);\
+ psHead = psHead->psNext;\
+ va_end(ap);\
+ }\
+}
+
+
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+ IMG_VOID *pResult;\
+ TYPE *psNextNode;\
+ pResult = IMG_NULL;\
+ psNextNode = psHead;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ pResult = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ IMG_VOID* pResult = IMG_NULL;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ pResult = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+ RTYPE result;\
+ TYPE *psNextNode;\
+ result = CONTINUE;\
+ psNextNode = psHead;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ result = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ RTYPE result = CONTINUE;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ result = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+ (*psNode->ppsThis)=psNode->psNext;\
+ if(psNode->psNext)\
+ {\
+ psNode->psNext->ppsThis = psNode->ppsThis;\
+ }\
+}
+
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+ psNewNode->ppsThis = ppsHead;\
+ psNewNode->psNext = *ppsHead;\
+ *ppsHead = psNewNode;\
+ if(psNewNode->psNext)\
+ {\
+ psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+ }\
+}
+
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
new file mode 100644
index 0000000..1ea12de
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
@@ -0,0 +1,126 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct
+{
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Stop;
+ IMG_UINT32 ui32Total;
+ IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[];
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY 0
+
+#define PVRSRV_TIMER_EXAMPLE_1 1
+#define PVRSRV_TIMER_EXAMPLE_2 2
+
+
+#define PVRSRV_NUM_TIMERS (PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X) { \
+ asTimers[X].ui32Count += 1; \
+ asTimers[X].ui32Count |= 0x80000000L; \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ asTimers[X].ui32Stop = 0; \
+ }
+
+#define PVRSRV_TIME_SUSPEND(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ }
+
+#define PVRSRV_TIME_RESUME(X) { \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ }
+
+#define PVRSRV_TIME_STOP(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+ asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+ }
+
+#define PVRSRV_TIME_RESET(X) { \
+ asTimers[X].ui32Start = 0; \
+ asTimers[X].ui32Stop = 0; \
+ asTimers[X].ui32Total = 0; \
+ asTimers[X].ui32Count = 0; \
+ }
+
+
+#if defined(__sh__)
+
+#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+
+#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28))
+#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32))
+#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+
+#define TIMER_DIVISOR 4
+
+#endif
+
+
+
+
+
+#else
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
new file mode 100644
index 0000000..7a0b064
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
@@ -0,0 +1,483 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#endif
+
+
+
+ #define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID 0xffffffffL
+#define POWER_MANAGER_ID 0xfffffffeL
+#define ISR_ID 0xfffffffdL
+#define TIMER_ID 0xfffffffcL
+
+
+#define HOST_PAGESIZE OSGetPageSize
+#define HOST_PAGEMASK (~(HOST_PAGESIZE()-1))
+#define HOST_PAGEALIGN(addr) (((addr)+HOST_PAGESIZE()-1)&HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK 0xf
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+
+
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_VOID *pvRangeAddrStart,
+ IMG_VOID *pvRangeAddrEnd);
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+
+#if defined(__linux__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__)
+ *ppvCpuVAddr = IMG_NULL;
+ return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes, ui32Flags, phOSMemHandle);
+#else
+ extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+
+ return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+#endif
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__)
+ OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+#endif
+
+ return PVRSRV_OK;
+}
+#else
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ *phOSMemHandleRet = hOSMemHandle;
+ return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_UINT32 OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+ (PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+ #define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+ (PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
+ OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ (PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+
+ #define OSAllocPages OSAllocPages_Impl
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+
+ typedef struct
+ {
+ IMG_UINT8 sGuardRegionBefore[8];
+ IMG_CHAR sFileName[128];
+ IMG_UINT32 uLineNo;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uSizeParityCheck;
+ enum valid_tag
+ { isFree = 0x277260FF,
+ isAllocated = 0x260511AA
+ } eValid;
+ } OSMEM_DEBUG_INFO;
+
+ #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+ #define TEST_BUFFER_PADDING_AFTER (8)
+ #define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+ #define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+ #define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+ #define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSAllocMem_Impl(flags, size, addr, blockAlloc)
+ #define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+
+#if defined(__linux__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_SIZE_T ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_SIZE_T ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ sCpuPAddr.uiAddr = 0;
+ return sCpuPAddr;
+}
+#endif
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...);
+#define OSStringLength(pszString) strlen(pszString)
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
+ PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM);
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T ui32Size,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T ui32Size, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_SYS_PHYADDR sCPUPhysAddr,
+ IMG_SIZE_T uiSizeInBytes,
+ IMG_UINT32 ui32CacheFlags,
+ IMG_PVOID *ppvUserAddr,
+ IMG_SIZE_T *puiActualSize,
+ IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *pui32Bytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+ HOST_PCI_INIT_FLAG_BUS_MASTER = 0x00000001,
+ HOST_PCI_INIT_FLAG_MSI = 0x00000002,
+ HOST_PCI_INIT_FLAG_FORCE_I32 = 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+ PVR_VERIFY_WRITE = 0,
+ PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+#if defined(__linux__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem,
+ IMG_BOOL bWrapWorkaround);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem,
+ IMG_BOOL bWrapWorkaround)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+ PVR_UNREFERENCED_PARAMETER(bWrapWorkaround);
+ return PVRSRV_OK;
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#define OS_SUPPORTS_IN_LISR
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+ return in_irq();
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
new file mode 100644
index 0000000..a23b983
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
@@ -0,0 +1,72 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
new file mode 100644
index 0000000..31f7aa2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
@@ -0,0 +1,448 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+#if defined(LINUX)
+#define COMMON_PDUMP_OS_SUPPORT
+#endif
+
+#if defined(COMMON_PDUMP_OS_SUPPORT)
+#if defined(SUPPORT_SGX) || defined(SUPPORT_MSVDX)
+#define SGX_SUPPORT_COMMON_PDUMP
+#if defined(SGX_SUPPORT_COMMON_PDUMP)
+#include <pdump_osfunc.h>
+#endif
+
+#endif
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PDUMP_FLAGS_NEVER 0x08000000UL
+#define PDUMP_FLAGS_TOOUT2MEM 0x10000000UL
+#define PDUMP_FLAGS_LASTFRAME 0x20000000UL
+#define PDUMP_FLAGS_RESETLFBUFFER 0x40000000UL
+#define PDUMP_FLAGS_CONTINUOUS 0x80000000UL
+
+#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+
+#define PDUMP_STREAM_PARAM2 0
+#define PDUMP_STREAM_SCRIPT2 1
+#define PDUMP_STREAM_DRIVERINFO 2
+#define PDUMP_NUM_STREAMS 3
+
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo) (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo) (((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)hMemInfo)->sMemBlk.hBuffer))->pMapping)
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+ IMG_PVOID pvAltLinAddr,
+ IMG_PVOID pvLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+ IMG_VOID PDumpInitCommon(IMG_VOID);
+ IMG_VOID PDumpDeInitCommon(IMG_VOID);
+ IMG_VOID PDumpInit(IMG_VOID);
+ IMG_VOID PDumpDeInit(IMG_VOID);
+ PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+ PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+ IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+ IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+ IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+ IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ IMG_BOOL PDumpIsSuspended(IMG_VOID);
+
+#if defined(SGX_SUPPORT_COMMON_PDUMP) || !defined(SUPPORT_VGX)
+
+ PVRSRV_ERROR PDumpRegKM(IMG_UINT32 dwReg,
+ IMG_UINT32 dwData);
+ PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...);
+ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+ IMG_CHAR* pszFormat,
+ ...);
+
+ PVRSRV_ERROR PDumpPDReg(IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32dwData,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+#else
+ IMG_VOID PDumpRegKM(IMG_UINT32 dwReg,
+ IMG_UINT32 dwData);
+ IMG_VOID PDumpComment(IMG_CHAR* pszFormat, ...);
+ IMG_VOID PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+ IMG_CHAR* pszFormat,
+ ...);
+
+
+ IMG_VOID PDumpPDReg(IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32dwData,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+#endif
+
+ IMG_VOID PDumpMsvdxRegRead(const IMG_CHAR* const pRegRegion,
+ const IMG_UINT32 dwRegOffset);
+
+ IMG_VOID PDumpMsvdxRegWrite(const IMG_CHAR* const pRegRegion,
+ const IMG_UINT32 dwRegOffset,
+ const IMG_UINT32 dwData);
+
+ PVRSRV_ERROR PDumpMsvdxRegPol(const IMG_CHAR* const pRegRegion,
+ const IMG_UINT32 ui32Offset,
+ const IMG_UINT32 ui32CheckFuncIdExt,
+ const IMG_UINT32 ui32RequValue,
+ const IMG_UINT32 ui32Enable,
+ const IMG_UINT32 ui32PollCount,
+ const IMG_UINT32 ui32TimeOut);
+
+ PVRSRV_ERROR PDumpMsvdxWriteRef(const IMG_CHAR* const pRegRegion,
+ const IMG_UINT32 ui32VLROffset,
+ const IMG_UINT32 ui32Physical );
+
+ IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+ IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+ IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_PUINT32 pui32PhysPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_VOID *pvPDCPUAddr);
+ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType);
+
+ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+
+ IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+
+#if defined (COMMON_PDUMP_OS_SUPPORT) && !defined(SUPPORT_VGX)
+
+ PVRSRV_ERROR PDumpTASignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpRegRead(const IMG_UINT32 dwRegOffset, IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpCycleCountRegRead(const IMG_UINT32 dwRegOffset, IMG_BOOL bLastFrame);
+
+ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+ PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_ *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved);
+ PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+#else
+ IMG_VOID PDumpTASignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+ IMG_VOID PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+ IMG_VOID PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ IMG_VOID PDumpRegRead(const IMG_UINT32 dwRegOffset, IMG_UINT32 ui32Flags);
+ IMG_VOID PDumpCycleCountRegRead(const IMG_UINT32 dwRegOffset, IMG_BOOL bLastFrame);
+
+ IMG_VOID PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+ IMG_VOID PDumpIDL(IMG_UINT32 ui32Clocks);
+
+
+ IMG_VOID PDumpMallocPages(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID PDumpMallocPageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID PDumpFreePages(struct _BM_HEAP_ *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved);
+ IMG_VOID PDumpFreePageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT IMG_VOID PDumpHWPerfCBKM(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ IMG_VOID PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+#endif
+
+ IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID PDumpSuspendKM(IMG_VOID);
+ IMG_VOID PDumpResumeKM(IMG_VOID);
+
+ #define PDUMPMEMPOL PDumpMemPolKM
+ #define PDUMPMEM PDumpMemKM
+ #define PDUMPMEM2 PDumpMem2KM
+ #define PDUMPMEMUM PDumpMemUM
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT PDumpDeInitCommon
+ #define PDUMPISLASTFRAME PDumpIsLastCaptureFrameKM
+ #define PDUMPTESTFRAME PDumpIsCaptureFrameKM
+ #define PDUMPTESTNEXTFRAME PDumpTestNextFrame
+ #define PDUMPREGWITHFLAGS PDumpRegWithFlagsKM
+ #define PDUMPREG PDumpRegKM
+ #define PDUMPCOMMENT PDumpComment
+ #define PDUMPCOMMENTWITHFLAGS PDumpCommentWithFlags
+ #define PDUMPREGPOL PDumpRegPolKM
+ #define PDUMPREGPOLWITHFLAGS PDumpRegPolWithFlagsKM
+ #define PDUMPMALLOCPAGES PDumpMallocPages
+ #define PDUMPMALLOCPAGETABLE PDumpMallocPageTable
+ #define PDUMPSETMMUCONTEXT PDumpSetMMUContext
+ #define PDUMPCLEARMMUCONTEXT PDumpClearMMUContext
+ #define PDUMPFREEPAGES PDumpFreePages
+ #define PDUMPFREEPAGETABLE PDumpFreePageTable
+ #define PDUMPPDREG PDumpPDReg
+ #define PDUMPPDREGWITHFLAGS PDumpPDRegWithFlags
+ #define PDUMPCBP PDumpCBP
+ #define PDUMPMALLOCPAGESPHYS PDumpMallocPagesPhys
+ #define PDUMPENDINITPHASE PDumpStopInitPhaseKM
+ #define PDUMPMSVDXREGWRITE PDumpMsvdxRegWrite
+ #define PDUMPMSVDXREGREAD PDumpMsvdxRegRead
+ #define PDUMPMSVDXPOL PDumpMsvdxRegPol
+ #define PDUMPMSVDXWRITEREF PDumpMsvdxWriteRef
+ #define PDUMPBITMAPKM PDumpBitmapKM
+ #define PDUMPDRIVERINFO PDumpDriverInfoKM
+ #define PDUMPIDLWITHFLAGS PDumpIDLWithFlags
+ #define PDUMPIDL PDumpIDL
+ #define PDUMPSUSPEND PDumpSuspendKM
+ #define PDUMPRESUME PDumpResumeKM
+
+#else
+ #if ((defined(LINUX) || defined(GCC_IA32)) || defined(GCC_ARM))
+ #define PDUMPMEMPOL(args...)
+ #define PDUMPMEM(args...)
+ #define PDUMPMEM2(args...)
+ #define PDUMPMEMUM(args...)
+ #define PDUMPINIT(args...)
+ #define PDUMPDEINIT(args...)
+ #define PDUMPISLASTFRAME(args...)
+ #define PDUMPTESTFRAME(args...)
+ #define PDUMPTESTNEXTFRAME(args...)
+ #define PDUMPREGWITHFLAGS(args...)
+ #define PDUMPREG(args...)
+ #define PDUMPCOMMENT(args...)
+ #define PDUMPREGPOL(args...)
+ #define PDUMPREGPOLWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGES(args...)
+ #define PDUMPMALLOCPAGETABLE(args...)
+ #define PDUMPSETMMUCONTEXT(args...)
+ #define PDUMPCLEARMMUCONTEXT(args...)
+ #define PDUMPFREEPAGES(args...)
+ #define PDUMPFREEPAGETABLE(args...)
+ #define PDUMPPDREG(args...)
+ #define PDUMPPDREGWITHFLAGS(args...)
+ #define PDUMPSYNC(args...)
+ #define PDUMPCOPYTOMEM(args...)
+ #define PDUMPWRITE(args...)
+ #define PDUMPCBP(args...)
+ #define PDUMPCOMMENTWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGESPHYS(args...)
+ #define PDUMPENDINITPHASE(args...)
+ #define PDUMPMSVDXREG(args...)
+ #define PDUMPMSVDXREGWRITE(args...)
+ #define PDUMPMSVDXREGREAD(args...)
+ #define PDUMPMSVDXPOLEQ(args...)
+ #define PDUMPMSVDXPOL(args...)
+ #define PDUMPBITMAPKM(args...)
+ #define PDUMPDRIVERINFO(args...)
+ #define PDUMPIDLWITHFLAGS(args...)
+ #define PDUMPIDL(args...)
+ #define PDUMPSUSPEND(args...)
+ #define PDUMPRESUME(args...)
+ #define PDUMPMSVDXWRITEREF(args...)
+ #else
+ #error Compiler not specified
+ #endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
new file mode 100644
index 0000000..eb2197f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
@@ -0,0 +1,133 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PDUMP_OSFUNC_H__
+#define __PDUMP_OSFUNC_H__
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_HANDLE hMsg; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetMessageString(&hMsg, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLenScript; \
+ IMG_UINT32 ui32MaxLenFileName; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+ if(eError != PVRSRV_OK) return eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+ if(eError != PVRSRV_OK) return eError;
+
+
+
+ PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+
+
+#define PDUMP_va_list va_list
+#define PDUMP_va_start va_start
+#define PDUMP_va_end va_end
+
+
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...);
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...);
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...);
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs);
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 *pui32PageOffset);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
new file mode 100644
index 0000000..11c1608
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
@@ -0,0 +1,106 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+ IMG_UINT32 ui32PID;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_CONTEXT hResManContext;
+ IMG_HANDLE hPerProcData;
+ PVRSRV_HANDLE_BASE *psHandleBase;
+#if defined (PVR_SECURE_HANDLES)
+
+ IMG_BOOL bHandlesBatched;
+#endif
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bInitProcess;
+
+
+ IMG_HANDLE hOsPrivateData;
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+ return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
new file mode 100644
index 0000000..1e47736
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
@@ -0,0 +1,116 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+ PFN_PRE_POWER pfnPrePower;
+ PFN_POST_POWER pfnPostPower;
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange;
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState;
+ struct _PVRSRV_POWER_DEV_TAG_ *psNext;
+ struct _PVRSRV_POWER_DEV_TAG_ **ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+ PVRSRV_INIT_SERVER_Unspecified = -1,
+ PVRSRV_INIT_SERVER_RUNNING = 0,
+ PVRSRV_INIT_SERVER_RAN = 1,
+ PVRSRV_INIT_SERVER_SUCCESSFUL = 2,
+ PVRSRV_INIT_SERVER_NUM = 3,
+ PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
new file mode 100644
index 0000000..f3e5df6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
@@ -0,0 +1,115 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
+ psQueue->ui32ReadOffset = (psQueue->ui32ReadOffset + ui32Size) \
+ & (psQueue->ui32QueueSize - 1);
+
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+ IMG_BOOL bInUse;
+
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_UINT32 ui32AllocSize;
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_UINT32 ui32CallerID,
+ IMG_BOOL bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+#include <linux/seq_file.h>
+off_t
+QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
new file mode 100644
index 0000000..d537601
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
@@ -0,0 +1,151 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+typedef struct _RA_ARENA_ RA_ARENA;
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+#define RA_STATS
+
+
+struct _RA_STATISTICS_
+{
+
+ IMG_SIZE_T uSpanCount;
+
+
+ IMG_SIZE_T uLiveSegmentCount;
+
+
+ IMG_SIZE_T uFreeSegmentCount;
+
+
+ IMG_SIZE_T uTotalResourceCount;
+
+
+ IMG_SIZE_T uFreeResourceCount;
+
+
+ IMG_SIZE_T uCumulativeAllocs;
+
+
+ IMG_SIZE_T uCumulativeFrees;
+
+
+ IMG_SIZE_T uImportCount;
+
+
+ IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+ IMG_SIZE_T uiSize;
+ IMG_CPU_PHYADDR sCpuPhyAddr;
+ IMG_HANDLE hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID *,
+ IMG_SIZE_T,
+ IMG_SIZE_T,
+ IMG_HANDLE),
+ IMG_VOID *import_handle);
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *pBase);
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total) \
+{ \
+ if(total<100) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+}
+
+#define UPDATE_SPACE(str, count, total) \
+{ \
+ if(count == -1) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+ else \
+ { \
+ str += count; \
+ total -= count; \
+ } \
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen);
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
new file mode 100644
index 0000000..a2c6d02
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
@@ -0,0 +1,109 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+enum {
+
+ RESMAN_TYPE_SHARED_PB_DESC = 1,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ RESMAN_TYPE_TRANSFER_CONTEXT,
+
+
+
+
+
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+
+ RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_EVENT_OBJECT,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+
+
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+};
+
+#define RESMAN_CRITERIA_ALL 0x00000000
+#define RESMAN_CRITERIA_RESTYPE 0x00000001
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM psResItem);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM psResItem,
+ PRESMAN_CONTEXT psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT hResManContext,
+ PRESMAN_ITEM psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+ IMG_BOOL bKernelContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
new file mode 100644
index 0000000..4f6c2a2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
@@ -0,0 +1,45 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
new file mode 100644
index 0000000..5506992
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
@@ -0,0 +1,65 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+ #ifdef PVR_DISABLE_LOGGING
+ #define PVR_LOG(X)
+ #else
+ #define PVR_LOG(X) PVRSRVReleasePrintf X
+ #endif
+
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat,
+ ...);
+
+ IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID);
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID);
+
+ IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+ IMG_UINT32 uiOffset, uiStart, uiCurrent, uiNotLastLoop; \
+ for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, uiNotLastLoop = 1;\
+ ((uiCurrent - uiStart + uiOffset) < TIMEOUT) || uiNotLastLoop--; \
+ uiCurrent = OSClockus(), \
+ uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset, \
+ uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
new file mode 100644
index 0000000..6146806
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
@@ -0,0 +1,1367 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <linux/pci.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#ifdef SUPPORT_MSVDX
+#include "msvdx_defs.h"
+#include "msvdxapi.h"
+#include "msvdx_infokm.h"
+#include "osfunc.h"
+#endif
+#include "pdump_km.h"
+#include "syslocal.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "msvdx_pvr.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Pointer to "System Data" used by all platform blocks, exported
+* in "syscommon.h" header file.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_DATA *gpsSysData = (SYS_DATA*)IMG_NULL;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Pointer to found platform interface. It is IMG_NULL when no
+* correct platform can be found.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE *gpsSysPlatformInterface = (SYS_PLATFORM_INTERFACE*)IMG_NULL;
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+extern SYS_PLATFORM_INTERFACE gpsSysPlatformInterfacePlb;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Atom E6xx platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+extern SYS_PLATFORM_INTERFACE gpsSysPlatformInterfaceTnc;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Table to available platforms interfaces.
+* The last element must be set to IMG_NULL.
+*
+* @Param &gpsSysPlatformInterfacePlb Poulsbo interface
+* @Param &gpsSysPlatformInterfaceTnc Atom E6xx interface
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE* gpsSysPlatformInterfacesTab[] = { &gpsSysPlatformInterfacePlb,
+ &gpsSysPlatformInterfaceTnc,
+ (SYS_PLATFORM_INTERFACE*)IMG_NULL};
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Function to detect platform and set "gpsSysPlatformInterface" to
+* one member of "gpsSysPlatformInterfacesTab".
+*
+* @Param IMG_VOID
+*
+* @Returns
+*/
+/* --------------------------------------------------------------------------*/
+IMG_VOID SysPlatformDetect(IMG_VOID)
+{
+ SYS_PLATFORM_INTERFACE** psSysPlatformInterfacesTab = gpsSysPlatformInterfacesTab;
+
+ while(*psSysPlatformInterfacesTab != IMG_NULL) {
+
+ if(pci_get_device(SYS_SGX_DEV_VENDOR_ID, (unsigned short)((*psSysPlatformInterfacesTab)->uiSgxDevDeviceID), NULL)) {
+ gpsSysPlatformInterface = *psSysPlatformInterfacesTab;
+ PVR_DPF((PVR_DBG_MESSAGE,"Platform detected: %s", gpsSysPlatformInterface->sProductName));
+ return;
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,"Platform search: %s", (*psSysPlatformInterfacesTab)->sProductName));
+ psSysPlatformInterfacesTab++;
+ }
+ PVR_DPF((PVR_DBG_ERROR,"Platform detected Failed"));
+}
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Interface for Atom E6xx device
+*/
+/* ----------------------------------------------------------------------------*/
+
+static SYS_DATA gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+
+static IMG_UINT32 gui32SGXDeviceID;
+static SGX_DEVICE_MAP gsSGXDeviceMap;
+static IMG_UINT32 gui32MSVDXDeviceID;
+
+#ifdef SUPPORT_MSVDX
+static IMG_UINT32 gui32MSVDXDeviceID;
+static MSVDX_DEVICE_MAP gsMSVDXDeviceMap;
+#endif
+
+
+#if defined(NO_HARDWARE)
+static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
+#ifdef SUPPORT_MSVDX
+static IMG_CPU_VIRTADDR gsMSVDXRegsCPUVAddr;
+#endif
+#endif
+
+#if !defined(NO_HARDWARE)
+static IMG_CPU_VIRTADDR gsPoulsboRegsCPUVaddr;
+
+#if defined(MAP_UNUSED_MAPPINGS)
+static IMG_CPU_VIRTADDR gsPoulsboDisplayRegsCPUVaddr;
+#endif
+
+#endif
+
+#ifdef LDM_PCI
+extern struct pci_dev *gpsPVRLDMDev;
+#endif
+
+IMG_UINT32 PVRSRV_BridgeDispatchKM( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+
+#ifdef __linux__
+#define ADDR_RANGE_INDEX (MMADR_INDEX - 4)
+#if defined(SGX_FEATURE_HOST_PORT)
+#define HP_ADDR_RANGE_INDEX (GMADR_INDEX - 4)
+#endif
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#ifdef LDM_PCI
+ psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, HOST_PCI_INIT_FLAG_BUS_MASTER);
+#else
+ psSysSpecData->hSGXPCI = OSPCIAcquireDev(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAG_BUS_MASTER);
+#endif
+ if (!psSysSpecData->hSGXPCI)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Failed to acquire PCI device"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV);
+
+ PVR_TRACE(("PCI memory region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX)));
+#if defined(SGX_FEATURE_HOST_PORT)
+ PVR_TRACE(("Host Port region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX)));
+#endif
+
+ if (OSPCIAddrRangeLen(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX) < MAX_OFFSET)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region isn't big enough"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+ if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region not available"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE);
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Host Port region not available"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE);
+#endif
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE))
+ {
+ OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX);
+ }
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE))
+ {
+ OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX);
+ }
+#endif
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV))
+ {
+ OSPCIReleaseDev(psSysSpecData->hSGXPCI);
+ }
+}
+#else
+static PVRSRV_ERROR FindPCIDevice(IMG_UINT16 ui16VenID, IMG_UINT16 ui16DevID, PCICONFIG_SPACE *psPCISpace)
+{
+ IMG_UINT32 ui32BusNum;
+ IMG_UINT32 ui32DevNum;
+ IMG_UINT32 ui32VenDevID;
+
+
+ for (ui32BusNum=0; ui32BusNum < 255; ui32BusNum++)
+ {
+
+ for (ui32DevNum=0; ui32DevNum < 32; ui32DevNum++)
+ {
+
+ ui32VenDevID=OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 0);
+
+
+ if (ui32VenDevID == (IMG_UINT32)((ui16DevID<<16)+ui16VenID))
+ {
+ IMG_UINT32 ui32Idx;
+
+
+ OSPCIWriteDword(ui32BusNum, ui32DevNum, 0, 4, OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 4) | 0x02);
+
+
+ for (ui32Idx=0; ui32Idx < 64; ui32Idx++)
+ {
+ psPCISpace->u.aui32PCISpace[ui32Idx] = OSPCIReadDword(ui32BusNum, ui32DevNum, 0, ui32Idx*4);
+
+ if (ui32Idx < 16)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE,"%08X\n",psPCISpace->u.aui32PCISpace[ui32Idx]));
+ }
+ }
+ return PVRSRV_OK;
+ }
+
+ }
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"Couldn't find PCI device"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE) || defined(__linux__)
+ IMG_UINT32 ui32BaseAddr;
+ IMG_UINT32 ui32IRQ;
+#endif
+#if defined(SGX_FEATURE_HOST_PORT)
+ IMG_UINT32 ui32HostPortAddr = 0UL;
+#endif
+#if defined(NO_HARDWARE)
+ IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+#if defined(NO_HARDWARE) || defined(__linux__)
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+#endif
+#if (!defined(__linux__) || defined(NO_HARDWARE))
+ PVRSRV_ERROR eError;
+#endif
+
+#ifdef __linux__
+ ui32BaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX);
+#if defined(SGX_FEATURE_HOST_PORT)
+ ui32HostPortAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX);
+#endif
+ if (OSPCIIRQ(psSysSpecData->hSGXPCI, &ui32IRQ) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Couldn't get IRQ"));
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+ PVR_TRACE(("IRQ: %d", ui32IRQ));
+#else
+ PVRSRV_ERROR eError;
+ PCICONFIG_SPACE sPCISpace;
+
+ eError = FindPCIDevice(VENDOR_ID, DEVICE_ID, &sPCISpace);
+ if (eError == PVRSRV_OK)
+ {
+ ui32BaseAddr = sPCISpace.u.aui32PCISpace[MMADR_INDEX];
+#if defined(SGX_FEATURE_HOST_PORT)
+ ui32HostPortAddr = sPCISpace.u.aui32PCISpace[GMADR_INDEX];
+#endif
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ ui32IRQ = (IMG_UINT32)sPCISpace.u.aui8PCISpace[0x3C];
+#endif
+
+
+ gsSGXDeviceMap.ui32Flags = 0x0;
+
+
+#if defined(NO_HARDWARE)
+
+ gsSGXDeviceMap.ui32IRQ = 0;
+#else
+ gsSGXDeviceMap.ui32IRQ = ui32IRQ;
+#endif
+
+#if defined(NO_HARDWARE)
+
+ eError = OSBaseAllocContigMemory(SGX_REG_SIZE,
+ &gsSGXRegsCPUVAddr,
+ &sCpuPAddr);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS);
+
+ gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+
+ OSMemSet(gsSGXRegsCPUVAddr, 0, SGX_REG_SIZE);
+
+#if defined(__linux__)
+
+ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+#else
+
+ gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+
+#else
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#endif
+
+
+ gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+ gsSGXDeviceMap.ui32RegsSize = SGX_REG_SIZE;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ gsSGXDeviceMap.ui32Flags = SGX_HOSTPORT_PRESENT;
+ gsSGXDeviceMap.sHPSysPBase.uiAddr = ui32HostPortAddr;
+ gsSGXDeviceMap.sHPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sHPSysPBase);
+ gsSGXDeviceMap.ui32HPSize = SYS_SGX_HP_SIZE;
+#endif
+
+
+
+
+ gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+ gsSGXDeviceMap.ui32LocalMemSize = 0;
+
+#if !defined(NO_HARDWARE)
+
+ {
+ IMG_SYS_PHYADDR sPoulsboRegsCpuPBase;
+
+ sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + REGS_OFFSET;
+ gsPoulsboRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+ REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+#if defined(MAP_UNUSED_MAPPINGS)
+ sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + DISPLAY_REGS_OFFSET;
+ gsPoulsboDisplayRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+ DISPLAY_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+#endif
+ }
+#endif
+
+#ifdef SUPPORT_MSVDX
+
+
+#if defined(NO_HARDWARE)
+
+ eError = OSBaseAllocContigMemory(MSVDX_REG_SIZE,
+ &gsMSVDXRegsCPUVAddr,
+ &sCpuPAddr);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS);
+ gsMSVDXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+
+ OSMemSet(gsMSVDXRegsCPUVAddr, 0, MSVDX_REG_SIZE);
+
+#if defined(__linux__)
+
+ gsMSVDXDeviceMap.pvRegsCpuVBase = gsMSVDXRegsCPUVAddr;
+#else
+
+ gsMSVDXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+#else
+ gsMSVDXDeviceMap.sRegsCpuPBase.uiAddr = ui32BaseAddr + MSVDX_REGS_OFFSET;
+#endif
+ gsMSVDXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsMSVDXDeviceMap.sRegsCpuPBase);
+ gsMSVDXDeviceMap.ui32RegsSize = MSVDX_REG_SIZE;
+
+
+
+
+
+ gsMSVDXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+ gsMSVDXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+ gsMSVDXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+ gsMSVDXDeviceMap.ui32LocalMemSize = 0;
+
+
+
+ gsMSVDXDeviceMap.ui32IRQ = ui32IRQ;
+
+#endif
+
+
+
+ return PVRSRV_OK;
+}
+
+#ifdef SUPPORT_MSVDX_FPGA
+static PVRSRV_ERROR FindPCIDevice(IMG_UINT16 ui16VenID, IMG_UINT16 ui16DevID, PCICONFIG_SPACE *psPCISpace)
+{
+ IMG_UINT32 ui32BusNum;
+ IMG_UINT32 ui32DevNum;
+ IMG_UINT32 ui32VenDevID;
+ IMG_UINT32 ui32BarIndex;
+
+
+ for (ui32BusNum=0; ui32BusNum < 255; ui32BusNum++)
+ {
+
+ for (ui32DevNum=0; ui32DevNum < 32; ui32DevNum++)
+ {
+
+ ui32VenDevID=OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 0);
+
+
+ if (ui32VenDevID == (IMG_UINT32)((ui16DevID<<16)+ui16VenID))
+ {
+ IMG_UINT32 ui32Idx;
+
+
+ OSPCIWriteDword(ui32BusNum, ui32DevNum, 0, 4, OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 4) | 0x02);
+
+ psPCISpace->ui32BusNum = ui32BusNum;
+ psPCISpace->ui32DevNum = ui32DevNum;
+ psPCISpace->ui32FuncNum = 0;
+
+
+ for (ui32Idx=0; ui32Idx < 64; ui32Idx++)
+ {
+ psPCISpace->u.aui32PCISpace[ui32Idx] = OSPCIReadDword(ui32BusNum, ui32DevNum, 0, ui32Idx*4);
+
+ if (ui32Idx < 16)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE,"%08X\n",psPCISpace->u.aui32PCISpace[ui32Idx]));
+ }
+ }
+
+ for (ui32BarIndex = 0; ui32BarIndex < 6; ui32BarIndex++)
+ {
+ GetPCIMemSpaceSize (ui32BusNum, ui32DevNum, ui32BarIndex, &psPCISpace->aui32PCIMemSpaceSize[ui32BarIndex]);
+ }
+ return PVRSRV_OK;
+ }
+
+ }
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"Couldn't find PCI device"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static IMG_UINT32 GetPCIMemSpaceSize (IMG_UINT32 ui32BusNum, IMG_UINT32 ui32DevNum, IMG_UINT32 ui32BarIndex, IMG_UINT32* pui32PCIMemSpaceSize)
+{
+
+ IMG_UINT32 ui32AddressRange;
+ IMG_UINT32 ui32BarSave;
+
+ ui32BarSave = OSPCIReadDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)));
+
+ OSPCIWriteDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)), 0xFFFFFFFF);
+
+ ui32AddressRange = OSPCIReadDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)));
+
+ OSPCIWriteDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)), ui32BarSave);
+
+ *pui32PCIMemSpaceSize = (~(ui32AddressRange & 0xFFFFFFF0)) + 1;
+ return PVRSRV_OK;
+}
+#endif
+
+
+#ifdef __linux__
+#define VERSION_STR_MAX_LEN_TEMPLATE "SGX revision = 000.000.000"
+static PVRSRV_ERROR SysCreateVersionString(SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32SGXRevision = 0;
+ IMG_UINT32 ui32MaxStrLen;
+ PVRSRV_ERROR eError;
+ IMG_INT32 i32Count;
+ IMG_CHAR *pszVersionString;
+
+#if !defined(NO_HARDWARE)
+
+ {
+ IMG_VOID *pvSGXRegs;
+
+ pvSGXRegs = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ if (pvSGXRegs != IMG_NULL)
+ {
+ ui32SGXRevision = OSReadHWReg(pvSGXRegs, EUR_CR_CORE_REVISION);
+
+ OSUnMapPhysToLin(pvSGXRegs,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysCreateVersionString: Couldn't map SGX registers"));
+ }
+ }
+#endif
+
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen + 1,
+ (IMG_PVOID *)&pszVersionString,
+ IMG_NULL,
+ "Version String");
+ if(eError != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ i32Count = OSSNPrintf(pszVersionString, ui32MaxStrLen + 1,
+ "SGX revision = %u.%u.%u",
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAJOR_MASK)
+ >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MINOR_MASK)
+ >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+ >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+ );
+ if(i32Count == -1)
+ {
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen + 1,
+ pszVersionString,
+ IMG_NULL);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psSysData->pszVersionString = pszVersionString;
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID SysFreeVersionString(SYS_DATA *psSysData)
+{
+ if(psSysData->pszVersionString)
+ {
+ IMG_UINT32 ui32MaxStrLen;
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen+1,
+ psSysData->pszVersionString,
+ IMG_NULL);
+ psSysData->pszVersionString = NULL;
+ }
+}
+#endif
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SGX_TIMING_INFORMATION* psTimingInfo;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SysInitialise"));
+
+ SysPlatformDetect();
+
+ gpsSysData = &gsSysData;
+ OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+ gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+ gsSysSpecificData.ui32SysSpecificData = 0;
+#ifdef LDM_PCI
+
+ PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+ gsSysSpecificData.psPCIDev = gpsPVRLDMDev;
+#endif
+
+ eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+ psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+ psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+ psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ psTimingInfo->bEnableActivePM = IMG_TRUE;
+#else
+ psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif
+ psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+ psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+#ifdef __linux__
+ eError = PCIInitDev(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+#endif
+
+ gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+
+ for(i=0; i<SYS_DEVICE_COUNT; i++)
+ {
+ gpsSysData->sDeviceID[i].uiID = i;
+ gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+ }
+
+ gpsSysData->psDeviceNodeList = IMG_NULL;
+ gpsSysData->psQueueList = IMG_NULL;
+
+ eError = SysInitialiseCommon(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+ eError = SysLocateDevices(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+ DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+//#ifdef SUPPORT_MSVDX
+ eError = PVRSRVRegisterDevice(gpsSysData, MSVDXRegisterDevice,
+ DEVICE_MSVDX_INTERRUPT, &gui32MSVDXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+//#endif
+
+
+ psDeviceNode = gpsSysData->psDeviceNodeList;
+
+ while(psDeviceNode)
+ {
+
+ switch(psDeviceNode->sDevId.eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+ {
+ psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+ }
+
+ break;
+ }
+
+//#ifdef SUPPORT_MSVDX
+ case PVRSRV_DEVICE_TYPE_MSVDX:
+ {
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+ {
+ psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+ }
+ break;
+ }
+//#endif
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ }
+
+
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PDUMPINIT();
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PDUMP_INIT);
+
+
+ eError = PVRSRVInitialiseDevice (gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_SGX_INITIALISED);
+
+//#ifdef SUPPORT_MSVDX
+ eError = PVRSRVInitialiseDevice (gui32MSVDXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MSVDX_INITIALISED);
+//#endif
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID SysEnableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegData;
+ IMG_UINT32 ui32Mask;
+
+ ui32Mask = THALIA_MASK | MSVDX_MASK;
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG, ui32RegData | ui32Mask);
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG, ui32RegData & (~ui32Mask));
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG, ui32RegData | ui32Mask);
+
+ PVR_TRACE(("SysEnableInterrupts: Interrupts enabled"));
+#endif
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+
+static IMG_VOID SysDisableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegData;
+ IMG_UINT32 ui32Mask;
+
+
+ ui32Mask = THALIA_MASK | MSVDX_MASK;
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG, ui32RegData & (~ui32Mask));
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG, ui32RegData | ui32Mask);
+
+ PVR_TRACE(("SysDisableInterrupts: Interrupts disabled"));
+#endif
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+
+IMG_VOID SysReEnableInterrupts(IMG_VOID)
+{
+ SysEnableInterrupts(gpsSysData);
+}
+
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(SYS_USING_INTERRUPTS)
+ eError = OSInstallMISR(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallMISR failed"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MISR_INSTALLED);
+
+ eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallSystemLISR failed"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+#endif
+
+ SysEnableInterrupts(gpsSysData);
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+
+#ifdef __linux__
+
+ eError = SysCreateVersionString(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to create a system version string"));
+ }
+#endif
+
+ return eError;
+}
+
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+ {
+ SysDisableInterrupts(psSysData);
+ }
+
+#if defined(SYS_USING_INTERRUPTS)
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+ {
+ eError = OSUninstallSystemLISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallSystemLISR failed"));
+ return eError;
+ }
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MISR_INSTALLED))
+ {
+ eError = OSUninstallMISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+ return eError;
+ }
+ }
+#endif
+/* Commenting this out to clean up allocation made in SysInitialise */
+/*#if defined(SUPPORT_MSVDX)*/
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MSVDX_INITIALISED))
+ {
+
+ eError = PVRSRVDeinitialiseDevice(gui32MSVDXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+ return eError;
+ }
+ }
+/*#endif*/
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_SGX_INITIALISED))
+ {
+
+ eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+ return eError;
+ }
+ }
+
+#ifdef __linux__
+ SysFreeVersionString(psSysData);
+
+ PCIDeInitDev(psSysData);
+#endif
+
+ eError = OSDeInitEnvData(psSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+ return eError;
+ }
+
+ SysDeinitialiseCommon(gpsSysData);
+
+#if defined(NO_HARDWARE)
+#ifdef SUPPORT_MSVDX
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS))
+ {
+ OSBaseFreeContigMemory(MSVDX_REG_SIZE, gsMSVDXRegsCPUVAddr, gsMSVDXDeviceMap.sRegsCpuPBase);
+ }
+#endif
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS))
+ {
+ OSBaseFreeContigMemory(SGX_REG_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase);
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+
+ OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+ REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+#if defined(MAP_UNUSED_MAPPINGS)
+ OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+ DISPLAY_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+#endif
+
+#endif
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PDUMP_INIT))
+ {
+ PDUMPDEINIT();
+ }
+
+ gpsSysData = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA* psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32Devices = 0;
+ IMG_UINT32 ui32Data, ui32DIMMask;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+ ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG);
+
+ if (ui32Data & THALIA_MASK)
+ {
+ ui32Devices |= DEVICE_SGX_INTERRUPT;
+ }
+
+ if (ui32Data & MSVDX_MASK)
+ {
+ ui32Devices |= DEVICE_MSVDX_INTERRUPT;
+ }
+
+
+ ui32DIMMask = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+ ui32DIMMask &= ~(THALIA_MASK | MSVDX_MASK);
+
+
+ if (ui32Data & ui32DIMMask)
+ {
+ ui32Devices |= DEVICE_DISP_INTERRUPT;
+ }
+
+ return (ui32Devices);
+#else
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+ return 0;
+#endif
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32Data;
+ IMG_UINT32 ui32Mask = 0;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_STATUS_REG);
+
+ if ((ui32ClearBits & DEVICE_SGX_INTERRUPT) &&
+ ((ui32Data & THALIA_MASK) == 0))
+ {
+ ui32Mask |= THALIA_MASK;
+ }
+
+ if ((ui32ClearBits & DEVICE_MSVDX_INTERRUPT) &&
+ ((ui32Data & MSVDX_MASK) == 0))
+ {
+ ui32Mask |= MSVDX_MASK;
+ }
+
+ if (ui32Mask)
+ {
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG, ui32Mask);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+#endif
+}
+
+
+
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap)
+{
+
+ switch(eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+
+ *ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+ break;
+ }
+#ifdef SUPPORT_MSVDX
+ case PVRSRV_DEVICE_TYPE_MSVDX:
+ {
+
+ *ppvDeviceMap = (IMG_VOID*)&gsMSVDXDeviceMap;
+ break;
+ }
+#endif
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_PHYADDR CpuPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+ IMG_CPU_PHYADDR cpu_paddr;
+
+
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+ IMG_SYS_PHYADDR sys_paddr;
+
+
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+ IMG_SYS_PHYADDR SysPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+ return SysPAddr;
+}
+
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+PVRSRV_ERROR SysOEMFunction ( IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize)
+{
+ if (ulInSize || pvIn);
+
+ if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+ (ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+ {
+ PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*)pvOut;
+ psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+#ifdef __linux__
+ psOEMJTable->pfnOEMReadRegistryString = IMG_NULL;
+ psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+#else
+ psOEMJTable->pfnOEMReadRegistryString = IMG_NULL;
+ psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+#endif
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError= PVRSRV_OK;
+
+ if (eNewPowerState != gpsSysData->eCurrentPowerState)
+ {
+ if ((eNewPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+ (gpsSysData->eCurrentPowerState < PVRSRV_SYS_POWER_STATE_D3))
+ {
+
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+ {
+ SysDisableInterrupts(gpsSysData);
+
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+ }
+
+#if defined(SYS_USING_INTERRUPTS)
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+ {
+ eError = OSUninstallSystemLISR(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSUninstallSystemLISR failed (%d)", eError));
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+ }
+#endif
+
+
+#ifdef __linux__
+ eError = OSPCISuspendDev(gsSysSpecificData.hSGXPCI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSPCISuspendDev failed (%d)", eError));
+ }
+#endif
+ }
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (eNewPowerState != gpsSysData->eCurrentPowerState)
+ {
+ if ((gpsSysData->eCurrentPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+ (eNewPowerState < PVRSRV_SYS_POWER_STATE_D3))
+ {
+#ifdef __linux__
+ eError = OSPCIResumeDev(gsSysSpecificData.hSGXPCI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSPCIResumeDev failed (%d)", eError));
+ }
+#endif
+
+
+#if defined(SYS_USING_INTERRUPTS)
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR))
+ {
+ eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSInstallSystemLISR failed to install ISR (%d)", eError));
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+ }
+#endif
+
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE))
+ {
+ SysEnableInterrupts(gpsSysData);
+
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE);
+ }
+ }
+ }
+ return eError;
+}
+
+
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if (ui32DeviceIndex == gui32SGXDeviceID)
+ {
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Remove SGX power"));
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if (ui32DeviceIndex == gui32SGXDeviceID)
+ {
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePostPowerState: Restore SGX power"));
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
new file mode 100644
index 0000000..0e3e7a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
@@ -0,0 +1,26 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "syslocal.h"
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
new file mode 100644
index 0000000..343e85f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
@@ -0,0 +1,68 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define OEM_EXCHANGE_POWER_STATE (1<<0)
+#define OEM_DEVICE_MEMORY_POWER (1<<1)
+#define OEM_DISPLAY_POWER (1<<2)
+#define OEM_GET_EXT_FUNCS (1<<3)
+
+typedef struct OEM_ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+} OEM_ACCESS_INFO, *POEM_ACCESS_INFO;
+
+typedef IMG_UINT32 (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+
+
+typedef PVRSRV_ERROR (*PFN_SRV_READREGSTRING)(PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+ PFN_SRV_BRIDGEDISPATCH pfnOEMBridgeDispatch;
+ PFN_SRV_READREGSTRING pfnOEMReadRegistryString;
+ PFN_SRV_READREGSTRING pfnOEMWriteRegistryString;
+
+} PVRSRV_DC_OEM_JTABLE;
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
new file mode 100644
index 0000000..8ae67dc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_SHARED_H__)
+#define __SYS_PVR_DRM_SHARED_H__
+
+#define DRM_PSB_GTT_MAP 0x0F
+#define DRM_PSB_GTT_UNMAP 0x10
+
+/* Note: the ioctl numbers used to be here, but are now defined in the common
+ * header, "emgd_shared.h", to avoid getting out-of-sync:
+ */
+#include "emgd_shared.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
new file mode 100644
index 0000000..d316141
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
@@ -0,0 +1,27 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
new file mode 100644
index 0000000..56abae7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
@@ -0,0 +1,326 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSCONFIG_H
+#define _SYSCONFIG_H
+
+#include "sysinfo.h"
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+ IMG_UINT32 uiID;
+ IMG_BOOL bInUse;
+
+} SYS_DEVICE_ID;
+
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS 4
+
+typedef struct _SYS_DATA_TAG_
+{
+ IMG_UINT32 ui32NumDevices;
+ SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
+ PVRSRV_DEVICE_NODE *psDeviceNodeList;
+ PVRSRV_POWER_DEV *psPowerDeviceList;
+ PVRSRV_RESOURCE sPowerStateChangeResource;
+ PVRSRV_SYS_POWER_STATE eCurrentPowerState;
+ PVRSRV_SYS_POWER_STATE eFailedPowerState;
+ IMG_UINT32 ui32CurrentOSPowerState;
+ PVRSRV_QUEUE_INFO *psQueueList;
+ PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
+ IMG_PVOID pvEnvSpecificData;
+ IMG_PVOID pvSysSpecificData;
+ PVRSRV_RESOURCE sQProcessResource;
+ IMG_VOID *pvSOCRegsBase;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_UINT32 *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCClockGateRegsBase;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+ PFN_CMD_PROC *ppfnCmdProcList[SYS_DEVICE_COUNT];
+
+
+ PCOMMAND_COMPLETE_DATA *ppsCmdCompleteData[SYS_DEVICE_COUNT];
+
+ IMG_BOOL bReProcessQueues;
+
+ RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+ IMG_CHAR *pszVersionString;
+ PVRSRV_EVENTOBJECT *psGlobalEventObject;
+
+ IMG_BOOL bFlushAll;
+
+} SYS_DATA;
+
+
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+IMG_VOID SysReEnableInterrupts(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA *psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+PVRSRV_ERROR SysOEMFunction( IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize);
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr( PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr( PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr( PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr( IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr( IMG_CPU_PHYADDR cpu_paddr);
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis platform interface definition
+*/
+/* ----------------------------------------------------------------------------*/
+typedef struct _SYS_PLATFORM_INTERFACE {
+ char* sProductName;
+ IMG_UINT32 uiSgxDevDeviceID;
+ IMG_UINT32 uiSgxRegsOffset;
+ IMG_UINT32 uiMsvdxRegsOffset;
+ IMG_UINT32 uiSysSgxClockSpeed;
+ IMG_UINT32 uiSysSgxActivePowerLatencyMs;
+} SYS_PLATFORM_INTERFACE;
+
+/* #define MAP_UNUSED_MAPPINGS */
+
+#if defined(MAP_UNUSED_MAPPINGS)
+#define SGX_FEATURE_HOST_PORT
+#endif
+
+extern SYS_PLATFORM_INTERFACE *gpsSysPlatformInterface;
+
+#define VS_PRODUCT_NAME ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->sProductName) : "Unknown Product")
+#define SYS_SGX_DEV_DEVICE_ID ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSgxDevDeviceID) : 0x0)
+#define SGX_REGS_OFFSET ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSgxRegsOffset) : 0x0)
+#ifdef SUPPORT_MSVDX
+#define MSVDX_REGS_OFFSET ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiMsvdxRegsOffset) : 0x0)
+#endif
+#define SYS_SGX_CLOCK_SPEED ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSysSgxClockSpeed) : 0)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSysSgxActivePowerLatencyMs) : 0)
+
+#define SYS_SGX_DEV_VENDOR_ID 0x8086
+
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ (100)
+#define SYS_SGX_PDS_TIMER_FREQ (1000)
+
+
+#define REGS_OFFSET 0x00000
+#define REG_SIZE 0x2100
+
+#define SGX_REG_SIZE 0x4000
+
+#ifdef SUPPORT_MSVDX
+#define MAX_OFFSET (MSVDX_REGS_OFFSET + MSVDX_REG_SIZE)
+#else
+#define MAX_OFFSET (SGX_REGS_OFFSET + SGX_REG_SIZE)
+#endif
+
+#define MMADR_INDEX 4
+
+#define DEVICE_SGX_INTERRUPT (1UL<<0)
+#define DEVICE_MSVDX_INTERRUPT (1UL<<1)
+#define DEVICE_DISP_INTERRUPT (1UL<<2)
+
+#define INTERRUPT_ENABLE_REG 0x20A0
+#define INTERRUPT_IDENTITY_REG 0x20A4
+#define INTERRUPT_MASK_REG 0x20A8
+#define INTERRUPT_STATUS_REG 0x20AC
+
+#define DISP_MASK (1UL<<17)
+#define THALIA_MASK (1UL<<18)
+#define MSVDX_MASK (1UL<<19)
+#define VSYNC_PIPEA_VBLANK_MASK (1UL<<7)
+#define VSYNC_PIPEA_EVENT_MASK (1UL<<6)
+#define VSYNC_PIPEB_VBLANK_MASK (1UL<<5)
+#define VSYNC_PIPEB_EVENT_MASK (1UL<<4)
+
+#define DISPLAY_REGS_OFFSET 0x70000
+#define DISPLAY_REG_SIZE 0x2000
+
+#define DISPLAY_A_CONFIG 0x00008UL
+#define DISPLAY_A_STATUS_SELECT 0x00024UL
+#define DISPLAY_B_CONFIG 0x01008UL
+#define DISPLAY_B_STATUS_SELECT 0x01024UL
+
+#define DISPLAY_PIPE_ENABLE (1UL<<31)
+#define DISPLAY_VSYNC_STS_EN (1UL<<25)
+#define DISPLAY_VSYNC_STS (1UL<<9)
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ #define SYS_SGX_HP_SIZE 0x8000000
+
+ #define SYS_SGX_HOSTPORT_BASE_DEVVADDR 0xD0000000
+ #if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030)
+ #define SYS_SGX_HOSTPORT_BRN23030_OFFSET 0x7C00000
+ #endif
+#endif
+
+
+typedef struct
+{
+ union
+ {
+#if !defined(VISTA)
+ IMG_UINT8 aui8PCISpace[256];
+ IMG_UINT16 aui16PCISpace[128];
+ IMG_UINT32 aui32PCISpace[64];
+#endif
+ struct
+ {
+ IMG_UINT16 ui16VenID;
+ IMG_UINT16 ui16DevID;
+ IMG_UINT16 ui16PCICmd;
+ IMG_UINT16 ui16PCIStatus;
+ }s;
+ }u;
+} PCICONFIG_SPACE, *PPCICONFIG_SPACE;
+
+
+extern SYS_DATA* gpsSysData;
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+
+
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE PVRSRV_ERROR SysAcquireData(SYS_DATA **ppsSysData)
+{
+
+ *ppsSysData = gpsSysData;
+
+ if (!gpsSysData)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVInit(psSysData);
+
+ return eError;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+ PVRSRVDeInit(psSysData);
+
+ OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif
+
+
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
new file mode 100644
index 0000000..95724d0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define MAX_HW_TIME_US (500000)
+#define WAIT_TRY_COUNT (10000)
+
+typedef enum _SYS_DEVICE_TYPE_
+{
+ SYS_DEVICE_SGX = 0,
+
+ SYS_DEVICE_FORCE_I16 = 0x7fff
+
+} SYS_DEVICE_TYPE;
+#if 0
+#define SYS_DEVICE_COUNT 5
+#endif
+
+#define SYS_DEVICE_COUNT 11
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
new file mode 100644
index 0000000..59d80da
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
@@ -0,0 +1,80 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#define SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV 0x00000001UL
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE 0x00000002UL
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE 0x00000004UL
+#if defined(NO_HARDWARE)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS 0x00000008UL
+#if defined(SUPPORT_MSVDX)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS 0x00000020UL
+#endif
+#endif
+#define SYS_SPECIFIC_DATA_SGX_INITIALISED 0x00000040UL
+//#if defined(SUPPORT_MSVDX)
+#define SYS_SPECIFIC_DATA_MSVDX_INITIALISED 0x00000080UL
+//#endif
+#define SYS_SPECIFIC_DATA_MISR_INSTALLED 0x00000100UL
+#define SYS_SPECIFIC_DATA_LISR_INSTALLED 0x00000200UL
+#define SYS_SPECIFIC_DATA_PDUMP_INIT 0x00000400UL
+#define SYS_SPECIFIC_DATA_IRQ_ENABLED 0x00000800UL
+
+#define SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS 0x00001000UL
+#define SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP 0x00004000UL
+#define SYS_SPECIFIC_DATA_PM_UNMAP_MSVDX_REGS 0x00008000UL
+#define SYS_SPECIFIC_DATA_PM_IRQ_DISABLE 0x00010000UL
+#define SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR 0x00020000UL
+
+#define SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+
+
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+
+ IMG_UINT32 ui32SysSpecificData;
+#ifdef __linux__
+ PVRSRV_PCI_DEV_HANDLE hSGXPCI;
+#endif
+#ifdef LDM_PCI
+ struct pci_dev *psPCIDev;
+#endif
+#ifdef SUPPORT_DRI_DRM_EXT
+
+ IMG_UINT32 msi_addr;
+ IMG_UINT32 msi_data;
+
+ IMG_UINT32 saveBSM;
+ IMG_UINT32 saveVBT;
+#endif
+} SYS_SPECIFIC_DATA;
+
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
new file mode 100644
index 0000000..ec0222c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
@@ -0,0 +1,48 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sysconfig.h"
+#include "sysplb.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE gpsSysPlatformInterfacePlb = {
+ VS_PRODUCT_NAME_PLB,
+ SYS_SGX_DEV_DEVICE_ID_PLB,
+ SGX_REGS_OFFSET_PLB,
+ MSVDX_REGS_OFFSET_PLB,
+ SYS_SGX_CLOCK_SPEED_PLB,
+ SYS_SGX_ACTIVE_POWER_LATENCY_MS_PLB
+};
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
new file mode 100644
index 0000000..0f7deff
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSPLB_H
+#define _SYSPLB_H
+
+#define SYS_SGX_DEV_DEVICE_ID_PLB 0x8108
+#define VS_PRODUCT_NAME_PLB "SGX Poulsbo"
+#define SGX_REGS_OFFSET_PLB 0x40000
+#define MSVDX_REGS_OFFSET_PLB 0x50000
+#define SYS_SGX_CLOCK_SPEED_PLB (200000000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS_PLB (1)
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
new file mode 100644
index 0000000..09e7997
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
@@ -0,0 +1,48 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sysconfig.h"
+#include "systnc.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE gpsSysPlatformInterfaceTnc = {
+ VS_PRODUCT_NAME_TNC,
+ SYS_SGX_DEV_DEVICE_ID_TNC,
+ SGX_REGS_OFFSET_TNC,
+ MSVDX_REGS_OFFSET_TNC,
+ SYS_SGX_CLOCK_SPEED_TNC,
+ SYS_SGX_ACTIVE_POWER_LATENCY_MS_TNC
+};
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
new file mode 100644
index 0000000..5793535
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSTNC_H
+#define _SYSTNC_H
+
+#define SYS_SGX_DEV_DEVICE_ID_TNC 0x4108
+#define VS_PRODUCT_NAME_TNC "SGX Atom E6xx"
+#define SGX_REGS_OFFSET_TNC 0x80000
+#define MSVDX_REGS_OFFSET_TNC 0x90000
+#define SYS_SGX_CLOCK_SPEED_TNC (400000000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS_TNC (50)
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
new file mode 100644
index 0000000..aa43db5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
@@ -0,0 +1,44 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+typedef struct tagIOCTL_PACKAGE
+{
+ IMG_UINT32 ui32Cmd;
+ IMG_UINT32 ui32Size;
+ IMG_VOID *pInBuffer;
+ IMG_UINT32 ui32InBufferSize;
+ IMG_VOID *pOutBuffer;
+ IMG_UINT32 ui32OutBufferSize;
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,
+ IMG_UINT32 ui32ControlCode,
+ IMG_VOID *pInBuffer,
+ IMG_UINT32 ui32InBufferSize,
+ IMG_VOID *pOutBuffer,
+ IMG_UINT32 ui32OutBufferSize,
+ IMG_UINT32 *pui32BytesReturned);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
new file mode 100644
index 0000000..d317957
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
@@ -0,0 +1,2072 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+#define LAST_FRAME_BUF_SIZE 1024
+
+typedef struct _DBG_LASTFRAME_BUFFER_
+{
+ PDBG_STREAM psStream;
+ IMG_UINT8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+ IMG_UINT32 ui32BufLen;
+ struct _DBG_LASTFRAME_BUFFER_ *psNext;
+} *PDBG_LASTFRAME_BUFFER;
+
+
+static PDBG_STREAM g_psStreamList = 0;
+static PDBG_LASTFRAME_BUFFER g_psLFBufferList;
+
+static IMG_UINT32 g_ui32LOff = 0;
+static IMG_UINT32 g_ui32Line = 0;
+static IMG_UINT32 g_ui32MonoLines = 25;
+
+static IMG_BOOL g_bHotkeyMiddump = IMG_FALSE;
+static IMG_UINT32 g_ui32HotkeyMiddumpStart = 0xffffffff;
+static IMG_UINT32 g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+IMG_VOID * g_pvAPIMutex=IMG_NULL;
+
+extern IMG_UINT32 g_ui32HotKeyFrame;
+extern IMG_BOOL g_bHotKeyPressed;
+extern IMG_BOOL g_bHotKeyRegistered;
+
+IMG_BOOL gbDumpThisFrame = IMG_FALSE;
+
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+ sizeof (DBGKM_SERVICE_TABLE),
+ ExtDBGDrivCreateStream,
+ ExtDBGDrivDestroyStream,
+ ExtDBGDrivFindStream,
+ ExtDBGDrivWriteString,
+ ExtDBGDrivReadString,
+ ExtDBGDrivWrite,
+ ExtDBGDrivRead,
+ ExtDBGDrivSetCaptureMode,
+ ExtDBGDrivSetOutputMode,
+ ExtDBGDrivSetDebugLevel,
+ ExtDBGDrivSetFrame,
+ ExtDBGDrivGetFrame,
+ ExtDBGDrivOverrideMode,
+ ExtDBGDrivDefaultMode,
+ ExtDBGDrivWrite2,
+ ExtDBGDrivWriteStringCM,
+ ExtDBGDrivWriteCM,
+ ExtDBGDrivSetMarker,
+ ExtDBGDrivGetMarker,
+ ExtDBGDrivStartInitPhase,
+ ExtDBGDrivStopInitPhase,
+ ExtDBGDrivIsCaptureFrame,
+ ExtDBGDrivWriteLF,
+ ExtDBGDrivReadLF,
+ ExtDBGDrivGetStreamOffset,
+ ExtDBGDrivSetStreamOffset,
+ ExtDBGDrivIsLastCaptureFrame,
+ ExtDBGDrivWaitForEvent
+};
+
+
+
+
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDestroyStream(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivFindStream(pszName, bResetStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetFrame(psStream, ui32Frame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivGetFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsLastCaptureFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivOverrideMode(psStream, ui32Mode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDefaultMode(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetMarker(psStream, ui32Marker);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Marker;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Marker = DBGDrivGetMarker(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStartInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStopInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ DBGDrivWaitForEvent(eEvent);
+#else
+ PVR_UNREFERENCED_PARAMETER(eEvent);
+#endif
+}
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+ IMG_INT iLen = 0;
+ IMG_UINT32 ui32Value = 0;
+ IMG_UINT32 ui32Digit=1;
+ IMG_UINT32 ui32Base=10;
+ IMG_INT iPos;
+ IMG_CHAR bc;
+
+
+ while (szIn[iLen] > 0)
+ {
+ iLen ++;
+ }
+
+
+ if (iLen == 0)
+ {
+ return (0);
+ }
+
+
+ iPos=0;
+ while (szIn[iPos] == '0')
+ {
+ iPos++;
+ }
+ if (szIn[iPos] == '\0')
+ {
+ return 0;
+ }
+ if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+ {
+ ui32Base=16;
+ szIn[iPos]='0';
+ }
+
+
+ for (iPos = iLen - 1; iPos >= 0; iPos --)
+ {
+ bc = szIn[iPos];
+
+ if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+ {
+ bc -= 'a' - 0xa;
+ }
+ else
+ if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+ {
+ bc -= 'A' - 0xa;
+ }
+ else
+ if ((bc >= '0') && (bc <= '9'))
+ {
+ bc -= '0';
+ }
+ else
+ return (0);
+
+ ui32Value += (IMG_UINT32)bc * ui32Digit;
+
+ ui32Digit = ui32Digit * ui32Base;
+ }
+ return (ui32Value);
+}
+
+
+IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psThis;
+
+ psThis = g_psStreamList;
+
+ while (psThis)
+ {
+ if (psStream && (psThis == psStream))
+ {
+ return(IMG_TRUE);
+ }
+ else
+ {
+ psThis = psThis->psNext;
+ }
+ }
+
+ return(IMG_FALSE);
+}
+
+
+void Write(PDBG_STREAM psStream,IMG_UINT8 * pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+
+
+ if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+ {
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+ IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+
+ HostMemCopy((IMG_VOID *)(psStream->ui32Base + psStream->ui32WPtr),
+ (IMG_VOID *) pui8Data,
+ ui32B1);
+
+
+ HostMemCopy((IMG_VOID *)psStream->ui32Base,
+ (IMG_VOID *)((IMG_UINT32) pui8Data + ui32B1),
+ ui32B2);
+
+
+ psStream->ui32WPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_VOID *)(psStream->ui32Base + psStream->ui32WPtr),
+ (IMG_VOID *) pui8Data,
+ ui32InBuffSize);
+
+ psStream->ui32WPtr += ui32InBuffSize;
+
+ if (psStream->ui32WPtr == psStream->ui32Size)
+ {
+ psStream->ui32WPtr = 0;
+ }
+ }
+ psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+
+void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
+{
+ IMG_UINT32 i;
+ IMG_CHAR * pScreen;
+
+ pScreen = (IMG_CHAR *) DBGDRIV_MONOBASE;
+
+ pScreen += g_ui32Line * 160;
+
+
+
+ i=0;
+ do
+ {
+ pScreen[g_ui32LOff + (i*2)] = pszString[i];
+ pScreen[g_ui32LOff + (i*2)+1] = 127;
+ i++;
+ }
+ while ((pszString[i] != 0) && (i < 4096));
+
+ g_ui32LOff += i * 2;
+
+ if (bNewLine)
+ {
+ g_ui32LOff = 0;
+ g_ui32Line++;
+ }
+
+
+
+ if (g_ui32Line == g_ui32MonoLines)
+ {
+ g_ui32Line = g_ui32MonoLines - 1;
+
+ HostMemCopy((IMG_VOID *)DBGDRIV_MONOBASE,(IMG_VOID *)(DBGDRIV_MONOBASE + 160),160 * (g_ui32MonoLines - 1));
+
+ HostMemSet((IMG_VOID *)(DBGDRIV_MONOBASE + (160 * (g_ui32MonoLines - 1))),0,160);
+ }
+}
+
+
+
+void AppendName(IMG_CHAR * pszOut,IMG_CHAR * pszBase,IMG_CHAR * pszName)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Off;
+
+ i = 0;
+
+ while (pszBase[i] != 0)
+ {
+ pszOut[i] = pszBase[i];
+ i++;
+ }
+
+ ui32Off = i;
+ i = 0;
+
+ while (pszName[i] != 0)
+ {
+ pszOut[ui32Off+i] = pszName[i];
+ i++;
+ }
+
+ pszOut[ui32Off+i] = pszName[i];
+}
+
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psInitStream;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ IMG_UINT32 ui32Off;
+ IMG_VOID * pvBase;
+
+
+
+
+ psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+ if (psStream)
+ {
+ return ((IMG_VOID *) psStream);
+ }
+
+
+
+ psStream = HostNonPageablePageAlloc(1);
+ psInitStream = HostNonPageablePageAlloc(1);
+ psLFBuffer = HostNonPageablePageAlloc(1);
+ if (
+ (!psStream) ||
+ (!psInitStream) ||
+ (!psLFBuffer)
+ )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+ return((IMG_VOID *) 0);
+ }
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+
+
+ psStream->psNext = 0;
+ psStream->ui32Flags = ui32Flags;
+ psStream->ui32Base = (IMG_UINT32)pvBase;
+ psStream->ui32Size = ui32Size * 4096UL;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = 0;
+ psStream->ui32CapMode = ui32CapMode;
+ psStream->ui32OutMode = ui32OutMode;
+ psStream->ui32DebugLevel = DEBUG_LEVEL_0;
+ psStream->ui32DefaultMode = ui32CapMode;
+ psStream->ui32Start = 0;
+ psStream->ui32End = 0;
+ psStream->ui32Current = 0;
+ psStream->ui32SampleRate = 1;
+ psStream->ui32Access = 0;
+ psStream->ui32Timeout = 0;
+ psStream->ui32Marker = 0;
+ psStream->bInitPhaseComplete = IMG_FALSE;
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ }
+ else
+ {
+ HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ }
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+ psInitStream->psNext = 0;
+ psInitStream->ui32Flags = ui32Flags;
+ psInitStream->ui32Base = (IMG_UINT32)pvBase;
+ psInitStream->ui32Size = ui32Size * 4096UL;
+ psInitStream->ui32RPtr = 0;
+ psInitStream->ui32WPtr = 0;
+ psInitStream->ui32DataWritten = 0;
+ psInitStream->ui32CapMode = ui32CapMode;
+ psInitStream->ui32OutMode = ui32OutMode;
+ psInitStream->ui32DebugLevel = DEBUG_LEVEL_0;
+ psInitStream->ui32DefaultMode = ui32CapMode;
+ psInitStream->ui32Start = 0;
+ psInitStream->ui32End = 0;
+ psInitStream->ui32Current = 0;
+ psInitStream->ui32SampleRate = 1;
+ psInitStream->ui32Access = 0;
+ psInitStream->ui32Timeout = 0;
+ psInitStream->ui32Marker = 0;
+ psInitStream->bInitPhaseComplete = IMG_FALSE;
+
+ psStream->psInitStream = psInitStream;
+
+
+ psLFBuffer->psStream = psStream;
+ psLFBuffer->ui32BufLen = 0UL;
+
+ g_bHotkeyMiddump = IMG_FALSE;
+ g_ui32HotkeyMiddumpStart = 0xffffffffUL;
+ g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
+
+
+
+ ui32Off = 0;
+
+ do
+ {
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+ ui32Off++;
+ }
+ while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+
+
+ psStream->psNext = g_psStreamList;
+ g_psStreamList = psStream;
+
+ psLFBuffer->psNext = g_psLFBufferList;
+ g_psLFBufferList = psLFBuffer;
+
+
+ return((IMG_VOID *) psStream);
+}
+
+void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psStreamThis;
+ PDBG_STREAM psStreamPrev;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ PDBG_LASTFRAME_BUFFER psLFThis;
+ PDBG_LASTFRAME_BUFFER psLFPrev;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ psStreamThis = g_psStreamList;
+ psStreamPrev = 0;
+
+ while (psStreamThis)
+ {
+ if (psStreamThis == psStream)
+ {
+ if (psStreamPrev)
+ {
+ psStreamPrev->psNext = psStreamThis->psNext;
+ }
+ else
+ {
+ g_psStreamList = psStreamThis->psNext;
+ }
+
+ psStreamThis = 0;
+ }
+ else
+ {
+ psStreamPrev = psStreamThis;
+ psStreamThis = psStreamThis->psNext;
+ }
+ }
+
+ psLFThis = g_psLFBufferList;
+ psLFPrev = 0;
+
+ while (psLFThis)
+ {
+ if (psLFThis == psLFBuffer)
+ {
+ if (psLFPrev)
+ {
+ psLFPrev->psNext = psLFThis->psNext;
+ }
+ else
+ {
+ g_psLFBufferList = psLFThis->psNext;
+ }
+
+ psLFThis = 0;
+ }
+ else
+ {
+ psLFPrev = psLFThis;
+ psLFThis = psLFThis->psNext;
+ }
+ }
+
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ DeactivateHotKeys();
+ }
+
+
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ HostNonPageablePageFree((IMG_VOID *)psStream->psInitStream->ui32Base);
+ }
+ else
+ {
+ HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ HostPageablePageFree((IMG_VOID *)psStream->psInitStream->ui32Base);
+ }
+
+ HostNonPageablePageFree(psStream->psInitStream);
+ HostNonPageablePageFree(psStream);
+ HostNonPageablePageFree(psLFBuffer);
+
+ if (g_psStreamList == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+ }
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psThis;
+ IMG_UINT32 ui32Off;
+ IMG_BOOL bAreSame;
+
+ psStream = 0;
+
+
+
+ for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+ {
+ bAreSame = IMG_TRUE;
+ ui32Off = 0;
+
+ if (strlen(psThis->szName) == strlen(pszName))
+ {
+ while ((psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && (ui32Off < 128) && bAreSame)
+ {
+ if (psThis->szName[ui32Off] != pszName[ui32Off])
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ ui32Off++;
+ }
+ }
+ else
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ if (bAreSame)
+ {
+ psStream = psThis;
+ break;
+ }
+ }
+
+ if(bResetStream && psStream)
+ {
+ static IMG_CHAR szComment[] = "-- Init phase terminated\r\n";
+ psStream->psInitStream->ui32RPtr = 0;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = psStream->psInitStream->ui32DataWritten;
+ if (psStream->bInitPhaseComplete == IMG_FALSE)
+ {
+ if (psStream->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+ {
+ DBGDrivWrite2(psStream, (IMG_UINT8 *)szComment, sizeof(szComment) - 1, 0x01);
+ }
+ psStream->bInitPhaseComplete = IMG_TRUE;
+ }
+ }
+
+ return((IMG_VOID *) psStream);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0);
+ }
+ }
+ else
+ {
+ if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+ return(0);
+ }
+ }
+ }
+
+ return(DBGDrivWriteString(psStream,pszString,ui32Level));
+
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT8 * pui8Buffer;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+
+ if ((psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
+ {
+ if (psStream->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
+ }
+
+
+
+ if (psStream->ui32OutMode & DEBUG_OUTMODE_MONO)
+ {
+ MonoOut(psStream->szName,IMG_FALSE);
+ MonoOut(": ",IMG_FALSE);
+ MonoOut(pszString,IMG_TRUE);
+ }
+ }
+
+
+
+ if (
+ !(
+ ((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
+ ((psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC) != 0)
+ )
+ )
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+
+ ui32Len = 0;
+ ui32WPtr = psStream->ui32WPtr;
+ pui8Buffer = (IMG_UINT8 *) psStream->ui32Base;
+
+ while((pszString[ui32Len] != 0) && (ui32Len < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+ }
+
+ if (ui32Len < ui32Space)
+ {
+
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+
+
+ psStream->ui32WPtr = ui32WPtr;
+ psStream->ui32DataWritten+= ui32Len;
+ } else
+ {
+ ui32Len = 0;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32Len)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+
+ return(ui32Len);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32OutLen;
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT8 *pui8Buff;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0);
+ }
+
+
+
+ pui8Buff = (IMG_UINT8 *) psStream->ui32Base;
+ ui32Offset = psStream->ui32RPtr;
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ {
+ return(0);
+ }
+
+
+
+ ui32Len = 0;
+ while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
+ {
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ ui32OutLen = ui32Len + 1;
+
+
+
+ if (ui32Len > ui32Limit)
+ {
+ return(0);
+ }
+
+
+
+ ui32Offset = psStream->ui32RPtr;
+ ui32Len = 0;
+
+ while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit))
+ {
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+
+ psStream->ui32RPtr = ui32Offset + 1;
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+
+ return(ui32OutLen);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Space;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psMainStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psMainStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+ }
+ else if (psMainStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psMainStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ return(0xFFFFFFFFUL);
+ }
+
+ if(psMainStream->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+
+
+ if ((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ return(0);
+ }
+
+ if (ui32Space < 8)
+ {
+ return(0);
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 8;
+ }
+
+
+
+ Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+ }
+ else
+ {
+ if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+ return(0xFFFFFFFFUL);
+ }
+ }
+ }
+
+ return(DBGDrivWrite2(psStream,pui8InBuf,ui32InBuffSize,ui32Level));
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Space;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+ if(psMainStream->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+
+
+ if ((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ return(0);
+ }
+
+
+
+ if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+ {
+
+
+
+ if (ui32Space < 32)
+ {
+ return(0);
+ }
+ }
+ else
+ {
+ if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+ {
+ IMG_UINT32 ui32NewBufSize;
+
+
+
+ ui32NewBufSize = 2 * psStream->ui32Size;
+
+ if (ui32InBuffSize > psStream->ui32Size)
+ {
+ ui32NewBufSize += ui32InBuffSize;
+ }
+
+
+
+ if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
+ {
+ if (ui32Space < 32)
+ {
+ return(0);
+ }
+ }
+
+
+
+ ui32Space = SpaceInStream(psStream);
+ }
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 4;
+ }
+
+
+
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Data;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return(0);
+ }
+
+ if(bReadInitBuffer)
+ {
+ psStream = psMainStream->psInitStream;
+ }
+ else
+ {
+ psStream = psMainStream;
+ }
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ {
+ return(0);
+ }
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+ ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+ }
+ else
+ {
+ ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+ }
+
+
+
+ if (ui32Data > ui32OutBuffSize)
+ {
+ ui32Data = ui32OutBuffSize;
+ }
+
+
+
+ if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+ {
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+ IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr),
+ ui32B1);
+
+
+ HostMemCopy((IMG_VOID *)((IMG_UINT32) pui8OutBuf + ui32B1),
+ (IMG_VOID *)psStream->ui32Base,
+ ui32B2);
+
+
+ psStream->ui32RPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr),
+ ui32Data);
+
+
+ psStream->ui32RPtr += ui32Data;
+
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+ }
+
+ return(ui32Data);
+}
+
+void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32CapMode = ui32Mode;
+ psStream->ui32DefaultMode = ui32Mode;
+ psStream->ui32Start = ui32Start;
+ psStream->ui32End = ui32End;
+ psStream->ui32SampleRate = ui32SampleRate;
+
+
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ ActivateHotKeys(psStream);
+ }
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32Current = ui32Frame;
+
+ if ((ui32Frame >= psStream->ui32Start) &&
+ (ui32Frame <= psStream->ui32End) &&
+ (((ui32Frame - psStream->ui32Start) % psStream->ui32SampleRate) == 0))
+ {
+ psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ }
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+ (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+ (((ui32Frame - g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) == 0))
+ {
+ psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ if (psStream->ui32Current > g_ui32HotkeyMiddumpEnd)
+ {
+ g_bHotkeyMiddump = IMG_FALSE;
+ }
+ }
+ }
+
+
+ if (g_bHotKeyRegistered)
+ {
+ g_bHotKeyRegistered = IMG_FALSE;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Hotkey pressed (%08x)!\n",psStream));
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+
+
+
+ if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ ((psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
+ {
+ if (!g_bHotkeyMiddump)
+ {
+
+ g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
+ g_ui32HotkeyMiddumpEnd = 0xffffffff;
+ g_bHotkeyMiddump = IMG_TRUE;
+ PVR_DPF((PVR_DBG_MESSAGE,"Sampling every %d frame(s)\n", psStream->ui32SampleRate));
+ }
+ else
+ {
+
+ g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+ PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
+ }
+ }
+
+ }
+
+
+
+ if (psStream->ui32Current > g_ui32HotKeyFrame)
+ {
+ g_bHotKeyPressed = IMG_FALSE;
+ }
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0);
+ }
+
+ return(psStream->ui32Current);
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32NextFrame;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ ui32NextFrame = psStream->ui32Current + psStream->ui32SampleRate;
+ if (ui32NextFrame > psStream->ui32End)
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((psStream->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
+ (psStream->ui32Current <= (g_ui32HotkeyMiddumpEnd - ui32FrameShift)) &&
+ ((((psStream->ui32Current + ui32FrameShift) - g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ else
+ {
+ if ((psStream->ui32Current >= (psStream->ui32Start - ui32FrameShift)) &&
+ (psStream->ui32Current <= (psStream->ui32End - ui32FrameShift)) &&
+ ((((psStream->ui32Current + ui32FrameShift) - psStream->ui32Start) % psStream->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ }
+ else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->ui32Current == (g_ui32HotKeyFrame-ui32FrameShift)) && (g_bHotKeyPressed))
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32CapMode = psStream->ui32DefaultMode;
+}
+
+void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32Marker = ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return 0;
+ }
+
+ return psStream->ui32Marker;
+}
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return 0;
+ }
+
+ if(psMainStream->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ return psStream->ui32DataWritten;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return;
+ }
+
+ if(psMainStream->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetServiceTable(void)
+{
+ return((IMG_UINT32) &g_sDBGKMServices);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
+ {
+ if ((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+ }
+ else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ return(0xFFFFFFFFUL);
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ if (ui32Flags & WRITELF_FLAGS_RESETBUF)
+ {
+
+
+ ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen = ui32InBuffSize;
+ }
+ else
+ {
+
+
+ ui32InBuffSize = ((psLFBuffer->ui32BufLen + ui32InBuffSize) > LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE - psLFBuffer->ui32BufLen) : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)(&psLFBuffer->ui8Buffer[psLFBuffer->ui32BufLen]), (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen += ui32InBuffSize;
+ }
+
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ IMG_UINT32 ui32Data;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0);
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+
+
+ HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
+
+ return ui32Data;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+ psStream->bInitPhaseComplete = IMG_FALSE;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+ psStream->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+ HostWaitForEvent(eEvent);
+}
+#endif
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+ IMG_VOID * pvNewBuf;
+ IMG_UINT32 ui32NewSizeInPages;
+ IMG_UINT32 ui32NewWOffset;
+ IMG_UINT32 ui32SpaceInOldBuf;
+
+
+
+ if (psStream->ui32Size >= ui32NewSize)
+ {
+ return IMG_FALSE;
+ }
+
+
+
+ ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+
+
+ ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+ }
+ else
+ {
+ pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+ }
+
+ if (pvNewBuf == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+
+
+ HostMemCopy((IMG_VOID *)pvNewBuf, (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr), psStream->ui32WPtr - psStream->ui32RPtr);
+ }
+ else
+ {
+ IMG_UINT32 ui32FirstCopySize;
+
+
+
+ ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+ HostMemCopy((IMG_VOID *)pvNewBuf, (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr), ui32FirstCopySize);
+
+
+
+ HostMemCopy((IMG_VOID *)((IMG_UINT32)pvNewBuf + ui32FirstCopySize), (IMG_VOID *)psStream->ui32Base, psStream->ui32WPtr);
+ }
+
+
+
+ ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ }
+ else
+ {
+ HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+ }
+
+
+
+ psStream->ui32Base = (IMG_UINT32)pvNewBuf;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = ui32NewWOffset;
+ psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+ return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Space;
+
+ if (psStream->ui32RPtr > psStream->ui32WPtr)
+ {
+ ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+ }
+ else
+ {
+ ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+ }
+
+ return ui32Space;
+}
+
+
+void DestroyAllStreams(void)
+{
+ while (g_psStreamList != IMG_NULL)
+ {
+ DBGDrivDestroyStream(g_psStreamList);
+ }
+ return;
+}
+
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+ psLFBuffer = g_psLFBufferList;
+
+ while (psLFBuffer)
+ {
+ if (psLFBuffer->psStream == psStream)
+ {
+ break;
+ }
+
+ psLFBuffer = psLFBuffer->psNext;
+ }
+
+ return psLFBuffer;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
new file mode 100644
index 0000000..167e0f6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
@@ -0,0 +1,112 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE 64*PAGESIZE
+
+#define DBGDRIV_VERSION 0x100
+#define MAX_PROCESSES 2
+#define BLOCK_USED 0x01
+#define BLOCK_LOCKED 0x02
+#define DBGDRIV_MONOBASE 0x000B0000
+
+
+extern IMG_VOID * g_pvAPIMutex;
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Pages);
+IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+IMG_BOOL StreamValid(PDBG_STREAM psStream);
+IMG_VOID Write(PDBG_STREAM psStream,IMG_UINT8 *pui8Data,IMG_UINT32 ui32InBuffSize);
+IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
new file mode 100644
index 0000000..558d6fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
@@ -0,0 +1,54 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
new file mode 100644
index 0000000..7ea2b5a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
@@ -0,0 +1,131 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#if !defined(LINUX)
+#include <ntddk.h>
+#include <windef.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+
+IMG_UINT32 g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL g_bHotKeyRegistered = IMG_FALSE;
+
+PRIVATEHOTKEYDATA g_PrivateHotKeyData;
+
+
+IMG_VOID ReadInHotKeys(IMG_VOID)
+{
+ g_PrivateHotKeyData.ui32ScanCode = 0x58;
+ g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+
+
+#if 0
+ if (_RegOpenKey(HKEY_LOCAL_MACHINE,pszRegPath,&hKey) == ERROR_SUCCESS)
+ {
+
+
+ QueryReg(hKey,"ui32ScanCode",&g_PrivateHotKeyData.ui32ScanCode);
+ QueryReg(hKey,"ui32ShiftState",&g_PrivateHotKeyData.ui32ShiftState);
+ }
+#else
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode" , &g_PrivateHotKeyData.ui32ScanCode);
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
+#endif
+}
+
+IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
+{
+ PDBG_STREAM psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pInfo);
+
+ if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PDUMP Hotkey pressed !\n"));
+
+ psStream = (PDBG_STREAM) g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+ }
+}
+
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
+{
+
+
+ ReadInHotKeys();
+
+
+
+ if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
+ {
+ if (g_PrivateHotKeyData.ui32ScanCode != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
+
+
+
+ g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+ DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
+ }
+ else
+ {
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+ }
+}
+
+IMG_VOID DeactivateHotKeys(IMG_VOID)
+{
+ if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Deactivate HotKey.\n"));
+
+ RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
new file mode 100644
index 0000000..5f95d22
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
@@ -0,0 +1,56 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HOTKEY_
+#define _HOTKEY_
+
+
+typedef struct _hotkeyinfo
+{
+ IMG_UINT8 ui8ScanCode;
+ IMG_UINT8 ui8Type;
+ IMG_UINT8 ui8Flag;
+ IMG_UINT8 ui8Filler1;
+ IMG_UINT32 ui32ShiftState;
+ IMG_UINT32 ui32HotKeyProc;
+ IMG_VOID *pvStream;
+ IMG_UINT32 hHotKey;
+} HOTKEYINFO, *PHOTKEYINFO;
+
+typedef struct _privatehotkeydata
+{
+ IMG_UINT32 ui32ScanCode;
+ IMG_UINT32 ui32ShiftState;
+ HOTKEYINFO sHotKeyInfo;
+} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+
+
+IMG_VOID ReadInHotKeys (IMG_VOID);
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
+IMG_VOID DeactivateHotKeys(IMG_VOID);
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey);
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo);
+IMG_VOID RegisterKeyPressed (IMG_UINT32 ui32ScanCode, PHOTKEYINFO psInfo);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
new file mode 100644
index 0000000..6b130d7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
@@ -0,0 +1,367 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#endif
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_CREATESTREAM psIn;
+ IMG_VOID * *ppvOut;
+ #ifdef LINUX
+ static IMG_CHAR name[32];
+ #endif
+
+ psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+ ppvOut = (IMG_VOID * *) pvOutBuffer;
+
+ #ifdef LINUX
+
+ if(copy_from_user(name, psIn->pszName, 32) != 0)
+ {
+ return IMG_FALSE;
+ }
+
+ *ppvOut = ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode, 0, psIn->ui32Pages);
+
+ #else
+ *ppvOut = ExtDBGDrivCreateStream(psIn->pszName, psIn->ui32CapMode, psIn->ui32OutMode, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages);
+ #endif
+
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pStream;
+ PDBG_STREAM psStream;
+
+ pStream = (IMG_UINT32 *) pvInBuffer;
+ psStream = (PDBG_STREAM) *pStream;
+
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ ExtDBGDrivDestroyStream(psStream);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_FINDSTREAM psParams;
+ IMG_UINT32 * pui32Stream;
+
+ psParams = (PDBG_IN_FINDSTREAM)pvInBuffer;
+ pui32Stream = (IMG_UINT32 *)pvOutBuffer;
+
+ *pui32Stream = (IMG_UINT32)ExtDBGDrivFindStream(psParams->pszName, psParams->bResetStream);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 * pui32OutLen;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32OutLen = ExtDBGDrivWriteString((PDBG_STREAM) psParams->pvStream,psParams->pszString,psParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 * pui32OutLen;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32OutLen = ExtDBGDrivWriteStringCM((PDBG_STREAM) psParams->pvStream,psParams->pszString,psParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32OutLen;
+ PDBG_IN_READSTRING psParams;
+
+ psParams = (PDBG_IN_READSTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32OutLen = ExtDBGDrivReadString(psParams->pvStream,psParams->pszString,psParams->ui32StringLen);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivWrite((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivWrite2((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivWriteCM((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivRead((PDBG_STREAM) psInParams->pvStream,psInParams->bReadInitBuffer, psInParams->ui32OutBufferSize,psInParams->pui8OutBuffer);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGMODE psParams;
+
+ psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetCaptureMode((PDBG_STREAM) psParams->pvStream,
+ psParams->ui32Mode,
+ psParams->ui32Start,
+ psParams->ui32End,
+ psParams->ui32SampleRate);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGOUTMODE psParams;
+
+ psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetOutputMode((PDBG_STREAM) psParams->pvStream,psParams->ui32Mode);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGLEVEL psParams;
+
+ psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetDebugLevel((PDBG_STREAM) psParams->pvStream,psParams->ui32Level);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETFRAME psParams;
+
+ psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetFrame((PDBG_STREAM) psParams->pvStream,psParams->ui32Frame);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pStream;
+ PDBG_STREAM psStream;
+ IMG_UINT32 * pui32Current;
+
+ pStream = (IMG_UINT32 *) pvInBuffer;
+ psStream = (PDBG_STREAM) *pStream;
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivGetFrame(psStream);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_ISCAPTUREFRAME psParams;
+ IMG_UINT32 * pui32Current;
+
+ psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivIsCaptureFrame((PDBG_STREAM) psParams->pvStream, psParams->bCheckPreviousFrame);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_OVERRIDEMODE psParams;
+
+ psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ ExtDBGDrivOverrideMode((PDBG_STREAM) psParams->pvStream,psParams->ui32Mode);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pStream;
+ PDBG_STREAM psStream;
+
+ pStream = (IMG_UINT32 *) pvInBuffer;
+ psStream = (PDBG_STREAM) *pStream;
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivDefaultMode(psStream);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETMARKER psParams;
+
+ psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetMarker((PDBG_STREAM) psParams->pvStream, psParams->ui32Marker);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pStream;
+ PDBG_STREAM psStream;
+ IMG_UINT32 * pui32Current;
+
+ pStream = (IMG_UINT32 *) pvInBuffer;
+ psStream = (PDBG_STREAM) *pStream;
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivGetMarker(psStream);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32Out;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ pui32Out = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32Out = DBGDrivGetServiceTable();
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITE_LF psInParams;
+ IMG_UINT32 * pui32BytesCopied;
+
+ psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivWriteLF(psInParams->pvStream,
+ psInParams->pui8InBuffer,
+ psInParams->ui32BufferSize,
+ psInParams->ui32Level,
+ psInParams->ui32Flags);
+
+ return IMG_TRUE;
+}
+
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivReadLF((PDBG_STREAM) psInParams->pvStream,psInParams->ui32OutBufferSize,psInParams->pui8OutBuffer);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivWaitForEvent(eEvent);
+
+ return(IMG_TRUE);
+}
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
new file mode 100644
index 0000000..882408c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
@@ -0,0 +1,83 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _IOCTL_
+#define _IOCTL_
+
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID*, IMG_VOID *);
+
+IMG_UINT32 (*g_DBGDrivProc[])(IMG_VOID *, IMG_VOID *) =
+{
+ DBGDIOCDrivCreateStream,
+ DBGDIOCDrivDestroyStream,
+ DBGDIOCDrivGetStream,
+ DBGDIOCDrivWriteString,
+ DBGDIOCDrivReadString,
+ DBGDIOCDrivWrite,
+ DBGDIOCDrivRead,
+ DBGDIOCDrivSetCaptureMode,
+ DBGDIOCDrivSetOutMode,
+ DBGDIOCDrivSetDebugLevel,
+ DBGDIOCDrivSetFrame,
+ DBGDIOCDrivGetFrame,
+ DBGDIOCDrivOverrideMode,
+ DBGDIOCDrivDefaultMode,
+ DBGDIOCDrivGetServiceTable,
+ DBGDIOCDrivWrite2,
+ DBGDIOCDrivWriteStringCM,
+ DBGDIOCDrivWriteCM,
+ DBGDIOCDrivSetMarker,
+ DBGDIOCDrivGetMarker,
+ DBGDIOCDrivIsCaptureFrame,
+ DBGDIOCDrivWriteLF,
+ DBGDIOCDrivReadLF,
+ DBGDIOCDrivWaitForEvent
+};
+
+#define MAX_DBGVXD_W32_API (sizeof(g_DBGDrivProc)/sizeof(IMG_UINT32))
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
new file mode 100644
index 0000000..29c3427
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
@@ -0,0 +1,300 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif
+
+#include <linux/slab.h>
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "dbgdriv/common/hostfunc.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_UINT32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#define PVR_STRING_TERMINATOR '\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+void PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace, bDebug;
+#if !defined(__sh__)
+ IMG_CHAR *pszLeafName;
+
+ pszLeafName = (char *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+ bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+ if (bTrace || bDebug)
+ {
+ va_list vaArgs;
+ static char szBuffer[256];
+
+ va_start (vaArgs, pszFormat);
+
+
+ if (bDebug)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strcpy (szBuffer, "PVR_K:(Fatal): ");
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strcpy (szBuffer, "PVR_K:(Error): ");
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strcpy (szBuffer, "PVR_K:(Warning): ");
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strcpy (szBuffer, "PVR_K:(Message): ");
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strcpy (szBuffer, "PVR_K:(Verbose): ");
+ break;
+ }
+ default:
+ {
+ strcpy (szBuffer, "PVR_K:(Unknown message level)");
+ break;
+ }
+ }
+ }
+ else
+ {
+ strcpy (szBuffer, "PVR_K: ");
+ }
+
+ vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+
+
+ if (!bTrace)
+ {
+ sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
+ }
+
+ printk(KERN_INFO "%s\r\n", szBuffer);
+
+ va_end (vaArgs);
+ }
+}
+#endif
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+ memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ unsigned char *src,*dst;
+ int i;
+
+ src=(unsigned char *)pvSrc;
+ dst=(unsigned char *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ dst[i]=src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+
+ return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+
+ return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+
+}
+
+IMG_VOID * HostCreateMutex(IMG_VOID)
+{
+ struct semaphore *psSem;
+
+ psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+ if (psSem)
+ {
+ init_MUTEX(psSem);
+ }
+
+ return psSem;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (down_trylock((struct semaphore *)pvMutex))
+ {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ down((struct semaphore *)pvMutex);
+ }
+#else
+ down((struct semaphore *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+ up((struct semaphore *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+ if (pvMutex)
+ {
+ kfree(pvMutex);
+ }
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define EVENT_WAIT_TIMEOUT_MS 500
+#define EVENT_WAIT_TIMEOUT_JIFFIES (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+ init_waitqueue_head(&sStreamDataEvent);
+
+ return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+
+ wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+ iStreamData = 0;
+ break;
+ default:
+
+ msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+ break;
+ }
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+ iStreamData = 1;
+ wake_up_interruptible(&sStreamDataEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
new file mode 100644
index 0000000..44c1357
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
@@ -0,0 +1,33 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+#
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
+
+MODULE = dbgdrv
+
+INCLUDES =
+
+SOURCES =
+
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
new file mode 100644
index 0000000..08691c0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
@@ -0,0 +1,294 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRI_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRI_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include "drmP.h"
+#include "drm.h"
+#endif
+
+#include "img_types.h"
+#include "client/linuxsrv.h"
+#include "dbgdriv/common/ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv/common/dbgdriv.h"
+#include "dbgdriv/common/hostfunc.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+static struct class *psDbgDrvClass;
+#endif
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ return 0;
+}
+
+static struct file_operations dbgdrv_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dbgdrv_ioctl,
+ .open = dbgdrv_open,
+ .release = dbgdrv_release,
+ .mmap = dbgdrv_mmap,
+};
+
+#endif
+
+void DBGDrvGetServiceTable(void **fn_table)
+{
+ extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+ *fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void dbgdrv_cleanup(void)
+#else
+void cleanup_module(void)
+#endif
+{
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psDbgDrvClass);
+#endif
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+ HostDestroyMutex(g_pvAPIMutex);
+ return;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+int init_module(void)
+#endif
+{
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+ struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ int err = -EBUSY;
+#endif
+
+
+ if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+ {
+ return -ENOMEM;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+ (void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ AssignedMajorNumber =
+ register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+ goto ErrDestroyEventObjects;
+ }
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+ psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+ if (IS_ERR(psDbgDrvClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+ __func__, PTR_ERR(psDbgDrvClass)));
+ goto ErrUnregisterCharDev;
+ }
+
+ psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DRVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+ __func__, PTR_ERR(psDev)));
+ goto ErrDestroyClass;
+ }
+#endif
+#endif
+
+ return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ErrUnregisterCharDev:
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+ class_destroy(psDbgDrvClass);
+#endif
+ return err;
+#endif
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+ IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+ char *buffer, *in, *out;
+ unsigned int cmd;
+
+ if((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+ return -1;
+ }
+
+ buffer = (char *) HostPageablePageAlloc(1);
+ if(!buffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+ return -EFAULT;
+ }
+
+ in = buffer;
+ out = buffer + (PAGE_SIZE >>1);
+
+ if(copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ cmd = ((pIP->ui32Cmd >> 2) & 0xFFF) - 0x801;
+
+ if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
+ {
+ IMG_CHAR *ui8Tmp;
+ IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+ DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+
+ ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+
+ if(!ui8Tmp)
+ {
+ goto init_failed;
+ }
+
+ *pui32BytesCopied = ExtDBGDrivRead((DBG_STREAM *)psReadInParams->pvStream,
+ psReadInParams->bReadInitBuffer,
+ psReadInParams->ui32OutBufferSize,
+ ui8Tmp);
+
+ if(copy_to_user(psReadInParams->pui8OutBuffer,
+ ui8Tmp,
+ *pui32BytesCopied) != 0)
+ {
+ vfree(ui8Tmp);
+ goto init_failed;
+ }
+
+ vfree(ui8Tmp);
+ }
+ else
+ {
+ (g_DBGDrivProc[cmd])(in, out);
+ }
+
+ if(copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return 0;
+
+init_failed:
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return -EFAULT;
+}
+
+
+void RemoveHotKey(unsigned hHotKey)
+{
+
+}
+
+void DefineHotKey(unsigned ScanCode, unsigned ShiftState, void *pInfo)
+{
+
+}
+
+EXPORT_SYMBOL(DBGDrvGetServiceTable);
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
new file mode 100644
index 0000000..f9a1c7f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
@@ -0,0 +1,38 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DBGDRV_SOURCES_ROOT = $(KBUILDROOT)/../tools/intern/debug/dbgdriv
+else
+DBGDRV_SOURCES_ROOT = ../..
+endif
+
+INCLUDES += -I$(EURASIAROOT)/include4 \
+ -I$(EURASIAROOT)/tools/intern/debug
+
+SOURCES += $(DBGDRV_SOURCES_ROOT)/linux/main.c \
+ $(DBGDRV_SOURCES_ROOT)/common/dbgdriv.c \
+ $(DBGDRV_SOURCES_ROOT)/common/ioctl.c \
+ $(DBGDRV_SOURCES_ROOT)/linux/hostfunc.c \
+ $(DBGDRV_SOURCES_ROOT)/common/hotkey.c
--
1.8.1.4
More information about the linux-yocto
mailing list