staging: emgd: experimental build 2667 38/938/1
authorWang Quanxian <quanxian.wang@intel.com>
Fri, 10 Aug 2012 03:19:09 +0000 (11:19 +0800)
committerWang Quanxian <quanxian.wang@intel.com>
Fri, 10 Aug 2012 03:19:09 +0000 (11:19 +0800)
Signed-off-by: Quanxian Wang <quanxian.wang@intel.com>
358 files changed:
Kconfig [new file with mode: 0644]
Makefile [new file with mode: 0644]
emgd/cfg/config.h [new file with mode: 0644]
emgd/cfg/config_default.h [new file with mode: 0644]
emgd/cfg/config_helper.c [new file with mode: 0644]
emgd/core/init/cmn/igd_global.c [new file with mode: 0644]
emgd/core/init/cmn/igd_init.c [new file with mode: 0644]
emgd/core/init/cmn/init_dispatch.h [new file with mode: 0644]
emgd/core/init/plb/init_plb.c [new file with mode: 0644]
emgd/core/init/plb/micro_init_plb.c [new file with mode: 0644]
emgd/core/init/tnc/init_tnc.c [new file with mode: 0644]
emgd/core/init/tnc/micro_init_tnc.c [new file with mode: 0644]
emgd/display/dsp/cmn/dsp.c [new file with mode: 0755]
emgd/display/dsp/cmn/dsp_dispatch.h [new file with mode: 0644]
emgd/display/dsp/plb/dsp_plb.c [new file with mode: 0644]
emgd/display/dsp/tnc/dsp_tnc.c [new file with mode: 0644]
emgd/display/mode/cmn/igd_mode.c [new file with mode: 0755]
emgd/display/mode/cmn/match.c [new file with mode: 0755]
emgd/display/mode/cmn/match.h [new file with mode: 0755]
emgd/display/mode/cmn/micro_mode.c [new file with mode: 0644]
emgd/display/mode/cmn/mode_dispatch.h [new file with mode: 0644]
emgd/display/mode/cmn/vga_mode.c [new file with mode: 0644]
emgd/display/mode/plb/clocks_plb.c [new file with mode: 0644]
emgd/display/mode/plb/kms_mode_plb.c [new file with mode: 0644]
emgd/display/mode/plb/micro_mode_plb.c [new file with mode: 0644]
emgd/display/mode/plb/mode_plb.c [new file with mode: 0644]
emgd/display/mode/plb/mode_plb.h [new file with mode: 0644]
emgd/display/mode/tnc/clocks_tnc.c [new file with mode: 0644]
emgd/display/mode/tnc/kms_mode_tnc.c [new file with mode: 0644]
emgd/display/mode/tnc/micro_mode_tnc.c [new file with mode: 0644]
emgd/display/mode/tnc/mode_tnc.c [new file with mode: 0644]
emgd/display/mode/tnc/mode_tnc.h [new file with mode: 0644]
emgd/display/pd/cmn/pd.c [new file with mode: 0755]
emgd/display/pi/cmn/displayid.c [new file with mode: 0644]
emgd/display/pi/cmn/edid.c [new file with mode: 0644]
emgd/display/pi/cmn/i2c_dispatch.h [new file with mode: 0755]
emgd/display/pi/cmn/igd_pi.c [new file with mode: 0644]
emgd/display/pi/cmn/mode_table.c [new file with mode: 0644]
emgd/display/pi/cmn/pd_init_all.c [new file with mode: 0644]
emgd/display/pi/cmn/pi.c [new file with mode: 0755]
emgd/display/pi/plb/i2c_plb.c [new file with mode: 0644]
emgd/display/pi/tnc/i2c_bitbash_tnc.c [new file with mode: 0644]
emgd/display/pi/tnc/i2c_gmbus_tnc.c [new file with mode: 0644]
emgd/drm/drm_emgd_private.h [new file with mode: 0644]
emgd/drm/emgd_connector.c [new file with mode: 0644]
emgd/drm/emgd_crtc.c [new file with mode: 0644]
emgd/drm/emgd_drv.c [new file with mode: 0644]
emgd/drm/emgd_drv.h [new file with mode: 0644]
emgd/drm/emgd_encoder.c [new file with mode: 0644]
emgd/drm/emgd_fb.c [new file with mode: 0644]
emgd/drm/emgd_fbcon.c [new file with mode: 0644]
emgd/drm/emgd_interface.c [new file with mode: 0644]
emgd/drm/emgd_mmap.c [new file with mode: 0644]
emgd/drm/emgd_test_pvrsrv.c [new file with mode: 0644]
emgd/drm/image_data.h [new file with mode: 0755]
emgd/drm/splash_screen.c [new file with mode: 0755]
emgd/drm/splash_screen.h [new file with mode: 0755]
emgd/drm/user_config.c [new file with mode: 0644]
emgd/drm/user_config.h [new file with mode: 0644]
emgd/gmm/gmm.c [new file with mode: 0644]
emgd/gmm/gtt.c [new file with mode: 0644]
emgd/include/cmd.h [new file with mode: 0644]
emgd/include/context.h [new file with mode: 0644]
emgd/include/debug.h [new file with mode: 0644]
emgd/include/decode.h [new file with mode: 0644]
emgd/include/dispatch.h [new file with mode: 0644]
emgd/include/dispatch_utils.h [new file with mode: 0644]
emgd/include/displayid.h [new file with mode: 0644]
emgd/include/dsp.h [new file with mode: 0644]
emgd/include/edid.h [new file with mode: 0644]
emgd/include/general.h [new file with mode: 0644]
emgd/include/instr_common.h [new file with mode: 0644]
emgd/include/intelpci.h [new file with mode: 0644]
emgd/include/math_fix.h [new file with mode: 0644]
emgd/include/memlist.h [new file with mode: 0644]
emgd/include/memory.h [new file with mode: 0644]
emgd/include/mode.h [new file with mode: 0644]
emgd/include/mode_access.h [new file with mode: 0644]
emgd/include/module_init.h [new file with mode: 0644]
emgd/include/msvdx.h [new file with mode: 0644]
emgd/include/pci.h [new file with mode: 0644]
emgd/include/pd.h [new file with mode: 0644]
emgd/include/pd_init.h [new file with mode: 0644]
emgd/include/pi.h [new file with mode: 0644]
emgd/include/plb/appcontext.h [new file with mode: 0644]
emgd/include/plb/cmd.h [new file with mode: 0644]
emgd/include/plb/context.h [new file with mode: 0644]
emgd/include/plb/instr.h [new file with mode: 0644]
emgd/include/plb/mi.h [new file with mode: 0644]
emgd/include/plb/regs.h [new file with mode: 0644]
emgd/include/plb/sgx.h [new file with mode: 0644]
emgd/include/plb/state3d.h [new file with mode: 0644]
emgd/include/plb/state3d_plb.h [new file with mode: 0644]
emgd/include/psb_regs.h [new file with mode: 0644]
emgd/include/rb.h [new file with mode: 0644]
emgd/include/reset.h [new file with mode: 0644]
emgd/include/sched.h [new file with mode: 0644]
emgd/include/state2d.h [new file with mode: 0644]
emgd/include/tnc/appcontext.h [new file with mode: 0644]
emgd/include/tnc/cmd.h [new file with mode: 0644]
emgd/include/tnc/context.h [new file with mode: 0644]
emgd/include/tnc/igd_tnc_wa.h [new file with mode: 0644]
emgd/include/tnc/instr.h [new file with mode: 0644]
emgd/include/tnc/mi.h [new file with mode: 0644]
emgd/include/tnc/regs.h [new file with mode: 0644]
emgd/include/tnc/sgx.h [new file with mode: 0644]
emgd/include/tnc/state3d.h [new file with mode: 0644]
emgd/include/tnc/state3d_plb.h [new file with mode: 0644]
emgd/include/topaz.h [new file with mode: 0755]
emgd/include/utils.h [new file with mode: 0644]
emgd/include/vga.h [new file with mode: 0644]
emgd/oal/src/math_fix.c [new file with mode: 0644]
emgd/oal/src/memmap.c [new file with mode: 0644]
emgd/oal/src/pci.c [new file with mode: 0644]
emgd/pal/Makefile.include [new file with mode: 0644]
emgd/pal/ch7036/Makefile.gnu [new file with mode: 0644]
emgd/pal/ch7036/ch7036.c [new file with mode: 0755]
emgd/pal/ch7036/ch7036.def [new file with mode: 0644]
emgd/pal/ch7036/ch7036.h [new file with mode: 0755]
emgd/pal/ch7036/ch7036_attr.c [new file with mode: 0644]
emgd/pal/ch7036/ch7036_attr.h [new file with mode: 0644]
emgd/pal/ch7036/ch7036_def_regmap.h [new file with mode: 0755]
emgd/pal/ch7036/ch7036_fw.c [new file with mode: 0755]
emgd/pal/ch7036/ch7036_fw.h [new file with mode: 0755]
emgd/pal/ch7036/ch7036_iic.c [new file with mode: 0755]
emgd/pal/ch7036/ch7036_iic.h [new file with mode: 0755]
emgd/pal/ch7036/ch7036_intf.c [new file with mode: 0644]
emgd/pal/ch7036/ch7036_intf.h [new file with mode: 0644]
emgd/pal/ch7036/ch7036_pm.c [new file with mode: 0755]
emgd/pal/ch7036/ch7036_port.c [new file with mode: 0644]
emgd/pal/ch7036/ch7036_port.h [new file with mode: 0644]
emgd/pal/ch7036/ch7036_reg_table.c [new file with mode: 0755]
emgd/pal/ch7036/ch7036_reg_table.h [new file with mode: 0755]
emgd/pal/ch7036/ch7036_typedef.h [new file with mode: 0755]
emgd/pal/ch7036/config_.h [new file with mode: 0644]
emgd/pal/ch7036/edid7036.car [new file with mode: 0644]
emgd/pal/ch7036/lvds/lvds.c [new file with mode: 0644]
emgd/pal/ch7036/lvds/lvds.h [new file with mode: 0644]
emgd/pal/lpd/lpd.c [new file with mode: 0644]
emgd/pal/lpd/pd_print.h [new file with mode: 0644]
emgd/pal/lvds/lvds.c [new file with mode: 0644]
emgd/pal/lvds/lvds.h [new file with mode: 0644]
emgd/pal/sdvo/sdvo.def [new file with mode: 0644]
emgd/pal/sdvo/sdvo_attr.c [new file with mode: 0644]
emgd/pal/sdvo/sdvo_attr.h [new file with mode: 0644]
emgd/pal/sdvo/sdvo_hdmi.c [new file with mode: 0644]
emgd/pal/sdvo/sdvo_hdmi.h [new file with mode: 0644]
emgd/pal/sdvo/sdvo_intf.c [new file with mode: 0644]
emgd/pal/sdvo/sdvo_intf.h [new file with mode: 0644]
emgd/pal/sdvo/sdvo_port.c [new file with mode: 0644]
emgd/pal/sdvo/sdvo_port.h [new file with mode: 0644]
emgd/state/appcontext/cmn/appcontext_dispatch.h [new file with mode: 0644]
emgd/state/appcontext/cmn/igd_appcontext.c [new file with mode: 0755]
emgd/state/appcontext/plb/appcontext_plb.c [new file with mode: 0644]
emgd/state/power/cmn/igd_pwr.c [new file with mode: 0644]
emgd/state/power/cmn/pwr_dispatch.h [new file with mode: 0644]
emgd/state/power/plb/pwr_plb.c [new file with mode: 0644]
emgd/state/reg/cmn/reg.c [new file with mode: 0644]
emgd/state/reg/cmn/reg_dispatch.h [new file with mode: 0644]
emgd/state/reg/plb/reg_plb.c [new file with mode: 0644]
emgd/state/reg/tnc/reg_tnc.c [new file with mode: 0644]
emgd/utils/math_fix.c [new file with mode: 0644]
emgd/utils/memmap.c [new file with mode: 0644]
emgd/utils/pci.c [new file with mode: 0644]
emgd/video/msvdx/msvdx.c [new file with mode: 0644]
emgd/video/msvdx/msvdx_init.c [new file with mode: 0644]
emgd/video/msvdx/msvdx_pvr.c [new file with mode: 0644]
emgd/video/msvdx/msvdx_pvr.h [new file with mode: 0644]
emgd/video/overlay/cmn/igd_ovl.c [new file with mode: 0644]
emgd/video/overlay/cmn/micro_ovl.c [new file with mode: 0644]
emgd/video/overlay/cmn/ovl_coeff.c [new file with mode: 0644]
emgd/video/overlay/cmn/ovl_coeff.h [new file with mode: 0644]
emgd/video/overlay/cmn/ovl_dispatch.h [new file with mode: 0644]
emgd/video/overlay/cmn/ovl_virt.h [new file with mode: 0644]
emgd/video/overlay/plb/micro_ovl_plb.c [new file with mode: 0644]
emgd/video/overlay/plb/ovl2_plb.c [new file with mode: 0644]
emgd/video/overlay/plb/ovl2_plb.h [new file with mode: 0644]
emgd/video/overlay/plb/ovl2_regs_plb.h [new file with mode: 0644]
emgd/video/overlay/plb/ovl_plb.c [new file with mode: 0644]
emgd/video/overlay/plb/ovl_plb_cache.c [new file with mode: 0644]
emgd/video/overlay/plb/ovl_plb_cache.h [new file with mode: 0644]
emgd/video/overlay/plb/ovl_regs_plb.h [new file with mode: 0644]
emgd/video/overlay/tnc/micro_ovl_tnc.c [new file with mode: 0644]
emgd/video/overlay/tnc/ovl2_regs_tnc.h [new file with mode: 0644]
emgd/video/overlay/tnc/ovl2_tnc.c [new file with mode: 0644]
emgd/video/overlay/tnc/ovl2_tnc.h [new file with mode: 0644]
emgd/video/overlay/tnc/ovl_regs_tnc.h [new file with mode: 0644]
emgd/video/overlay/tnc/ovl_tnc.c [new file with mode: 0644]
emgd/video/overlay/tnc/ovl_tnc_cache.c [new file with mode: 0644]
emgd/video/overlay/tnc/ovl_tnc_cache.h [new file with mode: 0644]
emgd/video/topaz/topaz.c [new file with mode: 0644]
emgd/video/topaz/topaz_hdr.h [new file with mode: 0644]
emgd/video/topaz/topaz_init.c [new file with mode: 0644]
include/emgd_drm.h [new file with mode: 0644]
include/emgd_shared.h [new file with mode: 0644]
include/gart.h [new file with mode: 0644]
include/igd.h [new file with mode: 0644]
include/igd_2d.h [new file with mode: 0644]
include/igd_appcontext.h [new file with mode: 0644]
include/igd_blend.h [new file with mode: 0644]
include/igd_debug.h [new file with mode: 0644]
include/igd_errno.h [new file with mode: 0644]
include/igd_gart.h [new file with mode: 0644]
include/igd_gmm.h [new file with mode: 0644]
include/igd_init.h [new file with mode: 0644]
include/igd_interrupt.h [new file with mode: 0644]
include/igd_mode.h [new file with mode: 0644]
include/igd_ovl.h [new file with mode: 0644]
include/igd_pd.h [new file with mode: 0644]
include/igd_pi.h [new file with mode: 0644]
include/igd_pwr.h [new file with mode: 0644]
include/igd_rb.h [new file with mode: 0644]
include/igd_render.h [new file with mode: 0644]
include/igd_reset.h [new file with mode: 0644]
include/igd_version.h [new file with mode: 0644]
include/igd_vga.h [new file with mode: 0644]
include/io.h [new file with mode: 0644]
include/memmap.h [new file with mode: 0644]
pvr/include4/dbgdrvif.h [new file with mode: 0644]
pvr/include4/img_defs.h [new file with mode: 0644]
pvr/include4/img_types.h [new file with mode: 0644]
pvr/include4/ioctldef.h [new file with mode: 0644]
pvr/include4/pdumpdefs.h [new file with mode: 0644]
pvr/include4/pvr_debug.h [new file with mode: 0644]
pvr/include4/pvrmodule.h [new file with mode: 0644]
pvr/include4/pvrversion.h [new file with mode: 0644]
pvr/include4/regpaths.h [new file with mode: 0644]
pvr/include4/services.h [new file with mode: 0644]
pvr/include4/servicesext.h [new file with mode: 0644]
pvr/include4/sgx_options.h [new file with mode: 0644]
pvr/include4/sgxapi_km.h [new file with mode: 0644]
pvr/include4/sgxscript.h [new file with mode: 0644]
pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c [new file with mode: 0644]
pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h [new file with mode: 0644]
pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c [new file with mode: 0644]
pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c [new file with mode: 0644]
pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h [new file with mode: 0644]
pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c [new file with mode: 0644]
pvr/services4/include/env/linux/pvr_drm_shared.h [new file with mode: 0644]
pvr/services4/include/kernelbuffer.h [new file with mode: 0644]
pvr/services4/include/kerneldisplay.h [new file with mode: 0644]
pvr/services4/include/pvr_bridge.h [new file with mode: 0644]
pvr/services4/include/pvr_bridge_km.h [new file with mode: 0644]
pvr/services4/include/pvrmmap.h [new file with mode: 0644]
pvr/services4/include/pvrsrv_errors.h [new file with mode: 0755]
pvr/services4/include/servicesint.h [new file with mode: 0644]
pvr/services4/include/sgx_bridge.h [new file with mode: 0644]
pvr/services4/include/sgx_mkif_km.h [new file with mode: 0644]
pvr/services4/include/sgxinfo.h [new file with mode: 0644]
pvr/services4/srvkm/bridged/bridged_pvr_bridge.c [new file with mode: 0644]
pvr/services4/srvkm/bridged/bridged_pvr_bridge.h [new file with mode: 0644]
pvr/services4/srvkm/bridged/bridged_support.c [new file with mode: 0644]
pvr/services4/srvkm/bridged/bridged_support.h [new file with mode: 0644]
pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c [new file with mode: 0644]
pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h [new file with mode: 0644]
pvr/services4/srvkm/common/buffer_manager.c [new file with mode: 0644]
pvr/services4/srvkm/common/deviceclass.c [new file with mode: 0644]
pvr/services4/srvkm/common/devicemem.c [new file with mode: 0644]
pvr/services4/srvkm/common/handle.c [new file with mode: 0644]
pvr/services4/srvkm/common/hash.c [new file with mode: 0644]
pvr/services4/srvkm/common/lists.c [new file with mode: 0644]
pvr/services4/srvkm/common/mem.c [new file with mode: 0644]
pvr/services4/srvkm/common/mem_debug.c [new file with mode: 0644]
pvr/services4/srvkm/common/metrics.c [new file with mode: 0644]
pvr/services4/srvkm/common/pdump_common.c [new file with mode: 0644]
pvr/services4/srvkm/common/perproc.c [new file with mode: 0644]
pvr/services4/srvkm/common/power.c [new file with mode: 0644]
pvr/services4/srvkm/common/pvrsrv.c [new file with mode: 0644]
pvr/services4/srvkm/common/queue.c [new file with mode: 0644]
pvr/services4/srvkm/common/ra.c [new file with mode: 0644]
pvr/services4/srvkm/common/resman.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/mmu.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/mmu.h [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/pb.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxconfig.h [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxinfokm.h [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxinit.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxkick.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxpower.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxreset.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxtransfer.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxutils.c [new file with mode: 0644]
pvr/services4/srvkm/devices/sgx/sgxutils.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/env_data.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/env_perproc.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/event.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/event.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/kbuild/Makefile [new file with mode: 0644]
pvr/services4/srvkm/env/linux/linkage.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/lock.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mm.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mm.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mmap.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mmap.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/module.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mutex.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mutex.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mutils.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/mutils.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/osfunc.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/osperproc.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/pdump.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/private_data.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/proc.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/proc.h [new file with mode: 0644]
pvr/services4/srvkm/env/linux/pvr_bridge_k.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/pvr_debug.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/pvr_drm.c [new file with mode: 0644]
pvr/services4/srvkm/env/linux/pvr_drm.h [new file with mode: 0644]
pvr/services4/srvkm/hwdefs/sgx535defs.h [new file with mode: 0644]
pvr/services4/srvkm/hwdefs/sgx540defs.h [new file with mode: 0755]
pvr/services4/srvkm/hwdefs/sgx545defs.h [new file with mode: 0755]
pvr/services4/srvkm/hwdefs/sgxdefs.h [new file with mode: 0644]
pvr/services4/srvkm/hwdefs/sgxerrata.h [new file with mode: 0644]
pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h [new file with mode: 0644]
pvr/services4/srvkm/hwdefs/sgxmmu.h [new file with mode: 0644]
pvr/services4/srvkm/include/buffer_manager.h [new file with mode: 0644]
pvr/services4/srvkm/include/device.h [new file with mode: 0644]
pvr/services4/srvkm/include/handle.h [new file with mode: 0644]
pvr/services4/srvkm/include/hash.h [new file with mode: 0644]
pvr/services4/srvkm/include/lists.h [new file with mode: 0644]
pvr/services4/srvkm/include/metrics.h [new file with mode: 0644]
pvr/services4/srvkm/include/osfunc.h [new file with mode: 0644]
pvr/services4/srvkm/include/osperproc.h [new file with mode: 0644]
pvr/services4/srvkm/include/pdump_km.h [new file with mode: 0644]
pvr/services4/srvkm/include/pdump_osfunc.h [new file with mode: 0644]
pvr/services4/srvkm/include/perproc.h [new file with mode: 0644]
pvr/services4/srvkm/include/power.h [new file with mode: 0644]
pvr/services4/srvkm/include/queue.h [new file with mode: 0644]
pvr/services4/srvkm/include/ra.h [new file with mode: 0644]
pvr/services4/srvkm/include/resman.h [new file with mode: 0644]
pvr/services4/srvkm/include/services_headers.h [new file with mode: 0644]
pvr/services4/srvkm/include/srvkm.h [new file with mode: 0644]
pvr/services4/system/common/sysconfig.c [new file with mode: 0644]
pvr/services4/system/common/sysutils.c [new file with mode: 0644]
pvr/services4/system/include/oemfuncs.h [new file with mode: 0644]
pvr/services4/system/include/sys_pvr_drm_shared.h [new file with mode: 0644]
pvr/services4/system/include/syscommon.h [new file with mode: 0644]
pvr/services4/system/include/sysconfig.h [new file with mode: 0644]
pvr/services4/system/include/sysinfo.h [new file with mode: 0644]
pvr/services4/system/include/syslocal.h [new file with mode: 0644]
pvr/services4/system/plb/sysconfig.c [new file with mode: 0644]
pvr/services4/system/plb/sysplb.h [new file with mode: 0644]
pvr/services4/system/tnc/sysconfig.c [new file with mode: 0644]
pvr/services4/system/tnc/systnc.h [new file with mode: 0644]
pvr/tools/intern/debug/client/linuxsrv.h [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/hostfunc.h [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/hotkey.c [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/hotkey.h [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/ioctl.c [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/common/ioctl.h [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/linux/main.c [new file with mode: 0644]
pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common [new file with mode: 0644]

diff --git a/Kconfig b/Kconfig
new file mode 100644 (file)
index 0000000..46ca880
--- /dev/null
+++ b/Kconfig
@@ -0,0 +1,39 @@
+config  DRM_EMGD
+        tristate "Intel IVI EMGD Kernel Module Driver"
+       depends on DRM &&PCI
+       select FB_CFB_COPYAREA
+       select FB_CFB_FILLRECT
+       select FB_CFB_IMAGEBLIT
+       select DRM_KMS_HELPER
+       select DRM_TTM
+       default m
+       help
+        Choose this option if you have a Tunnel Creak platform.
+        If M is selected the module will be called emgd.
+
+choice
+       prompt "Build EMGD kernel driver as "
+       depends on DRM_EMGD
+       default DRM_EMGD_RELEASE
+
+config         DRM_EMGD_RELEASE
+       bool "Release"
+       depends on DRM_EMGD
+       help
+         Build EMGD driver as release
+
+config         DRM_EMGD_DEBUG
+       bool "Debug"
+       depends on DRM_EMGD
+       help
+         Build EMGD driver as debug
+
+endchoice
+
+config DRM_EMGD_PDUMP
+       bool "Support PDUMP"
+       depends on DRM_EMGD
+       default n
+       help
+         Choose "yes" to enable PDUMP feature.
+         This is used to help debug EMGD driver.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e0cc0d5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,248 @@
+EMGD_MOD_DIR = drivers/staging/emgd
+
+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
+DBGDRVDIR = pvr/tools/intern/debug/dbgdriv
+BUFFERCLASSDIR = pvr/services4/3rdparty/emgd_bufferclass
+
+BUILDDATE ?= $(shell date +%Y%m%d)
+
+include_dirs := \
+       -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 \
+        -Iinclude/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 \
+
+ccflags-y += $(include_dirs)
+
+ccflags-y += \
+       -DSUPPORT_DRI_DRM_EXT \
+        -DLINUX \
+        -DPVR_BUILD_DIR="\"emgd\"" \
+               -DPVR_BUILD_DATE="\"$(BUILDDATE)\"" \
+        -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
+
+ccflags-$(CONFIG_DRM_EMGD_RELEASE) += -DBUILD="\"release\"" -DPVR_BUILD_TYPE="\"release\"" -DRELEASE
+ccflags-$(CONFIG_DRM_EMGD_DEBUG) += -DBUILD="\"debug\"" -DPVR_BUILD_TYPE="\"debug\"" -DDEBUG -DDEBUG_BUILD_TYPE
+ccflags-$(COFNIG_DRM_EMGD_PDUMP) += -DPDUMP=1
+
+
+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 \
+
+
+DBGDRV_OBJS = $(DBGDRVDIR)/linux/main.o \
+              $(DBGDRVDIR)/common/dbgdriv.o \
+              $(DBGDRVDIR)/common/ioctl.o \
+              $(DBGDRVDIR)/linux/hostfunc.o \
+              $(DBGDRVDIR)/common/hotkey.o
+
+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
+
+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) \
+
+emgd-$(CONFIG_DRM_EMGD_PDUMP) += $(DBGDRV_OBJS)
+
+obj-$(CONFIG_DRM_EMGD) += emgd.o
diff --git a/emgd/cfg/config.h b/emgd/cfg/config.h
new file mode 100644 (file)
index 0000000..14e7ca8
--- /dev/null
@@ -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/emgd/cfg/config_default.h b/emgd/cfg/config_default.h
new file mode 100644 (file)
index 0000000..18e97f5
--- /dev/null
@@ -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/emgd/cfg/config_helper.c b/emgd/cfg/config_helper.c
new file mode 100644 (file)
index 0000000..a9e1327
--- /dev/null
@@ -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/emgd/core/init/cmn/igd_global.c b/emgd/core/init/cmn/igd_global.c
new file mode 100644 (file)
index 0000000..52bc62e
--- /dev/null
@@ -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/emgd/core/init/cmn/igd_init.c b/emgd/core/init/cmn/igd_init.c
new file mode 100644 (file)
index 0000000..335a796
--- /dev/null
@@ -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/emgd/core/init/cmn/init_dispatch.h b/emgd/core/init/cmn/init_dispatch.h
new file mode 100644 (file)
index 0000000..7c58997
--- /dev/null
@@ -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/emgd/core/init/plb/init_plb.c b/emgd/core/init/plb/init_plb.c
new file mode 100644 (file)
index 0000000..d6a92ac
--- /dev/null
@@ -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/emgd/core/init/plb/micro_init_plb.c b/emgd/core/init/plb/micro_init_plb.c
new file mode 100644 (file)
index 0000000..c91adb6
--- /dev/null
@@ -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, &gtt_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/emgd/core/init/tnc/init_tnc.c b/emgd/core/init/tnc/init_tnc.c
new file mode 100644 (file)
index 0000000..658da92
--- /dev/null
@@ -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/emgd/core/init/tnc/micro_init_tnc.c b/emgd/core/init/tnc/micro_init_tnc.c
new file mode 100644 (file)
index 0000000..cb803a1
--- /dev/null
@@ -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, &gtt_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/emgd/display/dsp/cmn/dsp.c b/emgd/display/dsp/cmn/dsp.c
new file mode 100755 (executable)
index 0000000..d4abefb
--- /dev/null
@@ -0,0 +1,2366 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+       unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+
+       EMGD_TRACE_ENTER;
+
+       /* Go through the port table */
+       while ((p = dsp_get_next_port(context, p, 0)) != NULL) {
+
+               port_value = EMGD_READ32(mmio + p->port_reg);
+               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=&current_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;
+                       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/emgd/display/dsp/cmn/dsp_dispatch.h b/emgd/display/dsp/cmn/dsp_dispatch.h
new file mode 100644 (file)
index 0000000..7812416
--- /dev/null
@@ -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/emgd/display/dsp/plb/dsp_plb.c b/emgd/display/dsp/plb/dsp_plb.c
new file mode 100644 (file)
index 0000000..9330537
--- /dev/null
@@ -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}, 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}, 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/emgd/display/dsp/tnc/dsp_tnc.c b/emgd/display/dsp/tnc/dsp_tnc.c
new file mode 100644 (file)
index 0000000..0697657
--- /dev/null
@@ -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}, 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}, 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/emgd/display/mode/cmn/igd_mode.c b/emgd/display/mode/cmn/igd_mode.c
new file mode 100755 (executable)
index 0000000..8457774
--- /dev/null
@@ -0,0 +1,2340 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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"
+
+/*!
+ * @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;
+
+       /* 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;
+
+
+       /* 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;
+
+       /* 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;
+
+       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;
+
+       if(dc != mode_context->fw_info->fw_dc) {
+               /* DC doesn't match */
+               return FALSE;
+       }
+
+       /* 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) <= 1) {
+
+                       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 = FALSE;
+
+               if( (fb_info->screen_pitch != pf->screen_pitch) ||
+                       (fb_info->width != pf->width) ||
+                       (fb_info->height != pf->height) ) {
+
+                       /* 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;
+                       ret = TRUE;
+               }
+
+       }
+
+       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/emgd/display/mode/cmn/match.c b/emgd/display/mode/cmn/match.c
new file mode 100755 (executable)
index 0000000..4db71aa
--- /dev/null
@@ -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/emgd/display/mode/cmn/match.h b/emgd/display/mode/cmn/match.h
new file mode 100755 (executable)
index 0000000..40a6721
--- /dev/null
@@ -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/emgd/display/mode/cmn/micro_mode.c b/emgd/display/mode/cmn/micro_mode.c
new file mode 100644 (file)
index 0000000..5d615aa
--- /dev/null
@@ -0,0 +1,1767 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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) ||
+                               (cfb->flags != fb_info->flags)) {
+                               /* 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)) {
+                       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");
+                       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");
+               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/emgd/display/mode/cmn/mode_dispatch.h b/emgd/display/mode/cmn/mode_dispatch.h
new file mode 100644 (file)
index 0000000..b2ae62e
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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);
+} 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/emgd/display/mode/cmn/vga_mode.c b/emgd/display/mode/cmn/vga_mode.c
new file mode 100644 (file)
index 0000000..546b699
--- /dev/null
@@ -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/emgd/display/mode/plb/clocks_plb.c b/emgd/display/mode/plb/clocks_plb.c
new file mode 100644 (file)
index 0000000..f39e9d2
--- /dev/null
@@ -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/emgd/display/mode/plb/kms_mode_plb.c b/emgd/display/mode/plb/kms_mode_plb.c
new file mode 100644 (file)
index 0000000..ec1546d
--- /dev/null
@@ -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/emgd/display/mode/plb/micro_mode_plb.c b/emgd/display/mode/plb/micro_mode_plb.c
new file mode 100644 (file)
index 0000000..9fbb378
--- /dev/null
@@ -0,0 +1,1378 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 {
+                               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/emgd/display/mode/plb/mode_plb.c b/emgd/display/mode/plb/mode_plb.c
new file mode 100644 (file)
index 0000000..ac6ea5d
--- /dev/null
@@ -0,0 +1,1946 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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);
+
+/*!
+ * @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;
+}
+
+
+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,
+};
+
diff --git a/emgd/display/mode/plb/mode_plb.h b/emgd/display/mode/plb/mode_plb.h
new file mode 100644 (file)
index 0000000..0c42d29
--- /dev/null
@@ -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/emgd/display/mode/tnc/clocks_tnc.c b/emgd/display/mode/tnc/clocks_tnc.c
new file mode 100644 (file)
index 0000000..8e58723
--- /dev/null
@@ -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@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/emgd/display/mode/tnc/kms_mode_tnc.c b/emgd/display/mode/tnc/kms_mode_tnc.c
new file mode 100644 (file)
index 0000000..53c2c71
--- /dev/null
@@ -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 OKI*/
+               } 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/emgd/display/mode/tnc/micro_mode_tnc.c b/emgd/display/mode/tnc/micro_mode_tnc.c
new file mode 100644 (file)
index 0000000..78f7ba4
--- /dev/null
@@ -0,0 +1,2646 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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@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 {
+                               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 OKI*/
+               } 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/emgd/display/mode/tnc/mode_tnc.c b/emgd/display/mode/tnc/mode_tnc.c
new file mode 100644 (file)
index 0000000..6c1e34b
--- /dev/null
@@ -0,0 +1,2074 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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.
+ *
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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>
+
+
+/* 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);
+
+/* 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)
+{
+       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)));
+
+       /* 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
+                */
+               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++;
+       }
+
+       /* 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_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 = EMGD_READ32(mmio_sdvo + PIPEB_CONF);
+
+       if(pipe_conf & BIT(31)) { /* pipe B is active */
+               timing = &mode_context->fw_info->timing_arr[0];
+
+               reg = EMGD_READ32(mmio_sdvo + 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++;
+
+               {
+                       /* 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;
+
+                       dpllb = EMGD_READ32(mmio_sdvo + DPLLBCNTR);
+                       fpb0  = EMGD_READ32(mmio_sdvo + FPB0);
+                       fpb1  = EMGD_READ32(mmio_sdvo + FPB1);
+
+                       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_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;
+                                       }
+                               }
+
+                               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 * (5 * (mb1+2) + (mb2+2));
+                               temp = temp /(nb+2);
+                               dclk = temp/(pb1*pb2);
+
+                               dclk = temp * ref_freq;
+
+                               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;
+}
+
+
+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,
+};
+
diff --git a/emgd/display/mode/tnc/mode_tnc.h b/emgd/display/mode/tnc/mode_tnc.h
new file mode 100644 (file)
index 0000000..98d667e
--- /dev/null
@@ -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/emgd/display/pd/cmn/pd.c b/emgd/display/pd/cmn/pd.c
new file mode 100755 (executable)
index 0000000..0ac0e9c
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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(!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/emgd/display/pi/cmn/displayid.c b/emgd/display/pi/cmn/displayid.c
new file mode 100644 (file)
index 0000000..186ce7d
--- /dev/null
@@ -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/emgd/display/pi/cmn/edid.c b/emgd/display/pi/cmn/edid.c
new file mode 100644 (file)
index 0000000..d8a3c36
--- /dev/null
@@ -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/emgd/display/pi/cmn/i2c_dispatch.h b/emgd/display/pi/cmn/i2c_dispatch.h
new file mode 100755 (executable)
index 0000000..ae98630
--- /dev/null
@@ -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/emgd/display/pi/cmn/igd_pi.c b/emgd/display/pi/cmn/igd_pi.c
new file mode 100644 (file)
index 0000000..1cf54ce
--- /dev/null
@@ -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/emgd/display/pi/cmn/mode_table.c b/emgd/display/pi/cmn/mode_table.c
new file mode 100644 (file)
index 0000000..d698875
--- /dev/null
@@ -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/emgd/display/pi/cmn/pd_init_all.c b/emgd/display/pi/cmn/pd_init_all.c
new file mode 100644 (file)
index 0000000..ba70fc8
--- /dev/null
@@ -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/emgd/display/pi/cmn/pi.c b/emgd/display/pi/cmn/pi.c
new file mode 100755 (executable)
index 0000000..8eca6c7
--- /dev/null
@@ -0,0 +1,1919 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+
+               /* 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/emgd/display/pi/plb/i2c_plb.c b/emgd/display/pi/plb/i2c_plb.c
new file mode 100644 (file)
index 0000000..7021e34
--- /dev/null
@@ -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/emgd/display/pi/tnc/i2c_bitbash_tnc.c b/emgd/display/pi/tnc/i2c_bitbash_tnc.c
new file mode 100644 (file)
index 0000000..89bf1ed
--- /dev/null
@@ -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/emgd/display/pi/tnc/i2c_gmbus_tnc.c b/emgd/display/pi/tnc/i2c_gmbus_tnc.c
new file mode 100644 (file)
index 0000000..ed8cbb9
--- /dev/null
@@ -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/emgd/drm/drm_emgd_private.h b/emgd/drm/drm_emgd_private.h
new file mode 100644 (file)
index 0000000..ead99dd
--- /dev/null
@@ -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/emgd/drm/emgd_connector.c b/emgd/drm/emgd_connector.c
new file mode 100644 (file)
index 0000000..b62c2ca
--- /dev/null
@@ -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/emgd/drm/emgd_crtc.c b/emgd/drm/emgd_crtc.c
new file mode 100644 (file)
index 0000000..c38e4f0
--- /dev/null
@@ -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/emgd/drm/emgd_drv.c b/emgd/drm/emgd_drv.c
new file mode 100644 (file)
index 0000000..c8709cf
--- /dev/null
@@ -0,0 +1,2502 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 emgd_drm_config_t config_drm;
+extern int context_count;
+
+/* 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),
+
+       /*
+        * 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|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_UNINIT, emgd_bc_ts_cmd_uninit,
+               DRM_AUTH|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_REQUEST_BUFFERS, emgd_bc_ts_cmd_request_buffers,
+               DRM_AUTH|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_RELEASE_BUFFERS, emgd_bc_ts_cmd_release_buffers,
+               DRM_AUTH|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_SET_BUFFER_INFO, emgd_bc_ts_set_buffer_info,
+               DRM_AUTH|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFERS_COUNT, emgd_bc_ts_get_buffers_count,
+               DRM_AUTH|DRM_UNLOCKED),
+       EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFER_INDEX, emgd_bc_ts_get_buffer_index,
+               DRM_AUTH|DRM_UNLOCKED),
+};
+
+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;
+
+
+
+/*!
+ * 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;
+               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");
+       }
+
+       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;
+
+       /*
+        * 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
+
+       /* 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);
+                       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/emgd/drm/emgd_drv.h b/emgd/drm/emgd_drv.h
new file mode 100644 (file)
index 0000000..c7e334a
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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);
+/* 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/emgd/drm/emgd_encoder.c b/emgd/drm/emgd_encoder.c
new file mode 100644 (file)
index 0000000..58ceece
--- /dev/null
@@ -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/emgd/drm/emgd_fb.c b/emgd/drm/emgd_fb.c
new file mode 100644 (file)
index 0000000..9d24d44
--- /dev/null
@@ -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, &gtt_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/emgd/drm/emgd_fbcon.c b/emgd/drm/emgd_fbcon.c
new file mode 100644 (file)
index 0000000..d3f02b3
--- /dev/null
@@ -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    = IGD_PF_BPP(priv->initfb_info.pixel_format);
+       mode_cmd.depth  = mode_cmd.bpp;
+#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/emgd/drm/emgd_interface.c b/emgd/drm/emgd_interface.c
new file mode 100644 (file)
index 0000000..4fb5c24
--- /dev/null
@@ -0,0 +1,2730 @@
+/*-----------------------------------------------------------------------------
+ * 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;
+
+       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);
+
+
+       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;
+
+       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");
+                               surf.offset = pipe1->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)];
+                               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;
+                               display = context->mod_dispatch.dsp_display_list[IGD_DC_SECONDARY(dc)];
+                       } else {
+                               y_offset = (pipe1->plane->fb_info->height / 2);
+                               display = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
+                       }
+
+                       /* Call Pan display to affect pt_info offsets */
+                       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){
+                               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->kernel_virt_addr,
+                                                               &(drm_data->fence_id));
+                       break;
+               case TNC_ENGINE_ENCODE:
+                       drm_data->rtn = process_video_encode_tnc(context, drm_data->offset,
+                                                               drm_data->kernel_virt_addr,
+                                                               &(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->fw_priv, drm_data->fw_size, 0);
+                       break;
+               case TNC_ENGINE_ENCODE:
+                       drm_data->rtn = topaz_init_tnc(drm_data->wb_offset, drm_data->wb_addr, drm_data->firm_addr);
+                       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;
+               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;
+}
diff --git a/emgd/drm/emgd_mmap.c b/emgd/drm/emgd_mmap.c
new file mode 100644 (file)
index 0000000..c1d13a2
--- /dev/null
@@ -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/emgd/drm/emgd_test_pvrsrv.c b/emgd/drm/emgd_test_pvrsrv.c
new file mode 100644 (file)
index 0000000..6ba4567
--- /dev/null
@@ -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/emgd/drm/image_data.h b/emgd/drm/image_data.h
new file mode 100755 (executable)
index 0000000..6ca9967
--- /dev/null
@@ -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/emgd/drm/splash_screen.c b/emgd/drm/splash_screen.c
new file mode 100755 (executable)
index 0000000..f429894
--- /dev/null
@@ -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/emgd/drm/splash_screen.h b/emgd/drm/splash_screen.h
new file mode 100755 (executable)
index 0000000..5fac725
--- /dev/null
@@ -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/emgd/drm/user_config.c b/emgd/drm/user_config.c
new file mode 100644 (file)
index 0000000..cea78e1
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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_gamma_red */
+       0,      /* ovl_gamma_green */
+       0,      /* ovl_gamma_blue */
+       &splash_screen_data,
+       &splash_video_data,
+       &config_params  /* driver parameters from above */
+};
+
diff --git a/emgd/drm/user_config.h b/emgd/drm/user_config.h
new file mode 100644 (file)
index 0000000..5aca4d8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 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;
+} emgd_drm_config_t;
+
+#endif
diff --git a/emgd/gmm/gmm.c b/emgd/gmm/gmm.c
new file mode 100644 (file)
index 0000000..b44dec7
--- /dev/null
@@ -0,0 +1,1401 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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>
+
+#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;
+       };
+#define MAX_CI_LIST_SIZE 14
+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;
+}
+
+/*
+ * 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, /* virtaddr or v4l2_offset */
+                       unsigned long *virt_addr,
+                       unsigned int map_method,
+                       unsigned long size)
+
+{
+       unsigned char i;
+       int ret;
+
+       if(map_method){
+               ret = gmm_map_to_graphics(virt_to_phys((unsigned long *)ci_param),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 = ci_param;
+                                       ci_surfaces[i].size = size;
+                                       ci_surfaces[i].gtt_offset = *gtt_offset;
+                                       *virt_addr = ci_param;
+                                       break;
+                               }
+                       }
+               }
+       }
+       else{
+
+               for(i=0;i<MAX_CI_LIST_SIZE;i++){
+                       if(ci_surfaces[i].used && (ci_surfaces[i].v4l2_offset ==ci_param)){
+
+                               *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) {
+               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;
+                       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;
+}
+
+struct emgd_ci_meminfo_t {
+       unsigned long v4l2_offset;
+       unsigned long virt;
+       unsigned long  size;
+       };
+
+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, &gtt_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 = virt_to_phys((unsigned long *)ci_meminfo->virt);
+                       ci_surfaces[i].size =  ci_meminfo->size;
+                       ci_surfaces[i].gtt_offset =  gtt_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/emgd/gmm/gtt.c b/emgd/gmm/gtt.c
new file mode 100644 (file)
index 0000000..f530ca6
--- /dev/null
@@ -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(&gtt_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(&gtt_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(&gtt_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(&gtt_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/emgd/include/cmd.h b/emgd/include/cmd.h
new file mode 100644 (file)
index 0000000..e1787ec
--- /dev/null
@@ -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/emgd/include/context.h b/emgd/include/context.h
new file mode 100644 (file)
index 0000000..c1afb31
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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);
+
+       /* 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/emgd/include/debug.h b/emgd/include/debug.h
new file mode 100644 (file)
index 0000000..3a12fc1
--- /dev/null
@@ -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/emgd/include/decode.h b/emgd/include/decode.h
new file mode 100644 (file)
index 0000000..ac2415a
--- /dev/null
@@ -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/emgd/include/dispatch.h b/emgd/include/dispatch.h
new file mode 100644 (file)
index 0000000..c5a371f
--- /dev/null
@@ -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/emgd/include/dispatch_utils.h b/emgd/include/dispatch_utils.h
new file mode 100644 (file)
index 0000000..b6e4f73
--- /dev/null
@@ -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/emgd/include/displayid.h b/emgd/include/displayid.h
new file mode 100644 (file)
index 0000000..82a995f
--- /dev/null
@@ -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/emgd/include/dsp.h b/emgd/include/dsp.h
new file mode 100644 (file)
index 0000000..8a803bf
--- /dev/null
@@ -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/emgd/include/edid.h b/emgd/include/edid.h
new file mode 100644 (file)
index 0000000..829e272
--- /dev/null
@@ -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/emgd/include/general.h b/emgd/include/general.h
new file mode 100644 (file)
index 0000000..159bf23
--- /dev/null
@@ -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/emgd/include/instr_common.h b/emgd/include/instr_common.h
new file mode 100644 (file)
index 0000000..95c7e38
--- /dev/null
@@ -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/emgd/include/intelpci.h b/emgd/include/intelpci.h
new file mode 100644 (file)
index 0000000..b389cc7
--- /dev/null
@@ -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/emgd/include/math_fix.h b/emgd/include/math_fix.h
new file mode 100644 (file)
index 0000000..91306fe
--- /dev/null
@@ -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/emgd/include/memlist.h b/emgd/include/memlist.h
new file mode 100644 (file)
index 0000000..5801fef
--- /dev/null
@@ -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/emgd/include/memory.h b/emgd/include/memory.h
new file mode 100644 (file)
index 0000000..f85477c
--- /dev/null
@@ -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/emgd/include/mode.h b/emgd/include/mode.h
new file mode 100644 (file)
index 0000000..1cb8a2c
--- /dev/null
@@ -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/emgd/include/mode_access.h b/emgd/include/mode_access.h
new file mode 100644 (file)
index 0000000..307739a
--- /dev/null
@@ -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/emgd/include/module_init.h b/emgd/include/module_init.h
new file mode 100644 (file)
index 0000000..8feafea
--- /dev/null
@@ -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/emgd/include/msvdx.h b/emgd/include/msvdx.h
new file mode 100644 (file)
index 0000000..f0699af
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 *virt_addr, 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 *msvdx_fw, unsigned long msvdx_fw_size, 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/emgd/include/pci.h b/emgd/include/pci.h
new file mode 100644 (file)
index 0000000..9a5fc5c
--- /dev/null
@@ -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/emgd/include/pd.h b/emgd/include/pd.h
new file mode 100644 (file)
index 0000000..388a2af
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 */
+}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/emgd/include/pd_init.h b/emgd/include/pd_init.h
new file mode 100644 (file)
index 0000000..eb78285
--- /dev/null
@@ -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/emgd/include/pi.h b/emgd/include/pi.h
new file mode 100644 (file)
index 0000000..d14d39e
--- /dev/null
@@ -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/emgd/include/plb/appcontext.h b/emgd/include/plb/appcontext.h
new file mode 100644 (file)
index 0000000..3a1417c
--- /dev/null
@@ -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/emgd/include/plb/cmd.h b/emgd/include/plb/cmd.h
new file mode 100644 (file)
index 0000000..c4252cb
--- /dev/null
@@ -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/emgd/include/plb/context.h b/emgd/include/plb/context.h
new file mode 100644 (file)
index 0000000..563c232
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+} 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;
+    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/emgd/include/plb/instr.h b/emgd/include/plb/instr.h
new file mode 100644 (file)
index 0000000..791808a
--- /dev/null
@@ -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/emgd/include/plb/mi.h b/emgd/include/plb/mi.h
new file mode 100644 (file)
index 0000000..fcbc706
--- /dev/null
@@ -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/emgd/include/plb/regs.h b/emgd/include/plb/regs.h
new file mode 100644 (file)
index 0000000..95d880f
--- /dev/null
@@ -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/emgd/include/plb/sgx.h b/emgd/include/plb/sgx.h
new file mode 100644 (file)
index 0000000..b882efc
--- /dev/null
@@ -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/emgd/include/plb/state3d.h b/emgd/include/plb/state3d.h
new file mode 100644 (file)
index 0000000..68f4a80
--- /dev/null
@@ -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/emgd/include/plb/state3d_plb.h b/emgd/include/plb/state3d_plb.h
new file mode 100644 (file)
index 0000000..37327bc
--- /dev/null
@@ -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/emgd/include/psb_regs.h b/emgd/include/psb_regs.h
new file mode 100644 (file)
index 0000000..01edb09
--- /dev/null
@@ -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/emgd/include/rb.h b/emgd/include/rb.h
new file mode 100644 (file)
index 0000000..8e0c166
--- /dev/null
@@ -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/emgd/include/reset.h b/emgd/include/reset.h
new file mode 100644 (file)
index 0000000..809cb52
--- /dev/null
@@ -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/emgd/include/sched.h b/emgd/include/sched.h
new file mode 100644 (file)
index 0000000..1abba3c
--- /dev/null
@@ -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/emgd/include/state2d.h b/emgd/include/state2d.h
new file mode 100644 (file)
index 0000000..af04e47
--- /dev/null
@@ -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/emgd/include/tnc/appcontext.h b/emgd/include/tnc/appcontext.h
new file mode 100644 (file)
index 0000000..0c76cf1
--- /dev/null
@@ -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/emgd/include/tnc/cmd.h b/emgd/include/tnc/cmd.h
new file mode 100644 (file)
index 0000000..731c86a
--- /dev/null
@@ -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/emgd/include/tnc/context.h b/emgd/include/tnc/context.h
new file mode 100644 (file)
index 0000000..bcd73ee
--- /dev/null
@@ -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/emgd/include/tnc/igd_tnc_wa.h b/emgd/include/tnc/igd_tnc_wa.h
new file mode 100644 (file)
index 0000000..7cd4aa7
--- /dev/null
@@ -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/emgd/include/tnc/instr.h b/emgd/include/tnc/instr.h
new file mode 100644 (file)
index 0000000..14bf85f
--- /dev/null
@@ -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/emgd/include/tnc/mi.h b/emgd/include/tnc/mi.h
new file mode 100644 (file)
index 0000000..2bb8c23
--- /dev/null
@@ -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/emgd/include/tnc/regs.h b/emgd/include/tnc/regs.h
new file mode 100644 (file)
index 0000000..218722c
--- /dev/null
@@ -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/emgd/include/tnc/sgx.h b/emgd/include/tnc/sgx.h
new file mode 100644 (file)
index 0000000..c43d490
--- /dev/null
@@ -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/emgd/include/tnc/state3d.h b/emgd/include/tnc/state3d.h
new file mode 100644 (file)
index 0000000..b32aea2
--- /dev/null
@@ -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/emgd/include/tnc/state3d_plb.h b/emgd/include/tnc/state3d_plb.h
new file mode 100644 (file)
index 0000000..fd5e628
--- /dev/null
@@ -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/emgd/include/topaz.h b/emgd/include/topaz.h
new file mode 100755 (executable)
index 0000000..e14b46c
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 *virt_addr, unsigned long *fence_id);
+int topaz_init_tnc(unsigned long wb_offset, void *wb_addr, void *firm_addr);
+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);
+
+#endif
diff --git a/emgd/include/utils.h b/emgd/include/utils.h
new file mode 100644 (file)
index 0000000..18fe9c3
--- /dev/null
@@ -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/emgd/include/vga.h b/emgd/include/vga.h
new file mode 100644 (file)
index 0000000..1c9b782
--- /dev/null
@@ -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/emgd/oal/src/math_fix.c b/emgd/oal/src/math_fix.c
new file mode 100644 (file)
index 0000000..84e5811
--- /dev/null
@@ -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/emgd/oal/src/memmap.c b/emgd/oal/src/memmap.c
new file mode 100644 (file)
index 0000000..2ee0812
--- /dev/null
@@ -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/emgd/oal/src/pci.c b/emgd/oal/src/pci.c
new file mode 100644 (file)
index 0000000..ff8a28c
--- /dev/null
@@ -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/emgd/pal/Makefile.include b/emgd/pal/Makefile.include
new file mode 100644 (file)
index 0000000..c312c51
--- /dev/null
@@ -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/emgd/pal/ch7036/Makefile.gnu b/emgd/pal/ch7036/Makefile.gnu
new file mode 100644 (file)
index 0000000..3ea81d8
--- /dev/null
@@ -0,0 +1,43 @@
+#----------------------------------------------------------------------------
+# Filename: Makefile.gnu
+# $Revision: 1.1.2.1 $
+#----------------------------------------------------------------------------
+# INTEL CONFIDENTIAL
+# Copyright (2002-2008) Intel Corporation All Rights Reserved.
+# The source code contained or described herein and all documents related to
+# the source code ("Material") are owned by Intel Corporation or its suppliers
+# or licensors. Title to the Material remains with Intel Corporation or its
+# suppliers and licensors. The Material contains trade secrets and proprietary
+# and confidential information of Intel or its suppliers and licensors. The
+# Material is protected by worldwide copyright and trade secret laws and
+# treaty provisions. No part of the Material may be used, copied, reproduced,
+# modified, published, uploaded, posted, transmitted, distributed, or
+# disclosed in any way without Intel's prior express written permission.
+#
+# No license under any patent, copyright, trade secret or other intellectual
+# property right is granted to or conferred upon you by disclosure or
+# delivery of the Materials, either expressly, by implication, inducement,
+# estoppel or otherwise. Any license under such intellectual property rights
+# must be express and approved by Intel in writing.
+#
+#----------------------------------------------------------------------------
+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/emgd/pal/ch7036/ch7036.c b/emgd/pal/ch7036/ch7036.c
new file mode 100755 (executable)
index 0000000..76c3726
--- /dev/null
@@ -0,0 +1,2364 @@
+/*-----------------------------------------------------------------------------
+* 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/emgd/pal/ch7036/ch7036.def b/emgd/pal/ch7036/ch7036.def
new file mode 100644 (file)
index 0000000..566e872
--- /dev/null
@@ -0,0 +1,5 @@
+LIBRARY ch7036
+
+EXPORTS
+    get_version
+    dpd_init
diff --git a/emgd/pal/ch7036/ch7036.h b/emgd/pal/ch7036/ch7036.h
new file mode 100755 (executable)
index 0000000..b138174
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_attr.c b/emgd/pal/ch7036/ch7036_attr.c
new file mode 100644 (file)
index 0000000..a183d19
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_attr.h b/emgd/pal/ch7036/ch7036_attr.h
new file mode 100644 (file)
index 0000000..8c3aa21
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_def_regmap.h b/emgd/pal/ch7036/ch7036_def_regmap.h
new file mode 100755 (executable)
index 0000000..fe2e79a
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_fw.c b/emgd/pal/ch7036/ch7036_fw.c
new file mode 100755 (executable)
index 0000000..61c9dd7
--- /dev/null
@@ -0,0 +1,466 @@
+/*-----------------------------------------------------------------------------
+* 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/emgd/pal/ch7036/ch7036_fw.h b/emgd/pal/ch7036/ch7036_fw.h
new file mode 100755 (executable)
index 0000000..1dc77ee
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_iic.c b/emgd/pal/ch7036/ch7036_iic.c
new file mode 100755 (executable)
index 0000000..a26f866
--- /dev/null
@@ -0,0 +1,294 @@
+/*-----------------------------------------------------------------------------
+* 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/emgd/pal/ch7036/ch7036_iic.h b/emgd/pal/ch7036/ch7036_iic.h
new file mode 100755 (executable)
index 0000000..fd168db
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_intf.c b/emgd/pal/ch7036/ch7036_intf.c
new file mode 100644 (file)
index 0000000..b406710
--- /dev/null
@@ -0,0 +1,1993 @@
+/*-----------------------------------------------------------------------------
+* 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;
+
+\r#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/emgd/pal/ch7036/ch7036_intf.h b/emgd/pal/ch7036/ch7036_intf.h
new file mode 100644 (file)
index 0000000..0efb4da
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_pm.c b/emgd/pal/ch7036/ch7036_pm.c
new file mode 100755 (executable)
index 0000000..4429bce
--- /dev/null
@@ -0,0 +1,490 @@
+/*-----------------------------------------------------------------------------
+* 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);
+
+
+               I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) | 0x80 );
+
+
+               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);
+
+               I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) & 0x7F );
+
+               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/emgd/pal/ch7036/ch7036_port.c b/emgd/pal/ch7036/ch7036_port.c
new file mode 100644 (file)
index 0000000..1d33f50
--- /dev/null
@@ -0,0 +1,1546 @@
+/*-----------------------------------------------------------------------------
+* 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
+
+
+       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
+
+       return PD_SUCCESS;
+}
+
+
+
+
+
+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
+
+
+       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);
+
+               I2CWrite(p_ch7xxx_context,0x4E, I2CRead(p_ch7xxx_context,0x4E) & 0x7F);
+
+               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/emgd/pal/ch7036/ch7036_port.h b/emgd/pal/ch7036/ch7036_port.h
new file mode 100644 (file)
index 0000000..64ea9a5
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_reg_table.c b/emgd/pal/ch7036/ch7036_reg_table.c
new file mode 100755 (executable)
index 0000000..62d5a36
--- /dev/null
@@ -0,0 +1,222 @@
+/*-----------------------------------------------------------------------------
+* 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/emgd/pal/ch7036/ch7036_reg_table.h b/emgd/pal/ch7036/ch7036_reg_table.h
new file mode 100755 (executable)
index 0000000..cc12975
--- /dev/null
@@ -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/emgd/pal/ch7036/ch7036_typedef.h b/emgd/pal/ch7036/ch7036_typedef.h
new file mode 100755 (executable)
index 0000000..35e3f91
--- /dev/null
@@ -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/emgd/pal/ch7036/config_.h b/emgd/pal/ch7036/config_.h
new file mode 100644 (file)
index 0000000..c0c43bb
--- /dev/null
@@ -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/emgd/pal/ch7036/edid7036.car b/emgd/pal/ch7036/edid7036.car
new file mode 100644 (file)
index 0000000..b95f002
--- /dev/null
@@ -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/emgd/pal/ch7036/lvds/lvds.c b/emgd/pal/ch7036/lvds/lvds.c
new file mode 100644 (file)
index 0000000..d5636c5
--- /dev/null
@@ -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 \96 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/emgd/pal/ch7036/lvds/lvds.h b/emgd/pal/ch7036/lvds/lvds.h
new file mode 100644 (file)
index 0000000..6d552f5
--- /dev/null
@@ -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/emgd/pal/lpd/lpd.c b/emgd/pal/lpd/lpd.c
new file mode 100644 (file)
index 0000000..a180772
--- /dev/null
@@ -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/emgd/pal/lpd/pd_print.h b/emgd/pal/lpd/pd_print.h
new file mode 100644 (file)
index 0000000..8893e1b
--- /dev/null
@@ -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/emgd/pal/lvds/lvds.c b/emgd/pal/lvds/lvds.c
new file mode 100644 (file)
index 0000000..fff6756
--- /dev/null
@@ -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 \96 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/emgd/pal/lvds/lvds.h b/emgd/pal/lvds/lvds.h
new file mode 100644 (file)
index 0000000..dd9cc87
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo.def b/emgd/pal/sdvo/sdvo.def
new file mode 100644 (file)
index 0000000..f271b16
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_attr.c b/emgd/pal/sdvo/sdvo_attr.c
new file mode 100644 (file)
index 0000000..6d2d3c8
--- /dev/null
@@ -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, &reg);
+                                       sdvo_write_i2c_reg(p_ctx, 0x3C, (reg & 0xFC));
+                                       sdvo_read_i2c_reg(p_ctx, 0x3E, &reg);
+                                       sdvo_write_i2c_reg(p_ctx, 0x3E, (reg | 0x80));
+                               }
+                               else /* turn off EMI */
+                               {
+                                       sdvo_read_i2c_reg(p_ctx, 0x3C, &reg);
+                                       sdvo_write_i2c_reg(p_ctx, 0x3C, (reg | 0x01));
+                                       sdvo_read_i2c_reg(p_ctx, 0x3E, &reg);
+                                       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_OKI) &&
+                               (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_OKI) &&
+                       (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/emgd/pal/sdvo/sdvo_attr.h b/emgd/pal/sdvo/sdvo_attr.h
new file mode 100644 (file)
index 0000000..4c58315
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_hdmi.c b/emgd/pal/sdvo/sdvo_hdmi.c
new file mode 100644 (file)
index 0000000..81dd8f7
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_hdmi.h b/emgd/pal/sdvo/sdvo_hdmi.h
new file mode 100644 (file)
index 0000000..64c06c1
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_intf.c b/emgd/pal/sdvo/sdvo_intf.c
new file mode 100644 (file)
index 0000000..e2fb741
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_intf.h b/emgd/pal/sdvo/sdvo_intf.h
new file mode 100644 (file)
index 0000000..e861af4
--- /dev/null
@@ -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/emgd/pal/sdvo/sdvo_port.c b/emgd/pal/sdvo/sdvo_port.c
new file mode 100644 (file)
index 0000000..7651199
--- /dev/null
@@ -0,0 +1,3898 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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_OKI)
+               && (p_ctx->dev_cap.device_id != 0x1)){
+               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_OKI)
+               && (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, &reg);
+
+               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);
+               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);
+               reg |= 1;
+               sdvo_write_i2c_reg(p_ctx, 0x7F, reg);
+
+               sdvo_read_i2c_reg(p_ctx, 0x6C, &reg);
+               reg |= 0x03;
+               sdvo_write_i2c_reg(p_ctx, 0x6C, reg);
+
+               sdvo_read_i2c_reg(p_ctx, 0x7F, &reg);
+               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 *)&params[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, &params[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 OKI solution only.
+       It would probably give problem if the SDVO is connected to
+       analog display, but that is not the usage model for OKI.
+       */
+       if ((p_ctx->dev_cap.vendor_id == VENDOR_ID_OKI)
+               && (p_ctx->dev_cap.device_id == 0x1)){
+               /* The OKI 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 OKI */
+       if((p_ctx->dev_cap.vendor_id == VENDOR_ID_OKI)
+               && (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 OKI 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 OKI */
+       if(p_ctx->dev_cap.vendor_id == VENDOR_ID_OKI
+               && 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 OKI 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);
+                       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_OKI)
+               && (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/emgd/pal/sdvo/sdvo_port.h b/emgd/pal/sdvo/sdvo_port.h
new file mode 100644 (file)
index 0000000..b06fc73
--- /dev/null
@@ -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);
+
+/*OKI Workaround*/
+#define        VENDOR_ID_OKI 0x81
+
+
+#endif  /*  _SDVO_PORT_H_ */
diff --git a/emgd/state/appcontext/cmn/appcontext_dispatch.h b/emgd/state/appcontext/cmn/appcontext_dispatch.h
new file mode 100644 (file)
index 0000000..3da03e0
--- /dev/null
@@ -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/emgd/state/appcontext/cmn/igd_appcontext.c b/emgd/state/appcontext/cmn/igd_appcontext.c
new file mode 100755 (executable)
index 0000000..c5ee392
--- /dev/null
@@ -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/emgd/state/appcontext/plb/appcontext_plb.c b/emgd/state/appcontext/plb/appcontext_plb.c
new file mode 100644 (file)
index 0000000..568e24f
--- /dev/null
@@ -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/emgd/state/power/cmn/igd_pwr.c b/emgd/state/power/cmn/igd_pwr.c
new file mode 100644 (file)
index 0000000..2cfd775
--- /dev/null
@@ -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/emgd/state/power/cmn/pwr_dispatch.h b/emgd/state/power/cmn/pwr_dispatch.h
new file mode 100644 (file)
index 0000000..34043ba
--- /dev/null
@@ -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/emgd/state/power/plb/pwr_plb.c b/emgd/state/power/plb/pwr_plb.c
new file mode 100644 (file)
index 0000000..22d3280
--- /dev/null
@@ -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/emgd/state/reg/cmn/reg.c b/emgd/state/reg/cmn/reg.c
new file mode 100644 (file)
index 0000000..e030f0d
--- /dev/null
@@ -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, &reg_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+       {PCI_DEVICE_ID_VGA_TNC, &reg_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 = &reg_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 = &reg_ctx->device_state->flags;
+                       if((**flags & IGD_REG_SAVE_MODE)){
+                               *state = &reg_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/emgd/state/reg/cmn/reg_dispatch.h b/emgd/state/reg/cmn/reg_dispatch.h
new file mode 100644 (file)
index 0000000..985fa44
--- /dev/null
@@ -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/emgd/state/reg/plb/reg_plb.c b/emgd/state/reg/plb/reg_plb.c
new file mode 100644 (file)
index 0000000..5e11ac8
--- /dev/null
@@ -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,
+       &reg_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, &reg_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, &reg_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,
+                               &reg_buffer->mode_buffer,
+                               &reg_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, &reg_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,
+                               &reg_buffer->mode_buffer,
+                               &reg_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, &reg_args->dac_state, reg_platform_context);
+       }
+
+       /* Restore VGA registers */
+       if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+               reg_restore_vga_plb(context, &reg_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/emgd/state/reg/tnc/reg_tnc.c b/emgd/state/reg/tnc/reg_tnc.c
new file mode 100644 (file)
index 0000000..13263e5
--- /dev/null
@@ -0,0 +1,1241 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 */
+       unsigned long sgx_phyaddr;
+       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 clk_gating_ctl;
+       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,
+       &reg_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, &reg_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, &reg_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,
+                               &reg_buffer->mode_buffer,
+                               &reg_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, &reg_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,
+                               &reg_buffer->mode_buffer,
+                               &reg_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, &reg_args->dac_state, reg_platform_context);
+       }
+
+       /* Restore VGA registers */
+       if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+               reg_restore_vga_tnc(context, &reg_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_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);
+       }
+
+       /* Save the address of the SGX MMU */
+       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_tnc(igd_context_t *context,
+       reg_buffer_tnc_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 tablep */
+       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: The following code restore the SGX MMU. 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/emgd/utils/math_fix.c b/emgd/utils/math_fix.c
new file mode 100644 (file)
index 0000000..84e5811
--- /dev/null
@@ -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/emgd/utils/memmap.c b/emgd/utils/memmap.c
new file mode 100644 (file)
index 0000000..2ee0812
--- /dev/null
@@ -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/emgd/utils/pci.c b/emgd/utils/pci.c
new file mode 100644 (file)
index 0000000..969fc6d
--- /dev/null
@@ -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/emgd/video/msvdx/msvdx.c b/emgd/video/msvdx/msvdx.c
new file mode 100644 (file)
index 0000000..87b1105
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+       unsigned long submit_id;
+       unsigned long context_id;
+       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++) {
+               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;
+               }
+
+               /* 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/emgd/video/msvdx/msvdx_init.c b/emgd/video/msvdx/msvdx_init.c
new file mode 100644 (file)
index 0000000..c3b550d
--- /dev/null
@@ -0,0 +1,1603 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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*/
+
+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;
+
+       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.
+        * Where this is documented other than the UMG code is not clear.
+        */
+       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 *msvdx_fw, unsigned long msvdx_fw_size, 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;
+
+    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 && msvdx_fw) {
+               fw = (msvdx_fw_t *) msvdx_fw;
+               priv_fw = kzalloc(sizeof(msvdx_fw_t), GFP_KERNEL);
+               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);
+               memcpy(priv_fw->fw_text, (void *) ((unsigned long) msvdx_fw) +
+                               ((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);
+               memcpy(priv_fw->fw_data, (void *) ((unsigned long) msvdx_fw) +
+                       ((unsigned long) fw->fw_data), fw_size);
+
+               priv_fw->fw_version = kzalloc(priv_fw->fw_version_size, GFP_KERNEL);
+               strcpy(priv_fw->fw_version, (char *) (((unsigned long) msvdx_fw) +
+                       ((unsigned long) fw->fw_version)));
+       } else if (!priv_fw) {
+               printk(KERN_INFO "Kernel firmware is not loaded");
+               if(init_msvdx_first_time) {
+                       printk(KERN_ERR "ALAN!!! !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;
+
+       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 *virt_addr, 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;
+    EMGD_TRACE_ENTER;
+
+
+    platform = (platform_context_plb_t *)context->platform_context;
+
+       mtx_buf = (unsigned long *) virt_addr;
+    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_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, 0, 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, 0, 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;
+
+    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/emgd/video/msvdx/msvdx_pvr.c b/emgd/video/msvdx/msvdx_pvr.c
new file mode 100644 (file)
index 0000000..2b56e9d
--- /dev/null
@@ -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/emgd/video/msvdx/msvdx_pvr.h b/emgd/video/msvdx/msvdx_pvr.h
new file mode 100644 (file)
index 0000000..070c935
--- /dev/null
@@ -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/emgd/video/overlay/cmn/igd_ovl.c b/emgd/video/overlay/cmn/igd_ovl.c
new file mode 100644 (file)
index 0000000..299c781
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+               }
+       }
+
+       for (cur_ovl = 0; cur_ovl < OVL_MAX_HW; cur_ovl++) {
+               if (ovl_displays[cur_ovl] != NULL) {
+                       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/emgd/video/overlay/cmn/micro_ovl.c b/emgd/video/overlay/cmn/micro_ovl.c
new file mode 100644 (file)
index 0000000..7a15220
--- /dev/null
@@ -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/emgd/video/overlay/cmn/ovl_coeff.c b/emgd/video/overlay/cmn/ovl_coeff.c
new file mode 100644 (file)
index 0000000..fc08f0e
--- /dev/null
@@ -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/emgd/video/overlay/cmn/ovl_coeff.h b/emgd/video/overlay/cmn/ovl_coeff.h
new file mode 100644 (file)
index 0000000..60cadb7
--- /dev/null
@@ -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/emgd/video/overlay/cmn/ovl_dispatch.h b/emgd/video/overlay/cmn/ovl_dispatch.h
new file mode 100644 (file)
index 0000000..4487071
--- /dev/null
@@ -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/emgd/video/overlay/cmn/ovl_virt.h b/emgd/video/overlay/cmn/ovl_virt.h
new file mode 100644 (file)
index 0000000..7b0a998
--- /dev/null
@@ -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 2
+
+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/emgd/video/overlay/plb/micro_ovl_plb.c b/emgd/video/overlay/plb/micro_ovl_plb.c
new file mode 100644 (file)
index 0000000..c58e890
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl2_plb.c b/emgd/video/overlay/plb/ovl2_plb.c
new file mode 100644 (file)
index 0000000..816c3ab
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl2_plb.h b/emgd/video/overlay/plb/ovl2_plb.h
new file mode 100644 (file)
index 0000000..dca46bc
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl2_regs_plb.h b/emgd/video/overlay/plb/ovl2_regs_plb.h
new file mode 100644 (file)
index 0000000..6460560
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl_plb.c b/emgd/video/overlay/plb/ovl_plb.c
new file mode 100644 (file)
index 0000000..39d4a36
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl_plb_cache.c b/emgd/video/overlay/plb/ovl_plb_cache.c
new file mode 100644 (file)
index 0000000..d05c475
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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)       );
+
+}
+
+/* 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/emgd/video/overlay/plb/ovl_plb_cache.h b/emgd/video/overlay/plb/ovl_plb_cache.h
new file mode 100644 (file)
index 0000000..b8bb2ef
--- /dev/null
@@ -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/emgd/video/overlay/plb/ovl_regs_plb.h b/emgd/video/overlay/plb/ovl_regs_plb.h
new file mode 100644 (file)
index 0000000..34b24c4
--- /dev/null
@@ -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/emgd/video/overlay/tnc/micro_ovl_tnc.c b/emgd/video/overlay/tnc/micro_ovl_tnc.c
new file mode 100644 (file)
index 0000000..e4e7847
--- /dev/null
@@ -0,0 +1,1738 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+
+       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_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;
+
+       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_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/emgd/video/overlay/tnc/ovl2_regs_tnc.h b/emgd/video/overlay/tnc/ovl2_regs_tnc.h
new file mode 100644 (file)
index 0000000..9f2ac10
--- /dev/null
@@ -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/emgd/video/overlay/tnc/ovl2_tnc.c b/emgd/video/overlay/tnc/ovl2_tnc.c
new file mode 100644 (file)
index 0000000..c73d2b5
--- /dev/null
@@ -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/emgd/video/overlay/tnc/ovl2_tnc.h b/emgd/video/overlay/tnc/ovl2_tnc.h
new file mode 100644 (file)
index 0000000..300e826
--- /dev/null
@@ -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/emgd/video/overlay/tnc/ovl_regs_tnc.h b/emgd/video/overlay/tnc/ovl_regs_tnc.h
new file mode 100644 (file)
index 0000000..06e85f7
--- /dev/null
@@ -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/emgd/video/overlay/tnc/ovl_tnc.c b/emgd/video/overlay/tnc/ovl_tnc.c
new file mode 100644 (file)
index 0000000..116489c
--- /dev/null
@@ -0,0 +1,2128 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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"
+
+
+/*-----------------------------------------------------------------------------
+ * 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}
+};
+
+#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;
+
+       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_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);
+
+       /*************************************************************************
+        * 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_tnc->col_ctl_sat_hue =
+               (ovl_regs_tnc->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_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;
+}
diff --git a/emgd/video/overlay/tnc/ovl_tnc_cache.c b/emgd/video/overlay/tnc/ovl_tnc_cache.c
new file mode 100644 (file)
index 0000000..f3d162e
--- /dev/null
@@ -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/emgd/video/overlay/tnc/ovl_tnc_cache.h b/emgd/video/overlay/tnc/ovl_tnc_cache.h
new file mode 100644 (file)
index 0000000..0df413a
--- /dev/null
@@ -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/emgd/video/topaz/topaz.c b/emgd/video/topaz/topaz.c
new file mode 100644 (file)
index 0000000..f710ff2
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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>
+
+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 {
+                       EMGD_ERROR("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 = size;
+       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;
+       cur_cmd_size = cur_cmd_header->size;
+       cur_cmd_id = cur_cmd_header->id;
+
+       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)) {
+                                       EMGD_ERROR("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--;
+                       default:
+                               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) {
+                                       EMGD_ERROR("TOPAZ: error -- ret(%d)\n", ret);
+                                       return -IGD_ERROR_INVAL;
+                               }
+                               break;
+                       }
+        /* save frame skip flag for query */
+        /*topaz_priv->topaz_frame_skip = 0; CCB_CTRL_FRAMESKIP(context);*/
+        /* current command done */
+               command += cur_cmd_size;
+               cmd_size -= cur_cmd_size;
+
+               /* Get next command */
+               cur_cmd_header = (struct topaz_cmd_header *) command;
+               cur_cmd_size = cur_cmd_header->size;
+               cur_cmd_id = cur_cmd_header->id;
+       }
+       topaz_sync_tnc(context); 
+
+       return 0;
+}
diff --git a/emgd/video/topaz/topaz_hdr.h b/emgd/video/topaz/topaz_hdr.h
new file mode 100644 (file)
index 0000000..3545684
--- /dev/null
@@ -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/emgd/video/topaz/topaz_init.c b/emgd/video/topaz/topaz_init.c
new file mode 100644 (file)
index 0000000..4401b69
--- /dev/null
@@ -0,0 +1,985 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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>
+
+/* 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);
+
+/* According to UMG code this define is important */
+#define RAM_SIZE (1024 * 24)
+
+/* 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*/
+       }
+};
+
+
+int topaz_init_tnc(unsigned long wb_offset, void *wb_addr, void *firmware_addr)
+{
+       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;
+
+       priv = gpDrmDevice->dev_private;
+       context = priv->context;
+       mmio = context->device_context.virt_mmadr;
+
+       /* 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;
+
+       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;
+
+       size = WRITEBACK_MEM_SIZE;
+
+       GMM_SET_DEBUG_NAME("TOPAZ Writeback Memory");
+
+       topaz_priv->topaz_wb_offset = wb_offset;
+       topaz_priv->topaz_ccb_wb = (unsigned char *)wb_addr;
+
+       /* 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;
+       /*
+       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);
+       */      
+       
+       *(topaz_priv->topaz_sync_addr) = 0; /*reset sync seq */
+       topaz_priv->topaz_sync_id = 0; /*reset sync id */
+
+       /* firmware part */
+       /* allocate memory for all firmwares */
+       /* to check, is allocate or not */
+       if ( !firmware[1].text && firmware_addr) {
+               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, firmware_addr, 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;
+
+       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 */
+       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 *virt_addr, 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;
+
+       EMGD_TRACE_ENTER;
+
+       platform = (platform_context_plb_t *)context->platform_context;
+       topaz_priv = &platform->tpz_private_data;
+       mtx_buf = (unsigned long *) virt_addr;
+
+       EMGD_DEBUG("process_video_encode_tnc where buf=%p, offset=%lx\n",
+               mtx_buf, offset);
+
+       platform->topaz_busy = 1;
+       ret = process_encode_mtx_messages(context, mtx_buf, size);
+       if (ret){
+               printk(KERN_INFO "Invalid topaz encode cmd");
+       ret = -EINVAL;
+        }
+
+       *fence_id = topaz_priv->topaz_sync_id;
+       platform->topaz_busy = 0;
+       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;
+
+       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;
+
+       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/include/emgd_drm.h b/include/emgd_drm.h
new file mode 100644 (file)
index 0000000..d4a8df8
--- /dev/null
@@ -0,0 +1,927 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 *kernel_virt_addr;
+       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 *fw_priv;
+                       unsigned long fw_size;
+               };
+               struct {
+                       unsigned long wb_offset;
+                       void *wb_addr;
+                       void *firm_addr;
+               };
+               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;
+} emgd_drm_bc_ts_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
+/* 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_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/include/emgd_shared.h b/include/emgd_shared.h
new file mode 100644 (file)
index 0000000..fe576ed
--- /dev/null
@@ -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/include/gart.h b/include/gart.h
new file mode 100644 (file)
index 0000000..228ac41
--- /dev/null
@@ -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/include/igd.h b/include/igd.h
new file mode 100644 (file)
index 0000000..2c81c51
--- /dev/null
@@ -0,0 +1,1625 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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);
+
+       /*!
+        * 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);
+} igd_dispatch_t;
+
+#endif
diff --git a/include/igd_2d.h b/include/igd_2d.h
new file mode 100644 (file)
index 0000000..f7ee253
--- /dev/null
@@ -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/include/igd_appcontext.h b/include/igd_appcontext.h
new file mode 100644 (file)
index 0000000..d987937
--- /dev/null
@@ -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/include/igd_blend.h b/include/igd_blend.h
new file mode 100644 (file)
index 0000000..2ea3eb6
--- /dev/null
@@ -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/include/igd_debug.h b/include/igd_debug.h
new file mode 100644 (file)
index 0000000..455b182
--- /dev/null
@@ -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/include/igd_errno.h b/include/igd_errno.h
new file mode 100644 (file)
index 0000000..ee0c69c
--- /dev/null
@@ -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/include/igd_gart.h b/include/igd_gart.h
new file mode 100644 (file)
index 0000000..568e271
--- /dev/null
@@ -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/include/igd_gmm.h b/include/igd_gmm.h
new file mode 100644 (file)
index 0000000..b262a14
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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*/
+/*
+ * 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;
+
+
+
+/*!
+ * @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/include/igd_init.h b/include/igd_init.h
new file mode 100644 (file)
index 0000000..c382b0d
--- /dev/null
@@ -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/include/igd_interrupt.h b/include/igd_interrupt.h
new file mode 100644 (file)
index 0000000..6886a20
--- /dev/null
@@ -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/include/igd_mode.h b/include/igd_mode.h
new file mode 100644 (file)
index 0000000..6fc61a7
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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
+        */
+
+       unsigned long saved_offset;
+       /*!
+        * @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/include/igd_ovl.h b/include/igd_ovl.h
new file mode 100644 (file)
index 0000000..0c4ac4c
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+} 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 2
+
+/* 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/include/igd_pd.h b/include/igd_pd.h
new file mode 100644 (file)
index 0000000..2c36267
--- /dev/null
@@ -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/include/igd_pi.h b/include/igd_pi.h
new file mode 100644 (file)
index 0000000..bc12a5b
--- /dev/null
@@ -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/include/igd_pwr.h b/include/igd_pwr.h
new file mode 100644 (file)
index 0000000..3564031
--- /dev/null
@@ -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/include/igd_rb.h b/include/igd_rb.h
new file mode 100644 (file)
index 0000000..3008870
--- /dev/null
@@ -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/include/igd_render.h b/include/igd_render.h
new file mode 100644 (file)
index 0000000..c492918
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+
+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/include/igd_reset.h b/include/igd_reset.h
new file mode 100644 (file)
index 0000000..6150b6c
--- /dev/null
@@ -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/include/igd_version.h b/include/igd_version.h
new file mode 100644 (file)
index 0000000..55cfb0b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_version.h
+ * $Revision: 1.233 $
+ *-----------------------------------------------------------------------------
+ * 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  14
+#define IGD_BUILD_NUM  2667
+
+#define IGD_PCF_VERSION   0x00000400
+#endif
diff --git a/include/igd_vga.h b/include/igd_vga.h
new file mode 100644 (file)
index 0000000..1f232f0
--- /dev/null
@@ -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/include/io.h b/include/io.h
new file mode 100644 (file)
index 0000000..9b534df
--- /dev/null
@@ -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/include/memmap.h b/include/memmap.h
new file mode 100644 (file)
index 0000000..a02e943
--- /dev/null
@@ -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/pvr/include4/dbgdrvif.h b/pvr/include4/dbgdrvif.h
new file mode 100644 (file)
index 0000000..0527e7b
--- /dev/null
@@ -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/pvr/include4/img_defs.h b/pvr/include4/img_defs.h
new file mode 100644 (file)
index 0000000..454a68f
--- /dev/null
@@ -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/pvr/include4/img_types.h b/pvr/include4/img_types.h
new file mode 100644 (file)
index 0000000..a7b92e1
--- /dev/null
@@ -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/pvr/include4/ioctldef.h b/pvr/include4/ioctldef.h
new file mode 100644 (file)
index 0000000..d7e494a
--- /dev/null
@@ -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/pvr/include4/pdumpdefs.h b/pvr/include4/pdumpdefs.h
new file mode 100644 (file)
index 0000000..6285c6d
--- /dev/null
@@ -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/pvr/include4/pvr_debug.h b/pvr/include4/pvr_debug.h
new file mode 100644 (file)
index 0000000..8459841
--- /dev/null
@@ -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/pvr/include4/pvrmodule.h b/pvr/include4/pvrmodule.h
new file mode 100644 (file)
index 0000000..8aa4b20
--- /dev/null
@@ -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@imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+#endif
diff --git a/pvr/include4/pvrversion.h b/pvr/include4/pvrversion.h
new file mode 100644 (file)
index 0000000..25bc19b
--- /dev/null
@@ -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/pvr/include4/regpaths.h b/pvr/include4/regpaths.h
new file mode 100644 (file)
index 0000000..29a5574
--- /dev/null
@@ -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/pvr/include4/services.h b/pvr/include4/services.h
new file mode 100644 (file)
index 0000000..0b8efbb
--- /dev/null
@@ -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/pvr/include4/servicesext.h b/pvr/include4/servicesext.h
new file mode 100644 (file)
index 0000000..0f3dc1d
--- /dev/null
@@ -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/pvr/include4/sgx_options.h b/pvr/include4/sgx_options.h
new file mode 100644 (file)
index 0000000..75d1286
--- /dev/null
@@ -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/pvr/include4/sgxapi_km.h b/pvr/include4/sgxapi_km.h
new file mode 100644 (file)
index 0000000..5302204
--- /dev/null
@@ -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/pvr/include4/sgxscript.h b/pvr/include4/sgxscript.h
new file mode 100644 (file)
index 0000000..c6d080b
--- /dev/null
@@ -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/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c b/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
new file mode 100644 (file)
index 0000000..55a791e
--- /dev/null
@@ -0,0 +1,384 @@
+/***************************************************************************
+ *
+ * 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);
+    }
+       if (IMG_NULL != pbMapped) {
+               *pbMapped = IMG_TRUE;
+       }
+    psBuffer = (BC_BUFFER *)hBuffer;
+
+       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/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h b/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
new file mode 100644 (file)
index 0000000..7d5b5e3
--- /dev/null
@@ -0,0 +1,173 @@
+/**********************************************************************
+ *
+ * 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*/
+    } 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/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c b/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
new file mode 100644 (file)
index 0000000..ca987b9
--- /dev/null
@@ -0,0 +1,999 @@
+/****************************************************************************
+ *
+ * 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 "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 */
+#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);
+    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;
+       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->width <= 1 || p->height <= 1) {
+        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;
+        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) {
+               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);
+
+       for (i = 0; i < DevInfo->sBufferInfo.ui32BufferCount; i++) {
+               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 5 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);
+
+       /* 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;
+
+       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 {
+               bcBuf->psSysAddr[0].uiAddr = psBridge->phyaddr;
+       }
+
+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/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c b/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
new file mode 100644 (file)
index 0000000..0e503f8
--- /dev/null
@@ -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/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h b/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
new file mode 100644 (file)
index 0000000..8ea6d33
--- /dev/null
@@ -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/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c b/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
new file mode 100644 (file)
index 0000000..c8d8cdf
--- /dev/null
@@ -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/pvr/services4/include/env/linux/pvr_drm_shared.h b/pvr/services4/include/env/linux/pvr_drm_shared.h
new file mode 100644 (file)
index 0000000..7f0f445
--- /dev/null
@@ -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/pvr/services4/include/kernelbuffer.h b/pvr/services4/include/kernelbuffer.h
new file mode 100644 (file)
index 0000000..4bf59b1
--- /dev/null
@@ -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/pvr/services4/include/kerneldisplay.h b/pvr/services4/include/kerneldisplay.h
new file mode 100644 (file)
index 0000000..b14c131
--- /dev/null
@@ -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/pvr/services4/include/pvr_bridge.h b/pvr/services4/include/pvr_bridge.h
new file mode 100644 (file)
index 0000000..9e6004e
--- /dev/null
@@ -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/pvr/services4/include/pvr_bridge_km.h b/pvr/services4/include/pvr_bridge_km.h
new file mode 100644 (file)
index 0000000..063ffb5
--- /dev/null
@@ -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/pvr/services4/include/pvrmmap.h b/pvr/services4/include/pvrmmap.h
new file mode 100644 (file)
index 0000000..54f1121
--- /dev/null
@@ -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/pvr/services4/include/pvrsrv_errors.h b/pvr/services4/include/pvrsrv_errors.h
new file mode 100755 (executable)
index 0000000..7c8ed47
--- /dev/null
@@ -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/pvr/services4/include/servicesint.h b/pvr/services4/include/servicesint.h
new file mode 100644 (file)
index 0000000..4ef3939
--- /dev/null
@@ -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/pvr/services4/include/sgx_bridge.h b/pvr/services4/include/sgx_bridge.h
new file mode 100644 (file)
index 0000000..61a147c
--- /dev/null
@@ -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/pvr/services4/include/sgx_mkif_km.h b/pvr/services4/include/sgx_mkif_km.h
new file mode 100644 (file)
index 0000000..7a59274
--- /dev/null
@@ -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/pvr/services4/include/sgxinfo.h b/pvr/services4/include/sgxinfo.h
new file mode 100644 (file)
index 0000000..2e85b61
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c b/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
new file mode 100644 (file)
index 0000000..8e7876a
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h b/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
new file mode 100644 (file)
index 0000000..9d03a24
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/bridged_support.c b/pvr/services4/srvkm/bridged/bridged_support.c
new file mode 100644 (file)
index 0000000..b82231a
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/bridged_support.h b/pvr/services4/srvkm/bridged/bridged_support.h
new file mode 100644 (file)
index 0000000..b5c2d15
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
new file mode 100644 (file)
index 0000000..de4e697
--- /dev/null
@@ -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/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
new file mode 100644 (file)
index 0000000..ba2a3c8
--- /dev/null
@@ -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/pvr/services4/srvkm/common/buffer_manager.c b/pvr/services4/srvkm/common/buffer_manager.c
new file mode 100644 (file)
index 0000000..ecb5d03
--- /dev/null
@@ -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/pvr/services4/srvkm/common/deviceclass.c b/pvr/services4/srvkm/common/deviceclass.c
new file mode 100644 (file)
index 0000000..2867a08
--- /dev/null
@@ -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/pvr/services4/srvkm/common/devicemem.c b/pvr/services4/srvkm/common/devicemem.c
new file mode 100644 (file)
index 0000000..0d5d2da
--- /dev/null
@@ -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/pvr/services4/srvkm/common/handle.c b/pvr/services4/srvkm/common/handle.c
new file mode 100644 (file)
index 0000000..bfbd6b3
--- /dev/null
@@ -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/pvr/services4/srvkm/common/hash.c b/pvr/services4/srvkm/common/hash.c
new file mode 100644 (file)
index 0000000..981702b
--- /dev/null
@@ -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/pvr/services4/srvkm/common/lists.c b/pvr/services4/srvkm/common/lists.c
new file mode 100644 (file)
index 0000000..1d7602a
--- /dev/null
@@ -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/pvr/services4/srvkm/common/mem.c b/pvr/services4/srvkm/common/mem.c
new file mode 100644 (file)
index 0000000..0dd99db
--- /dev/null
@@ -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/pvr/services4/srvkm/common/mem_debug.c b/pvr/services4/srvkm/common/mem_debug.c
new file mode 100644 (file)
index 0000000..e9ae968
--- /dev/null
@@ -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/pvr/services4/srvkm/common/metrics.c b/pvr/services4/srvkm/common/metrics.c
new file mode 100644 (file)
index 0000000..c1df322
--- /dev/null
@@ -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/pvr/services4/srvkm/common/pdump_common.c b/pvr/services4/srvkm/common/pdump_common.c
new file mode 100644 (file)
index 0000000..518a583
--- /dev/null
@@ -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/pvr/services4/srvkm/common/perproc.c b/pvr/services4/srvkm/common/perproc.c
new file mode 100644 (file)
index 0000000..64e8faf
--- /dev/null
@@ -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/pvr/services4/srvkm/common/power.c b/pvr/services4/srvkm/common/power.c
new file mode 100644 (file)
index 0000000..b5b8585
--- /dev/null
@@ -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/pvr/services4/srvkm/common/pvrsrv.c b/pvr/services4/srvkm/common/pvrsrv.c
new file mode 100644 (file)
index 0000000..82cc4dd
--- /dev/null
@@ -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/pvr/services4/srvkm/common/queue.c b/pvr/services4/srvkm/common/queue.c
new file mode 100644 (file)
index 0000000..d16ab6d
--- /dev/null
@@ -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/pvr/services4/srvkm/common/ra.c b/pvr/services4/srvkm/common/ra.c
new file mode 100644 (file)
index 0000000..c2f7fb5
--- /dev/null
@@ -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/pvr/services4/srvkm/common/resman.c b/pvr/services4/srvkm/common/resman.c
new file mode 100644 (file)
index 0000000..14b16fe
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/mmu.c b/pvr/services4/srvkm/devices/sgx/mmu.c
new file mode 100644 (file)
index 0000000..ad24b6f
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/mmu.h b/pvr/services4/srvkm/devices/sgx/mmu.h
new file mode 100644 (file)
index 0000000..287d4f3
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/pb.c b/pvr/services4/srvkm/devices/sgx/pb.c
new file mode 100644 (file)
index 0000000..93f356d
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h b/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
new file mode 100644 (file)
index 0000000..bfc726f
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxconfig.h b/pvr/services4/srvkm/devices/sgx/sgxconfig.h
new file mode 100644 (file)
index 0000000..58415d8
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxinfokm.h b/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
new file mode 100644 (file)
index 0000000..b4fd589
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxinit.c b/pvr/services4/srvkm/devices/sgx/sgxinit.c
new file mode 100644 (file)
index 0000000..45c16dc
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxkick.c b/pvr/services4/srvkm/devices/sgx/sgxkick.c
new file mode 100644 (file)
index 0000000..575ca69
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxpower.c b/pvr/services4/srvkm/devices/sgx/sgxpower.c
new file mode 100644 (file)
index 0000000..af4d52a
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxreset.c b/pvr/services4/srvkm/devices/sgx/sgxreset.c
new file mode 100644 (file)
index 0000000..a746b88
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxtransfer.c b/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
new file mode 100644 (file)
index 0000000..9899f92
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxutils.c b/pvr/services4/srvkm/devices/sgx/sgxutils.c
new file mode 100644 (file)
index 0000000..8ffa3fa
--- /dev/null
@@ -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/pvr/services4/srvkm/devices/sgx/sgxutils.h b/pvr/services4/srvkm/devices/sgx/sgxutils.h
new file mode 100644 (file)
index 0000000..ead8d56
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/env_data.h b/pvr/services4/srvkm/env/linux/env_data.h
new file mode 100644 (file)
index 0000000..a16a2fa
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/env_perproc.h b/pvr/services4/srvkm/env/linux/env_perproc.h
new file mode 100644 (file)
index 0000000..c9fbad9
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/event.c b/pvr/services4/srvkm/env/linux/event.c
new file mode 100644 (file)
index 0000000..1a928d1
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/event.h b/pvr/services4/srvkm/env/linux/event.h
new file mode 100644 (file)
index 0000000..908014e
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/kbuild/Makefile b/pvr/services4/srvkm/env/linux/kbuild/Makefile
new file mode 100644 (file)
index 0000000..887689f
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/linkage.h b/pvr/services4/srvkm/env/linux/linkage.h
new file mode 100644 (file)
index 0000000..a124f78
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/lock.h b/pvr/services4/srvkm/env/linux/lock.h
new file mode 100644 (file)
index 0000000..4a18e01
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mm.c b/pvr/services4/srvkm/env/linux/mm.c
new file mode 100644 (file)
index 0000000..8844f0a
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mm.h b/pvr/services4/srvkm/env/linux/mm.h
new file mode 100644 (file)
index 0000000..78f3d14
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mmap.c b/pvr/services4/srvkm/env/linux/mmap.c
new file mode 100644 (file)
index 0000000..a273689
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mmap.h b/pvr/services4/srvkm/env/linux/mmap.h
new file mode 100644 (file)
index 0000000..afc7c94
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/module.c b/pvr/services4/srvkm/env/linux/module.c
new file mode 100644 (file)
index 0000000..0fd336b
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mutex.c b/pvr/services4/srvkm/env/linux/mutex.c
new file mode 100644 (file)
index 0000000..652955a
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mutex.h b/pvr/services4/srvkm/env/linux/mutex.h
new file mode 100644 (file)
index 0000000..894c1c9
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mutils.c b/pvr/services4/srvkm/env/linux/mutils.c
new file mode 100644 (file)
index 0000000..ce010bf
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/mutils.h b/pvr/services4/srvkm/env/linux/mutils.h
new file mode 100644 (file)
index 0000000..625041b
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/osfunc.c b/pvr/services4/srvkm/env/linux/osfunc.c
new file mode 100644 (file)
index 0000000..ba666a9
--- /dev/null
@@ -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(&current->mm->mmap_sem);
+    iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+    up_read(&current->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(&current->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(&current->mm->mmap_sem);
+
+exit_check:
+    CheckPagesContiguous(psInfo);
+
+
+
+    *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+    return PVRSRV_OK;
+
+error_release_mmap_sem:
+    up_read(&current->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/pvr/services4/srvkm/env/linux/osperproc.c b/pvr/services4/srvkm/env/linux/osperproc.c
new file mode 100644 (file)
index 0000000..6126ffd
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/pdump.c b/pvr/services4/srvkm/env/linux/pdump.c
new file mode 100644 (file)
index 0000000..70a8892
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/private_data.h b/pvr/services4/srvkm/env/linux/private_data.h
new file mode 100644 (file)
index 0000000..10a0201
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/proc.c b/pvr/services4/srvkm/env/linux/proc.c
new file mode 100644 (file)
index 0000000..50245a1
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/proc.h b/pvr/services4/srvkm/env/linux/proc.h
new file mode 100644 (file)
index 0000000..37849c2
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
new file mode 100644 (file)
index 0000000..8342891
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/pvr_debug.c b/pvr/services4/srvkm/env/linux/pvr_debug.c
new file mode 100644 (file)
index 0000000..56d1046
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/pvr_drm.c b/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100644 (file)
index 0000000..f31f989
--- /dev/null
@@ -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/pvr/services4/srvkm/env/linux/pvr_drm.h b/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100644 (file)
index 0000000..9f5e931
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgx535defs.h b/pvr/services4/srvkm/hwdefs/sgx535defs.h
new file mode 100644 (file)
index 0000000..4e1c97f
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgx540defs.h b/pvr/services4/srvkm/hwdefs/sgx540defs.h
new file mode 100755 (executable)
index 0000000..92a19f9
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgx545defs.h b/pvr/services4/srvkm/hwdefs/sgx545defs.h
new file mode 100755 (executable)
index 0000000..cad51f5
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgxdefs.h b/pvr/services4/srvkm/hwdefs/sgxdefs.h
new file mode 100644 (file)
index 0000000..c496765
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgxerrata.h b/pvr/services4/srvkm/hwdefs/sgxerrata.h
new file mode 100644 (file)
index 0000000..dee5b43
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h b/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
new file mode 100644 (file)
index 0000000..0672ad6
--- /dev/null
@@ -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/pvr/services4/srvkm/hwdefs/sgxmmu.h b/pvr/services4/srvkm/hwdefs/sgxmmu.h
new file mode 100644 (file)
index 0000000..c6b4c0d
--- /dev/null
@@ -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/pvr/services4/srvkm/include/buffer_manager.h b/pvr/services4/srvkm/include/buffer_manager.h
new file mode 100644 (file)
index 0000000..c792292
--- /dev/null
@@ -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/pvr/services4/srvkm/include/device.h b/pvr/services4/srvkm/include/device.h
new file mode 100644 (file)
index 0000000..c7fa61c
--- /dev/null
@@ -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/pvr/services4/srvkm/include/handle.h b/pvr/services4/srvkm/include/handle.h
new file mode 100644 (file)
index 0000000..ffa952f
--- /dev/null
@@ -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/pvr/services4/srvkm/include/hash.h b/pvr/services4/srvkm/include/hash.h
new file mode 100644 (file)
index 0000000..26c8e44
--- /dev/null
@@ -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/pvr/services4/srvkm/include/lists.h b/pvr/services4/srvkm/include/lists.h
new file mode 100644 (file)
index 0000000..70ef61d
--- /dev/null
@@ -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/pvr/services4/srvkm/include/metrics.h b/pvr/services4/srvkm/include/metrics.h
new file mode 100644 (file)
index 0000000..1ea12de
--- /dev/null
@@ -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/pvr/services4/srvkm/include/osfunc.h b/pvr/services4/srvkm/include/osfunc.h
new file mode 100644 (file)
index 0000000..7a0b064
--- /dev/null
@@ -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/pvr/services4/srvkm/include/osperproc.h b/pvr/services4/srvkm/include/osperproc.h
new file mode 100644 (file)
index 0000000..a23b983
--- /dev/null
@@ -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/pvr/services4/srvkm/include/pdump_km.h b/pvr/services4/srvkm/include/pdump_km.h
new file mode 100644 (file)
index 0000000..31f7aa2
--- /dev/null
@@ -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/pvr/services4/srvkm/include/pdump_osfunc.h b/pvr/services4/srvkm/include/pdump_osfunc.h
new file mode 100644 (file)
index 0000000..eb2197f
--- /dev/null
@@ -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/pvr/services4/srvkm/include/perproc.h b/pvr/services4/srvkm/include/perproc.h
new file mode 100644 (file)
index 0000000..11c1608
--- /dev/null
@@ -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/pvr/services4/srvkm/include/power.h b/pvr/services4/srvkm/include/power.h
new file mode 100644 (file)
index 0000000..1e47736
--- /dev/null
@@ -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/pvr/services4/srvkm/include/queue.h b/pvr/services4/srvkm/include/queue.h
new file mode 100644 (file)
index 0000000..f3e5df6
--- /dev/null
@@ -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/pvr/services4/srvkm/include/ra.h b/pvr/services4/srvkm/include/ra.h
new file mode 100644 (file)
index 0000000..d537601
--- /dev/null
@@ -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/pvr/services4/srvkm/include/resman.h b/pvr/services4/srvkm/include/resman.h
new file mode 100644 (file)
index 0000000..a2c6d02
--- /dev/null
@@ -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/pvr/services4/srvkm/include/services_headers.h b/pvr/services4/srvkm/include/services_headers.h
new file mode 100644 (file)
index 0000000..4f6c2a2
--- /dev/null
@@ -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/pvr/services4/srvkm/include/srvkm.h b/pvr/services4/srvkm/include/srvkm.h
new file mode 100644 (file)
index 0000000..5506992
--- /dev/null
@@ -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/pvr/services4/system/common/sysconfig.c b/pvr/services4/system/common/sysconfig.c
new file mode 100644 (file)
index 0000000..6146806
--- /dev/null
@@ -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/pvr/services4/system/common/sysutils.c b/pvr/services4/system/common/sysutils.c
new file mode 100644 (file)
index 0000000..0e3e7a9
--- /dev/null
@@ -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/pvr/services4/system/include/oemfuncs.h b/pvr/services4/system/include/oemfuncs.h
new file mode 100644 (file)
index 0000000..343e85f
--- /dev/null
@@ -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/pvr/services4/system/include/sys_pvr_drm_shared.h b/pvr/services4/system/include/sys_pvr_drm_shared.h
new file mode 100644 (file)
index 0000000..8ae67dc
--- /dev/null
@@ -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/pvr/services4/system/include/syscommon.h b/pvr/services4/system/include/syscommon.h
new file mode 100644 (file)
index 0000000..d316141
--- /dev/null
@@ -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/pvr/services4/system/include/sysconfig.h b/pvr/services4/system/include/sysconfig.h
new file mode 100644 (file)
index 0000000..56abae7
--- /dev/null
@@ -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/pvr/services4/system/include/sysinfo.h b/pvr/services4/system/include/sysinfo.h
new file mode 100644 (file)
index 0000000..95724d0
--- /dev/null
@@ -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/pvr/services4/system/include/syslocal.h b/pvr/services4/system/include/syslocal.h
new file mode 100644 (file)
index 0000000..59d80da
--- /dev/null
@@ -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/pvr/services4/system/plb/sysconfig.c b/pvr/services4/system/plb/sysconfig.c
new file mode 100644 (file)
index 0000000..ec0222c
--- /dev/null
@@ -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/pvr/services4/system/plb/sysplb.h b/pvr/services4/system/plb/sysplb.h
new file mode 100644 (file)
index 0000000..0f7deff
--- /dev/null
@@ -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/pvr/services4/system/tnc/sysconfig.c b/pvr/services4/system/tnc/sysconfig.c
new file mode 100644 (file)
index 0000000..09e7997
--- /dev/null
@@ -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/pvr/services4/system/tnc/systnc.h b/pvr/services4/system/tnc/systnc.h
new file mode 100644 (file)
index 0000000..5793535
--- /dev/null
@@ -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/pvr/tools/intern/debug/client/linuxsrv.h b/pvr/tools/intern/debug/client/linuxsrv.h
new file mode 100644 (file)
index 0000000..aa43db5
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c b/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
new file mode 100644 (file)
index 0000000..d317957
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h b/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
new file mode 100644 (file)
index 0000000..167e0f6
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h b/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
new file mode 100644 (file)
index 0000000..558d6fa
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/hotkey.c b/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
new file mode 100644 (file)
index 0000000..7ea2b5a
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/hotkey.h b/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
new file mode 100644 (file)
index 0000000..5f95d22
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/ioctl.c b/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
new file mode 100644 (file)
index 0000000..6b130d7
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/common/ioctl.h b/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
new file mode 100644 (file)
index 0000000..882408c
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c b/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
new file mode 100644 (file)
index 0000000..29c3427
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile b/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
new file mode 100644 (file)
index 0000000..44c1357
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/linux/main.c b/pvr/tools/intern/debug/dbgdriv/linux/main.c
new file mode 100644 (file)
index 0000000..08691c0
--- /dev/null
@@ -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/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common b/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
new file mode 100644 (file)
index 0000000..f9a1c7f
--- /dev/null
@@ -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